Monday, January 02, 2012

Setting up a DDD sample app

The guy who started it all is called Emanuele Del Bono. He’s a friend, a nice guy and a respected colleague. He participated in the first Domain-Driven Design class of my company, and also did a fantastic job in finding a suitable place for the class. He is also one of the guys that animated a discussion on the DDD-IT mailing list that urged me to write this posts, some time ago. So I should have been warned about the danger behind his simple request.
Some weeks ago, he complained about the lack of code example in the DDD-IT mailing list, and challenged the list to see if anybody dared to post the code of some aggregate. Innocent and legitimate request, ...or so it seemed. However, since he used the word “courage”, the one that kids use among themselves to do things they will regret, I accepted the challenge and started working on some code that could be shared, and found useful by the list.

Why should I regret it?

As I said, the request is both legitimate and innocent. What could be the drawbacks. I can point out two.

  • Time: I like to do things well, and sometimes I tend to get lost in meaningless details. So, for me, doing things right will take time. Given how busy I am, there’s a clear and present danger of never finishing the stuff.
  • Questions: there are many things that I don’t want to talk about when talking about Domain-Driven Design. Frameworks are one of these. I use some of them, but I can’t really say I love them. However, I don’t like questions like “how do you do this with Spring and Hibernate?” because you can probably do it in a smarter way that I can figure out. I think one of the values of DDD is to provide a conceptual background where these type of problems, decrease their importance to the point of being mere implementation details (even though they can make your time a hell if they don’t work exactly as expected). So my worry is to get too many questions focusing on the wrong side without really clarifying doubts on the part that matters most.
  • Choosing a domain

    I definitely need something different from Cargos. Since I know the training domain a little, and used it also in the recent DDD school camp, I decided to choose this domain. However, as will be clearer later, we’ll need precision in defining what this is really about. Simply knowing how things work in the training domain won’t be enough.

    Choosing a programming language

    Since colleagues were eager for code, the first thing to do was choosing a programming language to actually show some code. The obvious choice was to choose my favorite language and get along with that. Problem number one: I don’t have a favorite language. Problem number two: there are too many things in the code that could divert both writer and readers attention from the actual scope of the task.

  • Java: this has been my first choice, a little conservative I have to admit. However, it’s bee a while since I wrote some java code, and I stopped following Java trends after Oracle’s takeover. Last but not least, all of my local configuration needed an update.
  • Groovy: a lot more pleasant to work with than Java, but to make it really pleasant I had to deconstruct Grails a little, in ways that might look obscure to most readers, carefully selecting only some of the available features. Good topics for a blog post, but not for this app.
  • C#: though I’ve been recently playing with the platform, and I appreciated some features, I still don’t feel like it’s mine. Still too hard for me to distinguish good and bad stuff.
  • Ruby: I am relatively new to the language, and probably missing some key tips on the technology stack and on the programming style (“You still think like a Java guy” Paolo Perrotta once said, I hope I improved a little since then…).
  • Given this starting point, I started with Java. I thought I could set up quickly a skeleton architecture with Spring, like the ones I was used to work with.

    So I opened up the IDE and started coding.

    Wrong choice.

    After setting up an Aggregate an some satellite Services that did their dirty job, or faked it with a mock implementation, I finally realized that I was getting all wrong and was underestimating the task of writing a sample application. What was my problem?

    Ambiguity.

    The model I was building looked perfectly sound from a “modeling” perspective, but I was getting uncomfortable in the multiple roles of developer, analyst, and domain expert or product owner. Moreover, the “let’s show some code quickly” approach that I started with, didn’t really work. To define exactly what my aggregates were supposed to do, I needed a lot more precision, since a little business tweak in the underlying domain would have driven me in divergent modeling choices. I needed consistency and unity of vision in my domain, before I could implement it in my model.

    Well, that was no surprise. That’s exactly what DDD is for. And a common, simplified development cycle is:

    1. gather some information from the domain expert about features A, B and C;
    2. quickly implement it as a domain model, using DDD patterns;
    3. spot contradictions in the current understanding of the domain, that emerge from the model;
    4. refine the model, asking to the domain expert what he precisely meant when he talked about features A, B, and C.

    The only weird thing is that all the roles are in my head now. And to keep my sanity and stop swinging from one interpretation to another one of the same corner of the domain, I need to be a little more structured, and define exactly what I want from myself.

    Providing a little structure


    I want to model my aggregates around a problem, and I want this to be precisely defined. So, despite this being just an example, or maybe exactly for this reason, I can’t go for shortcuts. Let’s start with a user story and see where it lead us. 

    DDD Sample User Story

    My first problem was to find a good name for my role. I mean, my company is rather small, so there’s not much of a clean role separation. I could have put something like “as Me” and was probably going to be more correct, even if less portable.

    However, that’s defining the starting point, and the scope for the first iteration. But it’s not precise enough. Let’s nail it down with an acceptance test.
    Scenario: Publishing a new training
    Given a Catalog
    And a Training gourmet coding not yet published
    When I publish Training gourmet coding on Catalog
    Then Training gourmet coding is available on Catalog


    And try to make it work. Of course this means setting up Cucumber in the development environment, something I thought it wasn’t strictly necessary, but I realized I am getting addicted to.

    By the way, despite my previous experiences with Cucumber and Java, and the precious guidance by the secret ninjas cucumber scrolls, setting up again Cuke4Duke in my project didn’t work that smoothly. Looks like Maven got in the way. Again.

    No, please. Not that again.

    In a second, Maven destroyed my pleasure. And made me think that, even though I am still a rookie on Ruby, every second spent on solving problems on Ruby is a second spent learning, while the time spent on Java is probably wasted. So, after just a few minutes, I already dropped my platform and started again with Ruby, instead of Java. But this sample app is a sandbox, for learning and experimenting. Needs to be fun.

    Modeling question number one


    Do I really need a catalog? When thinking about managing trainings, a Catalog is the abstraction that naturally comes to mind. However when I started thinking about what I really wanted to do with this application, I couldn’t find any behavior for the catalog within the boundaries of my application. I said “boundaries” which means that I need to define scope more precisely. A little context map will do the job.
    Bounded Contexts plus ACLThe ultra-basic context map, with my application and an Anti-Corruption Layer separating it from the external website model


     The main idea, for now, is to manage the trainings locally and trigger a publishing action on an external website. I have no idea about how to do that, but I need to make it clear that I am not directly working on the catalog that is visible to a potential customer. I have an external website for that. Maybe some hosting service exposing APIs would do the job. But I don’t want to know that. Right now I just need to know that I won’t publish directly on that. I’ll hide the details behind some domain service and hide all the little dirty things needed to complete the job behind the curtain of a neat interface. More likely, I’ll pretend to do that, and shamelessly fake everything, but behind the same interface.

    Ruby, the architecture and me


    I hereby state loud and clear my ignorance about the architectural patterns in Ruby. I don’t know much about it, so whenever you see something that doesn’t quite fit the picture or that seems awkward, feel free to comment and correct me. The only thing I am almost sure about is that I don’t want to use Rails. Can’t say it won’t fit in the picture (I am not looking for a 100% DDD application, and I can figure out portions of the application that could be implemented according to that paradigm) but definitely Active Record is not what I want to start with, and definitely I don’t want a full framework stack. I want to add things little by little.

    Persistence framework


    After exploring a little, I’ve chosen Sequel. A lightweight persistence framework that can be used at two different levels of abstraction. I started with the very low level approach, so my repositories now look a little vintage. :-)

    Also DataMapper looked interesting. I’ll probably give it a try when trying to make the architecture a little more agnostic about persistence frameworks.

    The trickiest part so far has been separating persistence instructions from transaction management. In a typical DDD architecture, transaction management is an application layer concern, but this seems to be at odd with most of the examples regarding ORMs and persistence frameworks in general.

    What I like so far


    I really like the Ruby testing stack. Cucumber and Rspec are incredibly well supported by RubyMine, and coding is a pleasure in this area. Getting to all green is always a pleasure.

    What I don’t like so far


    Of course the database had his revenge after that presentation. SQLite rebelled and I wanted to test the app also with some real DMBS, but installing MySQL has been a little pain (well, the actual installation run smoothly ...it just didn’t work with my Ruby version). I had to switch to a different Ruby version and to reinstall it before having it work with my stack.

    There are also a few things that don’t feel right on the architecture. I missed some of the things Spring was doing behind the scenes, and that used to be my default paradigm so there is a high possibility that the whole stuff looks like a Spring based Java application in Ruby dress. Some patterns which are relevant in Java and C# (like Application Facade and Repository) probably have a more elegant alternative implementation in Ruby, and there are some Singletons around (forgive me) which are basically placeholder for a different implementation. In general wiring up is not as elegant as I would haver liked.

    Ok, but where is the code?


    I’ve started a project on GitHub. It’s called D3N. You can find it there. It's still naive, but I’ve tried to do things well and started to post also issues about the things I want to cover/experiment in the next weeks. At the end I am thinking more about a playground than a “sample app” (I hate this term).
    So far, there's not so much to see, but I've been writing a hell of a long post. Let's try to get more use cases implemented and more coverage of the actual evolution. As I said before, there’s a lot more in doing a DDD application than just the resulting code.

    As somebody once said: it’s the journey, not the destination.

    3 comments:

    Marco Paul said...

    very cool. any possibility of porting this to C#?

    Unknown said...

    Hi Marco, ...not really. I think there's plenty of C# examples and I am not enough into C# to provide "examples". My goal is to highlight the process, not the result.

    But the process and the choices are meant to be portable. I mean ...so far this is still a Ruby app written in Java/C# fashion ;-)

    Andre said...

    Nice article! I would be interested how you tweaked the Grails application defaults to better suite (your) DDD demands. Maybe you could elaborate in a separate blog post :-)