Middle Man

When a class only offers minimal value and mainly delegates most of its calls to another class.

Sign of Smell

If a class does nothing but just delegate to another class, it is commonly considered a middleman smell. One of the main features of objects is encapsulation, which involves hiding internal details from the outside world. Encapsulation often involves delegation, but it is possible for delegation to become excessive. When examining a class's interface, you may discover that a considerable portion of its methods are solely delegating to another class without any additional functionality.

Originally, the Middle Man smell was introduced into our codebase for good reasons. For instance, certain design patterns, like Proxy or Decorator, intentionally add a middleman as a decoupling pattern. It can also be used to address the Message Chains smell or to avoid dependencies between classes. However, after refactoring or becoming over-zealous, these middlemen may turn into empty shells that only delegate without performing any other meaningful actions.

Reason of Smell

  • Reduced Readability: The presence of a middleman can obscure the direct relationship between the client and the target class. Developers reading the code may need to navigate through the middleman to find the actual implementation, which can increase cognitive load and reduce code readability.

  • Unnecessary Abstraction: In some cases, the Middle Man adds an unnecessary level of abstraction that doesn't align with the system's architecture or design. This abstraction can make the codebase more complex without a corresponding benefit.

  • Violation of "Tell, Don't Ask": The Middle Man often violates the "Tell, Don't Ask" principle. Instead of instructing objects to perform actions, it merely passes requests along, behaving more like a passive messenger than an active participant in the system.

  • Maintenance Overhead: The Middle Man class adds maintenance overhead. Any changes or updates to the interactions between the client and the target class may require corresponding changes in the Middle Man, leading to more effort and complexity in code maintenance.

Refactoring Recipes

  • Remove Middle Man

  • Inline Method

  • Move Method

  • Replace Delegation with Inheritance

Remove Middle Man

If the middleman serves no purpose other than forwarding requests, we can remove it entirely and refactor the client to interact directly with the target class.

Inline Method

If the Middle Man simply delegates all method calls to another class without adding any value, you can eliminate the Middle Man and directly call methods on the target class.

Move Method

If the Middle Man does have some meaningful behavior but not enough to justify its existence, you can move its methods to the client or the target class, depending on where they make more sense.

Replace Delegation with Inheritance

To remove the Middle Man class in your codebase by this skill, we can identify the class it delegates calls to. Create a new subclass that inherits from this target class and overrides the delegated methods. Replace instances of the Middle Man class with instances of the new subclass, updating the references accordingly.

Reference

https://refactoring.guru/smells/middle-man

https://luzkan.github.io/smells/middle-man

https://www.informit.com/articles/article.aspx?p=1400866&seqNum=16

https://refactoring.guru/remove-middle-man

https://refactoring.guru/inline-method

https://refactoring.guru/replace-delegation-with-inheritance

Last updated