Middle Man

Description (What)

Middle Man is a class whose sole purpose in existence is to act as an intermediary between two other classes.

How to Locate It (Where)

Look at classes that simply act as a gateway for data to passed between two other classes. Classes that do only delegation work of moving data are generally considered as Middle Mans. Remember that a Middle Man doesn't do anything more than this. If a class looks like a Middle Man but also performs actual work on the data itself like processing, cleaning, converting, it is not a Middle Man.

How It Manifests (Why)

Trying to minimize the Message Chains code smell might end up bringing about this code smell.

It can also occur due to the slow removal of functions of a class to the point where it only delegates work at one stage.

How to Fix It (Possible Treatments)

In Example 1, Remove Middle Man treatment is used which simply means deleting the class that acts as a middle man and rerouting method calls directly to the main class which the middle man was acting as a facade for.

Example 2 is an ignoring case, please see When to Igonore on the page below.

Other treatments are also possible based on the specific scenario, they can be found here

Examples

Example 1

Before:

ProductHandler acts as a middleman to ProductManager by giving it access to only what it needs.

Observed Code Smells:
- Middle Man (lines 55-66)
- Data Class (line 55-66)

After:

Used Remove Middle Man by removing ProductHandler and letting ProductManager directly use Product methods

Refactoring Applied:
- Middle Man
    - Remove Middle Man (removed ProductHandler)
Observed Code Smells After Refactoring:
- None

Example 2

Before:

The class LucyChart is a proxy to gate keeping all the original servicing objects: Draw, Move and Resize.

The class LucyChart is doing little other than delegating all the works to other classes.

The class LucyChart is a 'middle man' in this case.

Observed Code Smells:
-  Middle Man (line 60-91)
  - In this case, the coding follows the proxy pattern, where the 'middle man' code smell can be ignored.

When to Ignore

In cases where a design pattern like the Proxy or Decorator Design Patterns are used

In cases where adding a middle man removes unnecessary interdependence between two classes

More

More about Middle Man

001  import java.util.HashMap;
002  import java.util.Map;
003  
004  class Product {
005   private String name;
006   private String type;
007   private int stock;
008  
009   public Product(String name, String type, int stock) {
010   this.name = name;
011   this.type = type;
012   this.stock = stock;
013   }
014  
015   public String getName() {
016   return name;
017   }
018  
019   public String getType() {
020   return type;
021   }
022  
023   public int getStock() {
024   return this.stock;
025   }
026  
027   public void reduceStock() {
028   this.stock -= 1;
029   }
030  
031  }
032  
033  class ProductHandler {
034   private Product product;
035   private int id;
036  
037   public ProductHandler(Product product, int id) {
038   this.product = product;
039   this.id = id;
040   }
041  
042   public int getStock() {
043   return this.product.getStock();
044   }
045  
046   public String getProductName() {
047   return this.product.getName();
048   }
049  
050   public String getProductType() {
051   return this.product.getType();
052   }
053  
054   public void reduceStock() {
055   this.product.reduceStock();
056   }
057  
058   public void showDetails() {
059   System.out.println("Product Name: " + this.product.getName());
060   System.out.println("Product Type: " + this.product.getType());
061   System.out.println("Stock: " + this.product.getStock());
062   }
063  
064  }
065  
066  class ProductManager {
067   Map<Integer, ProductHandler> productHandlers;
068  
069   public ProductManager() {
070   this.productHandlers = new HashMap<>();
071   }
072  
073   public void addProductHandler(int id, ProductHandler productHandler) {
074   productHandlers.put(id, productHandler);
075   }
076  
077   public void removeProductHandler(int id) {
078   productHandlers.remove(id);
079   }
080  
081   public void showTotalStock() {
082   int totalStock = 0;
083   for (ProductHandler productHandler : productHandlers.values()) {
084   totalStock += productHandler.getStock();
085   }
086   System.out.println("Total Stock: " + totalStock);
087   }
088  
089   public void showAllDetails() {
090   for (ProductHandler productHandler : productHandlers.values()) {
091   productHandler.showDetails();
092   }
093   }
094  
095  }
096  
097  public class MMBE1 {
098  
099   public static void main(String[] args) {
100   Product redsoxcap = new Product("Baseball Cap", "Hat", 10);
101   ProductHandler redsoxcapHandler = new ProductHandler(redsoxcap, 123);
102  
103   Product stanley = new Product("Stanley Cup", "Mug", 15);
104   ProductHandler stanleyHandler = new ProductHandler(stanley, 234);
105  
106   ProductManager pm = new ProductManager();
107   pm.addProduct(1, redsoxcapHandler);
108   pm.addProduct(2, stanleyHandler);
109  
110   pm.showTotalStock();
111   redsoxcapHandler.reduceStock();
112   pm.showTotalStock();
113   }
114  
115  }
116