Architectural Design Challenge by James Shore : a review

A few weeks ago, James Shore had initiated an architectural design challenge for which I submitted an entry.
Some other people also proposed an implementation. I have listed 4 :

I wanted to review these implementations. I tried to look at them from various perspectives and the exercise was quite interesting.
Here is what I found for 3 of them. I will not talk about James Shore implementation. It could be the topic of a dedicated blog post in the future.

The perspectives that interested me were :

  • the global workflow of commands
  • the coupling between software units
  • the unit testing method

Here we go.


Ralf Westphal : an Event-Based Components approach

Ralf has set-up a web site where he describes his solution. It is composed of lots of simple components assembled as if they were electronic components on a board.
See the nice drawings on Ralf google code website. Here is one :

Communication between components is only event based so the flow of commands follows the flow of events. The config path is pushed to the components that do the reading and the writing. The reader get the data and pushes it to the logic that, in turn, pushes the transformed data to the writer and to the display.

All components are implementations of a public contract. Basically, each public contract describes the pins for soldering the components.
Regarding software coupling,

  • each basic component has no knowledge of any other component
  • each board composed of multiple components has knowledge of the contract implemented by the components that are part of it -- except for the standard components whose instances are created by the board itself.

All basic components are unit tested. The event-style output ensures that the behavior of each component is observable hence testable without any fake, stub or mock.
Though, the absence of unit testing for the "domain board" lead to think that the global design was not test-driven.
But we could probably imagine a top down approach where the "domain board" would have been designed using mocks for its inner parts (reader, writer and transformer).

This component approach was new to me and I find it quite impressive and attractive.
My biggest concern is about scaling : what if a system needs thousands of components? In such a case, can we still use really simple piece of information through the pins?


Justin Bozonier : Message Oriented Object Design

Message Oriented Object Design is quite similar to the previous component based approach in the sense that the flow of commands goes from the initial reader to the final destination going through all needed steps.
This approach features the tell don't ask principle in every piece of software.

The main difference with the component approach is that each object knows the other contracts and directly "tell" the other objects what to do instead of raising an event. The real implementations of the other objects are, of course, unknown.
This leads to a loose coupling where each class only has to know few interfaces.

JustinBozinier.png

Classes are unit tested using stubs behind each interface.

My concern is similar to the previous approach : what about scaling? "tell don't ask" is nice and provide a loosely coupled design but I don't know if this principle can be applied - keeping the same readability level- on programs where the data flow is not so straightforward.


Alexander Beletsky : simple design from requirements to implementation

I have very little to say regarding this approach because I used more or less the same ;-)

Alexander adopts an inside-out design strategy : first the business logic, then moving towards the I/O.
Each design step is unit tested using mocks for verifying the interactions with the components that are not yet present. The mock framework is rhino mocks. It is good that some people like it but, to me, the verifications of Moq are much more readable than the expectations of Rhino Mocks.

The resulting design is mostly loosely coupled with a central business logic component that consumes strings as input and stores strings as output, featuring a bidirectional command flow.

AlexanderBeletsky.png

The only thing that I do not understand is the use of factories. They usually enhance loose coupling but, in this case, they are not really useful.


Conclusion

Actually, I do not have any conclusion except that lots of different approaches can lead to software that satisfy the same needs while following basic good principles (loose coupling, unit testing...)

Alexander Beletsky

Now, thats what I call - great job!

Many thanks for your analisys and sharing this. Regarding the factories. I would agree with you that in this particular case they could be not required, but I just to much get used to use that :)

It was really interesting to review the rest of solutions, so once again - thanks!) keep it up!

Fil des commentaires de ce billet

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.