Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Some more typos that I overlooked last time.

The road to the right software architecture can be very long. Especially when you're not a professional software architect who helps his customers with developing complex applications day by day.

...

My latest "achievements" are - again - having a deep impact on the big picture of the Oregami application. This summer I finally got some time to get into the topic "Domain Driven Design" (DDD), which Wikipedia describes as an "approach to software development for complex needs by connecting the implementation to an evolving model." You might think "so what?". I read the book "Implementing Domain Driven Design", which enlightened me in more than one way. Many of it's its topics are an obvious perfect match for Oregami devlopmentdevelopment. During the last months, even before I knew about DDD, I found some similar solutions for small aspects of the whole thing myself, which creates a rather good feeling.

But what is "Domain Driven Design" all about in the end? I will try to resume the major parts of DDD as I understand them:

  • Domain experts work very closely together with developers to create a "ubiquitous language" and describe the domain model with that language.
  • The complete business model is not modeled in one big, comprehensive model, but is instead divided into multiple, smaller sub domains ("bounded contexts") according to some special rules.
  • You distinguish between "real" entities and value objects, the latter should be used as much as possible, because they are in many aspects more controllable than entities. This gives you some major technical advantages.
  • Every Bounded Context (BC) consists of exactly one network of entities ("Aggregate") with one main entity which is called "Aggregate Root". If a transaction alters the state of the application, only one aggregate at a time is allowed to be changed. It's not allowed to change more than one aggregate in one transaction.
  • A connection from one BC to another may only reference the aggregate root of that BC. The aggregate root is responsible for all rules of that model. It's not allowed to span rules over several BCs.

During my investigations I also discovered the concept of the so-called "Hexagonal Architecture". Alistair Cockburn writes about it with this essential sentence: "Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases." Wow, that's exactly how software should be: universally useable, easy to expand and easy to test. This architecture concept is sometimes called "Ports and Adapters" or "Onion Architecture", too, starting from the inner application code of the core domain, going through the application service layer to the outer infrastructure, there are no dependencies from the inner to the outer parts. Doing this makes your core code independent of the technical infrastructure, which again leads to better testability (infrastructure "ports" can be swapped easily, e.g. with in-memory variants) and great extensibility (One can add an additional "adapter" to support more clients which use your software, e.g. via ReST or queues).

...

Talking about DDD and hexagonal architectures, you often stumble upon concepts like CQRS and Event Sourcing. Let us begin with Event Sourcing, which describes that the state of every business object is defined by a sequence of events. In practice this means a total rejection of the classic (mostly relational) persistence of data, which directly updates (replaces) the database state with every change. Instead every change of state is triggered by an event. These events are stored in the application, and reading requests are answered by "replaying" the saved events in the same order as they occured. This leads to nothing less then greater scalability and reproducibility of all changes. The latter is exactly what we do need at Oregami with an authoring system where updates to the central domain data (games & co) shall first be reviewed by peers before they are seen as permanent changes. Also suitable for this subject area is the concept of CQRS (Command and Query Responsibility Segregation): all reading access to the application ("queries") is strictly separated from the writing access ("commands"), which has positive influences on scalability. In my mind's eye, I can virtually see Oregami's users sending their input through commands, whose corresponding changes are saved as events. After having been reviewed (we just have to replay the stored events) they can be stored permanently and from now on can be used for all public reading access. This leads us to the user interface of our application: Unlike in our present prototypes, which all use the priciple principle of CRUD, we should better use a "command oriented" user interface, also known as Task based UI. This concept is perfectly suited for commands or tasks from the approaches described above. In our Oregami domain we might think of commands like "Create Game", "Add Release" or "Add Screenshot".

...

For the interested reader here are some of my favorite sources for my inspirations:

...