DDD Europe Conference Report - part II

Posted on by Matthias Noback

In a previous post I discussed some of the talks I attended at the DDD Europe conference in Amsterdam. This conference has offered a lot more amazing content and I'd like to continue to tell you about it.

Lately I've been thinking about why Domain-Driven Design (DDD) has such a great attractive force on me. In particular when at the same time I'm strongly attracted by technology like Docker and its surrounding ecosystem of tools that are finally helping us to fulfill the ideal of continuous delivery, with relative ease. Configuring servers, deploying them, connecting them, etc. is what we previously would have called "operations" work. Now that developers themselves get to do more and more operations work, a movement was called to life: devops, where two previously separated responsibilities are merged into one: writing software and running it in production is part of the same, single task: shipping working software.

Domain-Driven Design shows a certain symmetry with the devops movement. DDD is to be considered a movement too. Aside from all the technical advice we get from it, which is the easiest to focus on for us developers, the main message is more like an encouragement, a call to action for the group of developers as a whole: immerse yourself in the business domain. Know the people and try to understand what their work is about. You don't need to be a domain expert yourself, but you need to talk to the people who are. Only then will you be able to create meaningful software, that isn't just great with respect to the technical aspects, but contributes to the success of the organization you've created it for. It should help them accomplish things they are not able to accomplish with a spreadsheet and a telephone alone.

Looking back at my own career as a software developer I can see that for many years my focus has solely been on technical excellence. I remember my girlfriend asking me several years ago: "But don't you care about the users of your software?" I answered: "No, as long as I can work on solving interesting technical problems!" This attitude is by far not sufficient, and learning about DDD has been a real wake-up call for me. Software development isn't about design patterns, or knowing all about your programming language or framework of choice. It's about delivering proven-to-work software that is meaningful to a group of people and helps them accomplish extraordinary things. I'm not saying you shouldn't learn all you can about the tools you're working with. It just shouldn't be your sole point of focus.

Nick Tune: Aligning Organisational & Technical Boundaries for Team Autonomy

Although I was aware that all the talks were being recorded, I usually get the most out of a conference by simply attending a talk and think it through. It's much less likely for this mental process to occur while I'm watching a talk at home, it just doesn't come with the same kind of special focus I have in a conference room, if I sit down to watch a video at all...

Another interesting talk I attended was one by Nick Tune, whose style of presentation I really love - and so did the entire audience I think. In previous talks I saw by Nick it became very clear that DDD is the perfect area for him to be operating in. As a developer he has a strong awareness of the business world surrounding him (us).

He started out with a call to action: to not wait for management to fix issues you recognize with a software system. Instead, we don't need to seperate between technical and management issues, since they are tied to each other and often amount to the same underlying problem. An important take-away from this talk to me was that instead of taking refuge in a chapter in "the blue book" or something, you should also consider more mundane solutions, like redistributing the work, relocating teams, or relieving the workload of a team in order to speed up partnerships between teams.

If you have some DDD background, you already know that DDD offers us the idea of a bounded context to help us separate our system into multiple different services, each with their own domain model. Finding the right boundaries for such a context is the hardest part of course. Accoring to Nick (quoting Udi Dahan), there are no rules for determining service boundaries. The main heuristic for determining the correct course though, is that every decision with regard to the boundaries should help the organization towards achieving its goal.

In practice, the best thing you can do is strive for autonomy. Hence Nick's suggestion to let go of "microservices" or "bounded contexts" and fight about if you got them right, but focus on "autonomy contexts". We should align our services in the way that reduces the lead time to positive business impact, and having autonomous teams working in autonomous contexts, thereby reducing the number of dependencies, is the best way to do so.

