When I started programming, people were talking about Domain-Driven Design. Being a junior, I gave more attention to the tactical patterns. I kind of got the idea behind repositories, entities,Ā value objects, etc.. Six years later and I still see people paying more attention to the tactical patterns. Even Eric Evans says that he has overemphasized theĀ building blocks. So, in order to get a better understanding about what isĀ Domain-Driven Design, I decided to read the book that introduced it. The main purpose was to gain more knowledge about the strategic patterns of DDD.
ddd
Saga concurrency and coarse-grained locks when using NHibernate Persistence
Recently, I stumbled upon an interesting problem related to NServiceBus Saga concurrency and coarse-grained locks when using NHibernate Persistence.
With NServiceBus,Ā concurrent access to an existing saga instanceĀ works out of the box. This is because it relies on the underlying database system. WithĀ NHibernate, it relies on optimistic concurrency, by adding a Version column to your Saga Data. But there is a catch: NHibernate doesn’t support Coarse-Grained Locks. Let’s first explore this general problem and then we’ll get back to the NServiceBus Saga.
Coarse-Grained Locks
With a coarse-grained lock you basically lock a group of entities together. If you’re familiar with DDD, then you know that an aggregate should be a consistency boundary. When I save an aggregate, I want to save theĀ entireĀ aggregate, to ensureĀ it’s consistent. Why would you need this? Here’sĀ an example:
Let’s take the already familiar example of an Order with OrderLines, Order being the aggregate root. We’reĀ using optimistic concurrency control for each of our aggregate parts.Ā In our domain there isĀ an invariant that dictates that the total number of items Ā in an order can’t be more than 10. Two commands that would increase the quantity could be processed in parallel and break the invariant. This is because in each transaction, the invariant would hold and each transaction would commit, since theyĀ update differentĀ lines. Now you’re in an inconsistent state.
If we could lock the entire aggregate (order and order lines), then the second transaction would fail andĀ rollback, maintaining a consistent state. One way to achieve this when using optimistic concurrency is to update the root’s version whenever an aggregate part is updated.
Software Quality: Building the Product Right
In a previous blog post we discussed why building the right product is hard and some tips on how to achieve a high perceived integrity. But if you’re building a strategic solution that should support your business for many years, this is not enough. With time, new requirements get added, features change andĀ team members might leave the project. This, together with hard deadlines, means that technical debt starts to incur,Ā and the price of addingĀ new featuresĀ increases until someone says it will be easier to rebuild the whole thing from scratch. This isn’t a situation you’d like to be in, so that’s why it is important to build the product right.
Building the product right
In their book, Mary and Tom Poppendieck define this dimensionĀ of quality as the conceptualĀ integrity of a product. ConceptualĀ (internal) integrityĀ meansĀ that the system’s central concepts work together as a smooth, cohesive whole.
How can you maintain the conceptual integrity of a product during itsĀ lifetime? You rely on communication, short feedback loops, transparency and empowered teams. These are the same principles that can lead to a high perceived integrity. The only difference is that you apply them at an architectural and code level. Continue Reading
Software Quality: Building the Right Product
If you ask a hundred developers to define softwareĀ quality, you’ll probably get a hundred different answers. ThereĀ are a lot of ways to categorize quality, but one that I find most useful is building the right product and building the product right.
Building the Right Product
First we have to make sure we are building the right product. The most performantĀ and secure product, havingĀ the cleanest and most extensible architecture, covered with unit tests and acceptance tests is in vain if nobody uses it.
In their book,Ā Lean Software Development: An Agile Toolkit, Mary and Tom Poppendieck define this dimensionĀ of quality as theĀ perceived integrity of a product. Perceived (external) integrityĀ meansĀ theĀ totality of the product achieves a balance of function, usability, reliability, and economy that delights customers.
Traditionally, when customers want to build a product, they talk with business analysts andĀ write down the requirements. These documents are then handed overĀ to architects, who then defineĀ the high level architecture and pass the design documents down to programmers who start implementing. There’s a gap between each step and as we go through the process,Ā we lose more and more information and our chances of building the right product get slimmer.