Enterprise Integration Zone is brought to you in partnership with:

Justin Bozonier is the Product Optimization Specialist at GrubHub formerly Sr. Developer/Analyst at Cheezburger. He's engineered a large, scalable analytics system, worked on actuarial modeling software. As Product Optimization Specialist he is currently leading split test design, implementation, and analysis. The opinions expressed here represent my own and not those of my employer. Justin is a DZone MVB and is not an employee of DZone and has posted 27 posts at DZone. You can read more from them at their website. View Full User Profile

Message Oriented Object Design and James Shore's Challenge

10.29.2012
| 2326 views |
  • submit to reddit
James Shore posted an architectural challenge on his blog and personally threw his gauntlet in my face to answer the challenge using this message oriented design stuff I'd been ranting and raving about. Of course when I say "threw his gauntlet in my face" I really mean he said it might be interesting to see...but still! A man can't back down from that! Here's how I answered the challenge.

 

You can read about his challenge in detail here: http://jamesshore.com/Blog/Architectural-Design-Challenge.html   To sum it up, the idea is to build a ROT13 file encoder, TDD'd and beautiful. There were two parts to his challenge. The first was just to get everything done by reading the whole file into memory. Then he wanted us to refine our design around this idea. Once that was done we could move onto to part two of the challenge which required us to process the file as we load it off of disk and save it back to disk incrementally.   What did I learn from this experience? I'm extremely happy with the flexibility and robustness of the designs I get when I approach things from a message oriented point of view. There are times where it's too much (there are no absolutes laws right?) but for any system I work on of any actual complexity, it is a great guiding hand for me.   This is my final solution: http://github.com/jcbozonier/The-Jim-Shore-Architecture-Challenge   To get a general idea of what I did I've provided the way I connected my objects together below: 
public class ROT13EncodingFileWriter
{
    public static void Do(ITextHandOff guiWriter, string fromFile, string toFile)
    {
        var configuration = new FileSystemConfiguration();
        var encoder = new ROT13Encoding();
        var fileReader = new OneLineAtATimeFileReader();
        var fileWriter = new OneLineAtATimeFileWriter();
        var encodedTextSubscribers = new[]
                                         {
                                             guiWriter,
                                             fileWriter
                                         }.CreateMultiObserver();

        configuration.SetFileReaderToConfigure(fileReader);
        configuration.SetFileWriterToConfigure(fileWriter);
        fileReader.OnNewTextAvailableNotify(encoder);
        encoder.OnNewEncodedTextAvailableNotify(encodedTextSubscribers);

        configuration.Configure();

        fileReader.SetFilePath(fromFile);
        fileWriter.SetFilePath(toFile);

        fileReader.Read();
    }
}
First my mistakes:   1) This part is confusing. I'm basically just creating an object that will forward every message it receives to both other objects but it isn't executed well: 
var encodedTextSubscribers = new[]
{
   guiWriter,
   fileWriter
}.CreateMultiObserver();
2) Instead of having a separate configuration command, the things I wanted configured, should have just been configured on the fly. Setting them to be configured and then calling for configuration to occur seems way too meh. 
configuration.SetFileReaderToConfigure(fileReader);
configuration.SetFileWriterToConfigure(fileWriter);
...
configuration.Configure();
3) The line where I call out fileReader.Read(); is where the whole system comes to life but I fear that's not obvious.   Now what I like:   1) Whenever I create a message oriented design, I can discuss the whole system by pointing to the place where I configure my dependencies. The overall system flow may not be perfectly digestable but if one were to try to create a flow chart from this configuration they would find it very easy (I have and it lends itself well to presentations ;)  ). Another thing is, instead of needing a call graph that shows how objects talk to one another, the same ideas fall out of the view of how the objects are dependent on one another in my experience.   2) Whenever I run into too much pain with this approach it's a smell I did something wrong. Case in point: While working on part I of the challenge, I had begun to write and test a class that was essentially going to orchestrate all of the other classes together on top of the class which configures which objects talk to one another. Essentially I was building a router. The pain for me was that I was creating WAY too many fakes and needing to care WAY too much about what they were doing. So I took a step back and drew my objects on a piece of paper and then reconnected them per the new design I drew. There were hardly any code changes necessary and it was pretty short work.   3) I tend to write tiny objects. Some people hate having too many objects or objects that don't do much so your tastes may vary. I've found that smaller more focused classes help me however. When they encompass literally only a single responsibility I find them to be easier to replace/modify when they no longer fit my needs and I only need to mock when I absolutely need to.   If you haven't been talking with me or reading what I've been writing about Message Oriented Object Design here's a brief quick summary:   Message Oriented Object Design is an object oriented design philosophy wherein we view objects as sending immutable messages/publishing events on channels. MOOD systems also rely on the configuration of object networks to enable collaboration between them. A core tenet is the lack of inter-object getters (be it method or property calls).   4) I like how little code there is in my console application. 
namespace ConsoleGUI
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var guiWriter = new GuiWriter();

            ROT13EncodingFileWriter.Do(guiWriter, args[0], args[1]);
        }
    }
}
That's it! Leave me a comment if you want to lend your own critique of what I've done. I also encourage you to head over to James' site and throw your own hat in the ring and critique other people's designs (be harder on the other designs though of course!).
  
Published at DZone with permission of Justin Bozonier, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: