SuperAPI AI Directory

breach-encapsulation-naming

Coding & development

View repository

Updated 10-15 22:39

About this skill

Breach Encapsulation Naming

If you create a getter, shout "I'm breaking encapsulation" through its name.

Core Principles

For domain model getters, breachEncapsulationOf Add a prefix to make explicit that encapsulation is being broken.

Approach Characteristics Effect
Normal getter (getName()) Easy to use casually Prone to abuse
Explicit getter (breachEncapsulationOfName()) Awareness of "breaking it" when used Suppresses abuse

Why This Naming Convention Is Needed

Dilemma

  1. Tell Don't Ask Principle: Don't use getters; command the object
  2. Real-world Constraints: Getters are needed for persistence and JSON conversion
  3. Problem: If a getter exists, it ends up being used in business logic too

Solution

By giving getters "long, conspicuous names":

  • Make the developer aware each time it's used that "this is an exceptional use"
  • Make it easier to spot during code review
  • Make it detectable by static analysis tools

Naming Patterns

Basic Form

breachEncapsulationOf<PropertyName>()

Examples by Language

// Java
public String breachEncapsulationOfName() { return this.name; }
public Money breachEncapsulationOfPrice() { return this.price; }
// Kotlin
fun breachEncapsulationOfName(): String = name
fun breachEncapsulationOfPrice(): Money = price
// TypeScript
breachEncapsulationOfName(): string { return this.name; }
breachEncapsulationOfPrice(): Money { return this.price; }
# Python
def breach_encapsulation_of_name(self) -> str:
    return self._name
// Go
func (u *User) BreachEncapsulationOfName() string { return u.name }
// Rust
pub fn breach_encapsulation_of_name(&self) -> &str { &self.name }

Applicability Decision Flow

getterが必要か?
    ↓
├─ NO → getterを作らない(Tell Don't Ask)
│
└─ YES → 対象は?
          │
          ├─ 値オブジェクト → 通常のアクセサでOK
          │   (イミュータブルかつ振る舞いが限定的なため)
          │   例: Money.amount(), UserId.value()
          │
          └─ エンティティ → breachEncapsulationOf を使用
                            │
                            └─ なぜ必要?
                                ├─ 永続化/シリアライズ → ✅ 許容
                                ├─ 表示/UI → ✅ 許容
                                ├─ テスト → ✅ 許容
                                └─ ビジネスロジック → ❌ Tell パターンに変換

Value Objects vs Entities

Type Characteristics Getter Policy
Value Object Immutable, identified by equality Normal accessors allowed (amount(), value())
Entity Mutable, identified by ID breachEncapsulationOf Use

Reason: Since a value object's internal state does not change, even if a getter is exposed, the Ask pattern of "get state → judge externally → update" is unlikely to occur.

Anti-pattern Detection

Warn when the following patterns are found:

// ❌ breachEncapsulationOf + if → Tell Don't Ask違反
if (user.breachEncapsulationOfAge() >= 18) {
    // ロジック
}

// ❌ breachEncapsulationOf + 計算 → ロジックが外部に漏れている
total = item.breachEncapsulationOfPrice() * item.breachEncapsulationOfQuantity();

// ❌ 連鎖呼び出し → デメテルの法則違反
order.breachEncapsulationOfCustomer().breachEncapsulationOfAddress().getCity();

Acceptable Use Cases

1. Persistence Layer (Repository Implementation)

// ✅ 永続化のためのアクセスは許容
public UserEntity toEntity(User user) {
    return new UserEntity(
        user.breachEncapsulationOfId(),
        user.breachEncapsulationOfName(),
        user.breachEncapsulationOfEmail()
    );
}

2. JSON/XML serialization

// ✅ DTOへの変換は許容
toJson(): UserJson {
    return {
        id: this.breachEncapsulationOfId(),
        name: this.breachEncapsulationOfName()
    };
}

3. Assertions in tests

// ✅ テストでの検証は許容
@Test
void shouldChangeName() {
    user.rename("New Name");
    assertEquals("New Name", user.breachEncapsulationOfName());
}

4. Debug/Log Output

# ✅ デバッグ目的は許容
logger.debug(f"User: {user.breach_encapsulation_of_name()}")

Implementation Guidelines

1. Domain Model Side

public class User {
    private final UserId id;
    private String name;
    private Email email;

    // ❌ 通常のgetterは作らない
    // public String getName() { return name; }

    // ✅ カプセル化を破ることを明示
    public String breachEncapsulationOfName() {
        return name;
    }

    // ✅ ビジネスロジックは振る舞いとして提供
    public void rename(String newName) {
        validateName(newName);
        this.name = newName;
    }

    public boolean hasName(String name) {
        return this.name.equals(name);
    }
}

2. Use in the Infrastructure Layer

// リポジトリ実装
public class JpaUserRepository implements UserRepository {
    @Override
    public void save(User user) {
        UserEntity entity = new UserEntity();
        entity.setId(user.breachEncapsulationOfId().value());
        entity.setName(user.breachEncapsulationOfName());
        entity.setEmail(user.breachEncapsulationOfEmail().value());
        jpa.save(entity);
    }
}

Code Review Perspectives

Check Item Response
breachEncapsulationOf + if Suggest conversion to the Tell pattern
breachEncapsulationOf + calculation Move the calculation logic into the object
Use in the domain layer Warn if it is for anything other than persistence/serialization
Chained calls Suggest adding a delegation method
Normal getter (getName()) breachEncapsulationOf Suggest changing to

Integration with Static Analysis

Custom Lint Rule Example

# 検出ルール
1. breachEncapsulationOf の後に if/switch が続く → 警告
2. ドメイン層で breachEncapsulationOf を呼び出している → 警告
3. 通常の get プレフィックスがドメインモデルにある → 警告

Related Skills

Skill Relationship
tell-dont-ask Prerequisite for this skill. Prioritize designs that do not use getters
first-class-collection Apply the same principle to collection encapsulation
domain-building-blocks Consistency with value object design

References

  • Katojun "Getter/Setter for Domain Objects" (2018)

Detailed Guidelines

For detailed implementation patterns by language, refer to references/patterns.md .

Related Skills (Recommended for Concurrent Reading)

When using this skill, also refer to the following skills:

  • tell-dont-ask: Foundational principles for why getters should be avoided
  • law-of-demeter: Structural principles that getter chaining violates
  • first-class-collection: Collection encapsulation patterns