I have a MessageHandler class which receives and validates messages before determining which components in the architecture they should be delegated to so they can be processed. This involves calling functions with different names and possibly different signatures on classes in different components.
What is the best way to implement the delegation?
The diagram below shows two possible approaches.
Option 1 – each component that must process messages exposes an interface, which is realised by a Facade. For each message, the MessageHandler calls the appropriate operation on the interface and the facade delegates it to the appropriate class internally.
Option 2 – for each message, the MessageHandler calls the appropriate operation directly in the relevant component.
Weighing up the advantages/disadvantages of each:
Option 2 means polluting the message handler with a handle of each class in every component that will process a message. It also makes it harder to test the message handler in isolation. Doesn’t seem right.
Option 1 – seems like a better approach. The message handler depends on an interface rather than concrete classes, which also makes it easier to test.
I’m wondering if option 1 a good approach? Or is there a better way to achieve what I want?
4
I’m guessing the image represents both approaches at the same time.
I think approach 1 is the obvios winner and the beneficts of programming against interfaces are well documented.
I would ask, nonetheless:
- Are you sure there’s no commonality between the classes behind the facadem so all of them could implement the same interface?
If MessageHandler
is able to do all its calls using an interface to the facade, how is that not every class behind the facade can’t implement the same interface. It seems to me that they are not getting any more info from MessageHandler
than that interface allows.
12
An interface implemented by only one class gains you nothing in this situation. Will the interfaces ever be implemented by more than one class? If not, you have substituted a dependency for a concrete class, for a dependency on an interface implemented by one concrete class, which adds complexity and no advantage, unless the testing framework must use interfaces.
2