2

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?

enter image description here

ksl
  • 121
  • 2
  • If message_X contains 2 data fields and message_Y contains 3 data fields, who is responsible for getting those data fields out of the messages? Is that the MessageHandler or the class that actually processes the message? – Bart van Ingen Schenau Mar 04 '15 at 14:31
  • @BartvanIngenSchenau That would be the message handler. – ksl Mar 04 '15 at 15:37
  • I am not sure the interface is relevant here. You just need a match between the caller and the callee. An interface is one way to do it in a strongly typed language, but not necessarily the simplest way (classes are another way). – Frank Hileman Mar 04 '15 at 16:12
  • Option 1 because of the separation of responsibilities. Those responsibilities being message aggregation and message dispatch. – mortalapeman Mar 04 '15 at 16:57

2 Answers2

1

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.

Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
  • Yes, the image shows both approaches. – ksl Mar 04 '15 at 15:38
  • If all the classes behind the facade implemented the same interface, that would mean the message handler would need a handle to each one. Which is effectively what the other option is (just without the interface). Or am I missing something? – ksl Mar 04 '15 at 15:40
  • What do you mean by _"a handle"_? – Tulains Córdova Mar 04 '15 at 15:42
  • @user61852 I think he means an explicit reference to the instance of each potential message receiver. I agree that option 1 is the clear winner, but not because it is programming against an interface. The message handler gather messages, the façade (or dispatcher as I like to call this pattern) is responsible for knowing where messages need to go. It is the separation of responsibilities that is important in option 1. – mortalapeman Mar 04 '15 at 16:55
  • @user61852 By handle I mean a reference or a pointer. – ksl Mar 04 '15 at 16:59
  • @mortalapeman The facade only knows which class in a given component to dispatch a message to. Would it make a difference if there are several components that the message handler needs to dispatch messages to? – ksl Mar 04 '15 at 17:01
  • @ksl For most problems, I would expect a single system wide message handler (or aggregator) to handle all inbound traffic. I would expect a single façade per message handler to dispatch all inbound traffic to their correct destinations and in the correct order. Unless the messages you are working with span several problem domains, I would not deviate from this design. – mortalapeman Mar 04 '15 at 19:06
  • @mortalapeman The handler doesn't need a reference of any concrete class, just instances of the interface type. The patterns _"Chain of responsability"_ or _"Estrategy"_ could be used to handle forward the requests. – Tulains Córdova Mar 04 '15 at 19:15
  • @user61852 Agreed, I just wanted to point out that the benefits of option 1 are not just the common interface. – mortalapeman Mar 04 '15 at 19:22
  • @mortalapeman Where is the facade in your example? In the same component as the message handler? If so, what you appear to be describing is effectively option 2 - i.e where messages are dispatched to concrete classes rather than interfaces. – ksl Mar 05 '15 at 20:57
  • @ksl That's what static factories are for. So you don't have to instantiate concrete types. – Tulains Córdova Mar 06 '15 at 12:31
  • There is no advantage in programming against an interface, unless you need the interface for some reason... We could substitute any other abstraction type for "interface" and the logic would be the same. – Frank Hileman Mar 07 '15 at 01:26
1

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.

Frank Hileman
  • 3,922
  • 16
  • 18
  • Perhaps the interfaces won't ever be implemented by more than one class. But doesn't having an interface make testing easier? – ksl Mar 05 '15 at 20:59
  • @ksl It depends on the testing framework, and what you consider a "unit" when you do unit testing. – Frank Hileman Mar 07 '15 at 01:25