Inappropriate Intimacy (General Form)


Inappropriate Intimacy (General Form)

Symptoms

  • One class accesses internal (should-be-private) parts of another class. (There is a related form of Inappropriate Intimacy between a subclass and its parents; see "Inappropriate Intimacy [Subclass Form]," Chapter 9.)

Causes

The two classes probably became intertwined a little at a time. By the time you realize there's a problem, they're coupled . There may be a missing class that should mediate between them. This problem is more serious between unrelated classes than between a parent and child.

What to Do

  • If two independent classes are entangled, use Move Method and Move Field to put the right pieces on the right class.

  • If the tangled part seems to be a missing class, use Extract Class and Hide Delegate to introduce the new class.

  • If classes point to each other, use Change Bidirectional Reference to Unidirectional to turn it into a one-way dependency.

  • If a subclass is too coupled to its parent (as explained in "Inappropriate Intimacy [Subclass Form]," Chapter 9)

    • If the subclass is accessing the parent's fields in an uncontrolled way, use Self Encapsulate Field.

    • If the parent can define a general algorithm that the children can plug into, then use Form Template Method.

    • If the parent and child need to be even more decoupled, then Replace Inheritance with Delegation .

Payoff

Reduces duplication. Often improves communication. May reduce size.

Contraindications

None identified.


Message Chains

Symptoms

  • You see calls of the form:

     a.b().c().d() 

    (This may happen directly or through intermediate results.)

Causes

An object must cooperate with other objects to get things done, and that is OK; the problem is that this couples both the objects and the path to get to them. This sort of coupling goes against two maxims of object-oriented programming: Tell, Don't Ask and the Law of Demeter . Tell, Don't Ask says that, instead of asking for objects so that you can manipulate them, you simply tell them to do the manipulation for you. It's phrased even more clearly in the Law of Demeter: A method shouldn't talk to strangers; that is, it should talk only to itself, its arguments, its own fields, or the objects it creates. (Andrew Hunt and David Thomas's The Pragmatic Programmer describes both of these rules in more detail.)

What to Do

  • If the manipulations actually belong on the target object (the one at the end of the chain), use Extract Method and Move Method to put them there.

  • Use Hide Delegate to make the method depend on one object only. (So, rather than a.b().c().d() , put a d() method on the a object. That may require adding a d() method to the b() and c() objects as well.)

Payoff

May reduce or expose duplication.

Contraindications

This is a trade-off refactoring. If you apply Hide Delegate too much, you get to the point where everything's so busy delegating that nothing seems to be doing any actual work. Sometimes, it's just easier and less confusing to call a small chain.


Middle Man

Symptoms

  • Most methods of a class call the same or a similar method on another object:

     f() {delegate.f();} 

    (A class that mostly delegates its work is known as a middle man .)

Causes

For one thing, this can result from applying Hide Delegate to address Message Chains. Perhaps other features have moved out since then, and you're left with mostly delegating methods.

What to Do

  • In general, Remove Middle Man by having the client call the delegate directly.

  • If the delegate is owned by the middle man or is immutable, and the middle man has behavior to add, and the middle man can be seen as an example of the delegate, you might Replace Delegation with Inheritance .

Payoff

Reduces size. May improve communication.

Contraindications

  • Some patterns (e.g., Proxy or Decorator) intentionally create delegates. Don't remove a Middle Man that's there for a reason.

  • Middle Man and Message Chain trade off against each other.

  • Delegates provide a sort of fa §ade, letting a caller remain unaware of details of messages and structures. Removing a Middle Man can expose clients to more information than they should know.