Friday, May 12, 2017

Reading Note on DDD(Domain Driven Design) - Model evolution

The book provides some interesting examples to show how we can evolve models. It is seldom that engineers can arrive at a supple design at the first go, models need be refined interactively just as code. A supple model is the key to cope with business changes. In my opinion, these examples are the gems of the book, pity the author doesn’t offer more examples.

Take the following example in chapter 9 (making implicit concept explicit). A batch script is running each night, it iterates through each asset, and calculates its interest and fee. The result of this calculation is posted to another service, which will log the result into various accounts. The book doesn’t say clearly about how “Fee Payment History”, “Interest Payment History” fit into the graph, my understanding is the nightly script also checks if a fee/interest is due but unpaid and log it. 

What is so awkward about this model?

  • A lot of business logic is encapsulated in the script, not on the business models.
  • Probably there are a lot of duplications on the logic of calculating fee and interest; and also on logging fee payment history and interest payment history.
  •  Because the logic is scattered into the script (probably a very long one), it is difficult to cope with business changes, for example, what if we need to calculate monthly interest? Annual interest? What if we need to calculate penalty for overdue payment? For these changes, we’d have to through the long script, find out the places to change, and carefully change them without disturbing original functions.
  •  The worst part is, in my opinion, this model diagram doesn’t convey the business knowledge. Developers can’t point to the diagram and say to QA or business experts: “this is how interest and fee are calculated, can you review and test if our logic is correct?” Some lengthy explanation has to be made to make everyone on the same page.  And eventually (after a few years or even few months), with original developers moved on, later developers might have to go into the code to dredge out the knowledge.

A naïve technical oriented refactoring is to abstract out the common parts the calculation logic, and reuse them:

In short term, this will make the application mildly better: now you know you should look at CalculationUtil if business requirements involve calculation logic changes. But soon, CalculationUtil will get bloated with a lot of murky logics. 

Version 1

By talking to business experts, developers pick up some business terms: assets “accrue” interest and fee, which are posted to “ledgers” (accounts). Digging deeper into these terms, and using the skill of abstraction, developers come to this understanding:

  •  Asset is something that can generate income
  •  There are two types of income accruals, interest and fee, both can have different schedules and are posted to different ledges
  •  Payment and accruals are separate: interest can be generated daily, but payment can be paid monthly.

With this understand, developers draw this model diagram:

Business experts probably won’t abstract asset as something that will accrue incoming, that is where we software engineers step in and abstract business concepts into object models that facilitate programing. Even though this is a higher level of abstraction, business experts won’t have difficulty in understanding the diagram, conversations will be much easier now that everyone is on the same page. 

Future business requirements can be accommodated, not only more easily, but also in a more clear-cut way. For example, if there is a need to calculate annual fee, we know where and how to implement this logic. 

Version 2

The above diagram looks very nice, but it is not the only way to model business logic. The author suggests that there are established analysis patterns that you can draw experiences from.

In the accounting business, “double-entry book-keeping” is a well-known practice. And also, in accounting, it is usually required to track each entry in the account: money has to be accounted for, it can’t be generated or disappeared from nowhere. 

By reading accounting books and talking to business experts, developers came up with this model:

This model doesn’t get rid of InterestCalculator and FeeCalculator, but it does unite Fee Payment History and Interest Payment History into concepts (account and entry) that are understandable to business experts. And when developers and business speak in the same language (UBIQUITOUS LANGUAGE), future development will be much smoother. 

This is not the end of evolution, developers will iterate models through learning from business experts and high level of abstraction. The author provides a few more examples to show the journey, which are worth reading. 

Through this example, you should know that to be able to keep up with rapid business change (the goal of Agile), the key is to have a supple business model. “scrum”, “daily standup”, “user story breaking” will be frivolous if they do not contribute to a supple model.

1 comment: