Search code examples
domain-driven-design

How to Approach Domain Modelling with Polymorphic Entity in Domain-Driven Design?


I am rebuilding a software in accounting. This sofware can handle many types of transactions, e.g. sales, inventory restock, and expenses. I have no background in accounting, but I learned some concepts online. I am trying to model the domain with these principles in mind:

  1. A journal entry consists of several recordings, each of which is either a debit or credit. These recordings' total of debit and credit must be equal (balanced) in a given journal entry
  2. A journal entry must be created based off of a source document. One cannot simply create a journal entry without any reason.

From those, I conclude that there has to be these entities present:

  1. JournalEntry entity, which has many JournalEntryItem value objects. This entity is responsible for keeping all its entries in a balanced state.
  2. SourceDocument entity, which has some information of transactions being made

Both JournalEntity and SourceDocument are each an aggregate root, with JournalEntity referencing to a SourceDocument identity.

Now here is the problem. Source documents that are the basis of journal entry creation, can be different things with different behaviors. For example, an 'expense' source document may consists of list of pair of expense category and expense amount, while a 'sales' source document may consists of related inventories, amount of each inventories, and the price of each inventory per one unit.

This makes me think of another approach in the model:

  1. Create an abstract SourceDocument class, with shared properties like date of creation and identity attribute
  2. Create SalesSourceDocument, ExpenseSourceDocument, etc., that are extended from the abstract SourceDocument
  3. JournalEntry entity will still have to reference SourceDocument identity.

While this can make sense, I don't think this is the best way to model the problem in DDD, specifically because it requires to have an abstract entity.

From the sources I read online about DDD, when encountering such problem where I need an abstract entity, I need to separate it into different bounded contexts. However, I'm not sure if it can be done, because a SourceDocument identity may return a concrete SalesSourceDocument in 'sales' context, but it may also return nothing in 'expense' context.

What is the best way to approach this problem?


Solution

  • I think what's important to recognize here is that the source document terminology is to describe the relationship between a journal entry and a document, from a JournalEntry's perspective. Documents are ARs of their own, which can most likely exist without a journal so why should their abstraction be named after the relationship with another AR?

    Source document most likely is a necessary terminology to describe the document relating to a journal entry and chances are it will be part of your model too, but perhaps in the form of a value object such as SourceDocument { id, type }.

    That doesn't mean you couldn't have a Document abstraction as well if useful: there's no reason to avoid polymorphism at all cost when it's useful.

    I may be wrong with that analysis (all models are wrong anyway), but I just wanted to give you a different perspective on that specific modeling aspect.

    I am rebuilding a software in accounting. This sofware can handle many types of transactions, e.g. sales, inventory restock, and expenses. I have no background in accounting, but I learned some concepts online.

    If you can learn your whole domain online then chances are that it's a generic sub-domain where an off the shelf product can most likely be bought. Rather than going online and try to come up with a model on your own you should be involving domain experts: perhaps your entire vision is wrong here.

    Furthermore, given the source documents will most likely live in different contexts, it seems like the Accounting context could be acting as a supporting BC that doesn't have explicit knowledge or dependency on other BCs.