Though there are no rules (of course), Nick offers several heuristics that may be worth mentioning here:

  • Look for contextual language. Language that you will only find to be used in certain contexts; you can put boundaries around those contexts (thereby even allowing the contextual language to be further developed).
  • Data uniqueness. You can look for places where certain data naturally resides and put the context boundaries around that data.
  • Exclusive domain experts. If there are multiple subdomains in play and each of them come with their own domain experts, this might reveal where context boundaries can be placed.
  • Business process steps. When the business process gets divided in several natural phases, they can often be separated by context boundaries.
  • Existing team boundaries. A more conservative option: find out how the teams are currently being divided. If that works well and teams are pretty autonomous already, the boundaries may already be in place.
  • Bottlenecks. If things aren't working well between teams (they have to wait for each other, they ruin another team's life), those are bottlenecks and resolving them may lead you to better context boundaries.

Whatever you decide, don't go for the theoretically ideal solution (like aligning bounded contexts with subdomains), but for the solution that improves customer responsiveness.

Udi Dahan: If (domain logic) then CQRS, or Saga?

I'd never seen Udi Dahan speak, but now I know it's the right thing to do. Speaking is natural for him, and his talk's journey from start to end, making a very interesting point, was impeccable.

The main point was that even when we have familiarized ourselves with domain events and state being like a snapshot, we still rely on current state to protect domain invariants in a very short-sighted fashion. The simple example around which the talk revolves is that of a product getting added to a basket. Between the moment of looking into the details of a product and clicking "add to cart", there is a small chance that the product itself has been deleted, or has been sold out. So we add if-statements in our code to verify that adding the product to the cart is still a valid thing to do. We hereby think that we successfully implement the "domain invariant" that "you can only add existing products to a cart, and only those that aren't sold out".

Udi calls the scenario a race condition, which hints to the fact that the domain of e-shopping is in fact a collaborative domain. This calls for a more careful approach. Even more things can go wrong: what happens if a product becomes unavailable for sale after it was added to the shopping cart? Udi warns us to always be prepared to loose.

We have gotten ourselves into trouble by verifying domain invariants using simple if-statements. But whether or not the answer of the expression is yes or no depends on at which point in time you ask it. Since the example domain is a collaborative one, we should (one of Udi's heuristics) choose CQRS as an implementation pattern anway. And with it comes the rule that commands don't fail.

Instead of trying to cover every failure scenario in our application services, we should be prepared to loose after we've handled the command. This is in fact another case of eventual consistency. We often use that term in a technical context to describe that the state of our domain objects is not immediately consistent across the entire system. Here it means that our application can't have total knowledge of everything that's happening in the real world and that instead it should be able to keep up with those events. An example would be: when a user has a product in their basket which gets sold out, the product will be removed from the basket and the user gets a nice message about it. Or maybe taking a product out of sale is something that could happen within a certain timeframe, instead of immediately, allowing customers to finish their order.

I found this a very interesting talk, and I'm certain that this will change my perspective on domain invariants and how to enforce them in code.

Conclusion

This concludes my report of day 1 of DDD Europe. I still have more to say about what came by on the second day. Not sure when I'll come around to publishing that post though...

DDD conference report Comments

DDD Europe Conference Report - part I

Posted on by Matthias Noback

I'm currently attending the DDD Europe conference in Amsterdam and thought it might be interesting for people at home to read up on some of the topics that this interesting (and well-organized) conference covers.

Mel Conway: Consider the development feedback loop

On Twitter there were outbursts of "The legend on stage" and "This is the Conway of 'Conway's Law'" when Mel Conway entered the stage. I knew about the law, which amounts to the observation that software systems tend to be shaped by the way the teams working on it communicate.

I had already tried to apply Conway's Law to the software products of the teams I've worked with in the past. Most certainly, it was an interesting exercise, one which has also led me to believe that we should be more pro-active about Conway's Law, which is actually more like a "Conway's Problem": we should fix it by shaping our teams and interactions in such a way that we can make better software. Something like this is already known as the "Reverse Conway's Law", by the way.

To be honest, my high expectations weren't met by the real talk. It felt somewhat irrelevant. There were some interesting ideas in it though:

  • Sofware is becoming so important that everyone should have an idea of what's going on inside - it can't be all magic anymore.
  • We need a better feedback loop for software development. We might be able to leverage the age-old feedback loop between hand, eye and brain.

An interesting corollary to the original law, introduced by Mel in his talk, is: stable interfaces allow groups to work together without having knowledge of each other's work. This is a highly relevant rule for teams working on the same overall system, with a need to get "unstuck". An example of this came from a demonstration of "visual programming with a Windows 3 Smalltalk application running on Windows XP in compatible mode inside a Virtual Machine on Mac" (I would have loved to see an entire talk on this by the way). Mel demonstrated how several larger components can be connected easily when the designer of the application defines several standardized interfaces through which different parts of the application connect.

Further reading: Mel's paper on simplifying the development process

Jérémie Chassaing: Thermodynamics of Software

The next talk I attended was an experimental talk (#NoSlides, and on short notice) by Jérémie Chassaing. I liked his style; I admire the kind of free form it had, something I haven't dared to try myself...

His talk built on the work of Carlo Pescio, mainly his ideas on the Physics of Software. Its endeavours are to discover and influence the forces that are working on software, either in the artifact space (the code, amongst other things) as well as the runtime space (the running application, amongst other things).

The notion of friction is interesting in this context. As is apparent in a lot of development teams, some aspects of a software product are easier to change than others. It can be easier to move the team in one direction, and harder to move in the opposite direction.

Several examples of friction in a DDD world: when you don't align your solution space (e.g. bounded context) with your user's problem space (e.g. subdomain), it will be hard to make your domain model follow along with changes in the domain that happen in the real world. The same goes for aggregates: if you get their boundaries "wrong", then they will work against you, making consistency hard to achieve, or giving you a false sense of consistency.

Friction can be leveraged too, when, for example, you don't want your team to move in a certain direction. For example, if you don't want to let your team change code without verifying that the unit tests still pass, let them install a pre-commit hook. I've applied this technique in my open source projects too. For example while designing the SimpleBus command bus library, I decided that command handlers wouldn't be allowed to have a return value. Not that it may never be useful to have a return value, I just wanted to make it really hard to rely in some way on the result of a "command" action.

Vaughn Vernon: The Language of Actors

Next up was a talk by Vaughn Vernon on the actor model. Having attended several other talks on this topic, it didn't bring me lot of new insights. The main idea is: actors are just like objects, except - when they call each other, the call is modelled as a message, which gets added to the queue of the other object, waiting to be processed in a non-blocking fashion. Again and again I must admit that I find this a fascinating concept. Asynchronous communication is the conceptual solution to a lot of real-world problems. Problems for which we currently have lots of shaky solutions in place, like synchronous (blocking) network calls, multi-threaded applications, database transactions, or centralized message brokers.

According to Vaughn, an actor system gives you a "simplicity stack", as opposed to the "complexity stack" many of us are currently working with (i.e. a layered architecture, with ports & adapters). I do "believe" in the actor model, I don't think it solves all of those problems though.

I'll take it from Vaughn that we should "embrace latency". We should be more and more ready for distributed work, across networks too. We should reduce the amount of state in our applications to a maximum level, mimicking a functional approach to modelling.

All of this will allow us to fulfill one of DDD's ideals too: to develop a Ubiquitous Language in a Bounded Context.

To be continued

I've had a great "first day" at DDD Europe. In another post I'll talk about several of the other talks I've attended. By the way, all the talks have been filmed and will be available online at some point.

DDD conference report Comments

Introducing the ConvenientImmutability package

Posted on by Matthias Noback

As was the case with the SymfonyConsoleForm library, I realized I had not taken the time to properly introduce another library I created some time ago: ConvenientImmutability. This one is a lot simpler, but from a technical standpoint I think it might be interesting to at least talk a bit about the considerations that went into it.

For starters, it's important to keep in mind that I don't think you'll actually need to use this library. Of course, I'll explain why. But first: what is ConvenientImmutability about?

In early 2016 I took a Java programming course. At some point they explained the concept of a final property. As Wikipedia puts it:

A final variable can only be initialized once [...]. It does not need to be initialized at the point of declaration: this is called a "blank final" variable.

Marking a property as final is really useful. It shows that, after some initial value has been assigned to it, it is not going to change again. In smarter-sounding words: such a variable becomes immutable. As you may know, using immutable values (maybe we shouldn't call them variables anymore) leads to code that's easier to understand and has less state-related bugs. It also brings us closer to writing pure functions that never modify existing values, only return new ones. Such functions, too, are easier to work with than their imperative counterparts, which change the value of variables all over the place (possibly even global ones) whenever they feel like it.

Defining final properties in PHP

Anyway, this is not a post about the merits of a functional programming style, this is about achieving "final properties" in PHP.

Of course, in PHP we can change the value of any property:

class SomeClass
{
    public $property;
}

$object = new SomeClass();

$object->property = 'some value';

// Re-assignment is not a problem
$object->property = 'some other value';

In fact, the property doesn't even need to be defined as a class attribute, you can just set it if you like:

// This will create a property on-the-fly:
$object->undefinedProperty = '...';

The magic __set() method

We'd like to be able to inject some code, right before a re-assignment, that warns the user: "you can't reassign this property". If we don't want to rely on code generation and auto-loader hijacking, there's nothing we can do, except … implement a "magic" __set() method:

class SomeClass
{
    /**
     * @param string $name The name of the property to set
     * @param mixed $value The value to assign to that property
     */
    public function __set($name, $value) {
        // if property "$name" has been assigned already: 
        //     throw an exception

        // else:
        //     store the value in some internal map
    }
}
$object->property = 'some value';

// Re-assignment throws an exception:
$object->property = 'some other value';

The main problem is: __set() will only be called when the user tries to set a property that hasn't been defined as a class attribute. But we really need to make this work for properties that have been defined as class attributes.

Unsetting class attributes

Searching for a solution, I remembered that it was indeed possible to make PHP ignore defined attributes by unset-ting object properties (don't know where I learned this by the way):

class SomeClass
{
    // We can first define the attribute:
    public $property;

    public function __construct() {
        // Then unset it:
        unset($this->property);
    }

    public function __set($name, $value) {
        // ...
    }
}

$object = new SomeClass();

// This will trigger __set()
$object->property = 'some value';

We have the key to the solution, but we need several more ingredients:

  • The value passed to __set() should be kept safe inside a map (which can be an associative array).
  • It should be possible to retrieve the value from the pseudo-property. This can be achieved by implementing __set()'s counterpart: __get().
  • As a bonus we could also prevent the abuse of properties that are not defined, e.g. throw an exception when a user tries to assign a value to $object->undefinedProperty.

Completing the list of requirements

Of course, this should become a fully automated solution. We don't want to unset a list of hard-code properties.

Some other design goals I came up with:

  • The solution should use a trait instead of an abstract base class, to prevent the solution from taking over the inheritance tree the user has imagined for an object.
  • The solution should be designed to work well with DTOs. For regular objects, encapsulation of state is already a concern of many developers. For DTOs (i.e. objects with no behavior, only data) not so much.
  • It would be particularly nice if the solution works well with the Symfony Form component as it would allow us to have — for example — immutable command objects that can still be populated by the mutable-by-default property-mapping mechanism of the Form component.

The final solution (no pun intended)

It took some lines of code and some testing to make the solution generic, but take a look at the Immutable trait and you'll find all the ingredients mentioned above in that code.

Closing remarks

As I mention in the project's README, using this trait might help you overcome your fear of using public properties for DTOs. It would help you protect objects from being mutable (at least at the first line of defense, you could always store mutable objects in properties of a — thereby — semi-immutable object.

Since this may be more of a psychological thing, related to your mind's attachment to a certain state of the world, you may not be helped much by using this library. Still, it might be nice to know how it works.

PHP functional programming immutability Comments