8

In my domain I have an Account object.

e.g.

class Account
{
    public string Number;
    public string SortCode;
}

Within the context of DDD, should this account object have an ID property? The ID would be a primary key, basically a database artefact.

8
  • What do you mean by "ID property"?
    – Euphoric
    Apr 8, 2014 at 14:05
  • @Euphoric The ID would be a primary key, basically a database artefact.
    – BanksySan
    Apr 8, 2014 at 14:30
  • surely 'Number' is unique?
    – Ewan
    Oct 12, 2015 at 13:57
  • @Ewan no, it's definately not.
    – BanksySan
    Oct 12, 2015 at 16:44
  • How would one identify an account, if not by its identifier? Suppose I want to change the sortcode of an account. Which account?
    – Flater
    Jul 13, 2022 at 11:06

4 Answers 4

9

It depends. If your Account class shall be mapped to a relational database, then its not just a good idea, but proven practice, to use technical IDs for every table as PKs (and FKs, referencing those PKs). To my experience, separating the technical PK of all tables from the "domain keys" (like the "bank account number") works very well and helps you to avoid all kind of technical issues. I typically name those PKs not just ID, but <class-Name>Id, so in your case AccountID.

If your class above will just be used as an input to a code generator which will generate the "real" code of your implementation language as well as your CREATE TABLE statements, some CRUD code etc., you probably don't need to add the ID attribute in the class code directly. If you are going to use an ORM, it depends on the ORM if it can add ID attributes as PKs automatically, or if it expects you to add those IDs manually.

In a DDD context, it may probably be helpful to hide those technical details when discussing the model with your domain experts, but show them when you change your viewpoint to the implementation of the model. If your tool set allows to display the model in those different levels of abstraction, make use of it. But if the tool set does not allow it, add the ID attributes and tell your domain experts that those are just "technical attributes".

9
  • Should my Domain be unaware of my database?
    – BanksySan
    Apr 8, 2014 at 15:33
  • @BanksySan: Your "Domain", your "Domain experts" or your "Domain model"? Ideally, your toolset allows to show different presentations of your domain model. For example, an UML model where the IDs are not visible (for discussion with your experts), and a representation in code where they are visible. And of course, your domain experts should be aware of your database, but do they don't have to know every technical detail of your database implementation.
    – Doc Brown
    Apr 8, 2014 at 15:57
  • 1
    Hiding the database ID is one way of Persistence Ignorance or Polyglot Persistence It means that the business logic itself doesn't know about persistence. Most of the DDD implementations I see do expose the ID, which is IMHO to be avoided if possible. This is why e.g. I added another automated translation layer over our ORM, to convert DDD Aggregates and ORM records. Oct 12, 2015 at 13:24
  • This answer does not seem written "within the context of DDD". DDD goes beyond "discussing the model with your domain experts". When implementing the domain layer as a domain model (as opposed to your description which seems more in line with an active record), I believe there is a good point to be made not to include the ID in the implementation. Arnoud's answer points this out nicely. Nov 8, 2017 at 11:01
  • @StevenJeuris: "context of DDD" is a very vague term. On some lower layer of abstraction, developers who implement the domain model in code will need access to the ID, and the database will need it for allowing foreign key constraints. I don't see this lower levels excluded by speaking of "within the context of DDD" - for me this reads more like "in a project where the DDD methodology is used".
    – Doc Brown
    Nov 8, 2017 at 11:29
7

Most of the time, the ID field you are talking about would be generated by the database, e.g. as a RDBMS sequence or a NoSQL unique identifier. It is therefore tied to the corresponding database backend used.

According to the Persistence Ignorance / Polyglot Persistence principle, you should better hide this ID from your domain aggregates as much as possible.

In practice, your domain Aggregates may already have an unique identifier. For instance, a serial number, a client code, a logon name, an account number, an invoice reference or an ISBN for a book.

If there is no such "natural" identifier in your model, it may be one role of the domain logic to generate such genuine identifiers, e.g. following a pattern defined by regulation, or human-friendly notions, following your company best practice (it is common to include the year and the month in invoice numbers, or an alphanumeric identifier of the department in charge of the process for instance).

Within the Infrastructure Layer, you would probably let an ID field appear, especially if you need to construct joined SQL queries among several RBDMS tables. Or, if you use an ORM, you may not persist directly the DDD aggregate objects as ORM objects, but use an "agnostic" translation layer. This is for instance what our DDD framework proposes, by adding an automated translation layer between the DDD plain objects and the ORM objects, which have their own ID... some kind of "square ORM": on DDD mapper over an ORM mapper.

DDD is mainly about isolation: don't pollute your domain with database consideration! Naming an aggregate object field as ID does definitively smell: there is probably another naming, compatible with the Ubiquitous Language of your bounded context, which may be used instead of a plain ID.

1
  • 1
    I think this should be the correct answer
    – alaboudi
    Nov 29, 2020 at 15:42
2

I don't think that id is a database artefact. How do you know that account you are working with is correct? You know it's a correct account because it probably has a unique identifier. In your case the unique identifier is called "Id", so naturally you think it's a database artefact. Because of this I think that it's perfectly fine to have Id property in your domain model.

On a side note, I would NOT have a foreign key property in a domain model. For example, instead of having AddressId in the domain model, I would have an Address property and that would contain the address id.

5
  • 1
    In this instance (as it's a UK account) the account is identifiable by the combination of it's sort code and account number. If it were international then it might be different properties or an IBAN.
    – BanksySan
    Apr 8, 2014 at 15:05
  • 1
    Good point. Then there might not be a need for Id at all.
    – CodeART
    Apr 8, 2014 at 15:07
  • 5
    When a relational DB is used, not adding a technical Id will lead to the usage of domain keys as foreign keys. So in this case, every table referencing the Account table will store a duplicate of the "sort number" and the "account number". Now imagine what will happen if some domain requirements change (like local country bank account numbers to be replaced by IBAN, as its currently happening in Europe). Believe me, the usage of technical IDs leads to much more stable models, avoiding a lot of real-world problem which you otherwise have to deal with.
    – Doc Brown
    Apr 8, 2014 at 16:08
  • 2
    As @DocBrown points out: resist the temptation to piggy back on a domain property - they're always prone to change (no matter how sure you are). That said, I consider the ID, or unique key, part of the domain model.
    – jkoreska
    Apr 8, 2014 at 22:01
  • Agreed with @DocBrown, using existing concepts to function as identifiers may prove to be unstable, therefore in many cases it is required to create a new ID concept, as part of the model.
    – setnoset
    Mar 17, 2022 at 4:18
0

The question easer to answer from the end. You are trying to add primary key, since I would use following thought process

  1. Why we need PK? - are we going to search in this table? Is it more than 3-10 records etc? - If we can say yes, that means we have a need for clustered index (do not mix with PK, PK creates it as a side effect).

A clustered index is an index which defines the physical order in which table records are stored in a database.

  1. Do we really need PK or it is enough to have unique key? - Unique also can be the baseline for clustered index. Let's imagine we can use unique

  2. How big index key would be? - There might be multiple options but let's consider only 2: Your field Number is unique and can be from 1 to 50000. The uniqueness of record can be define only by combination of fields SortOrder and Number. While in 1st option I would most likely create PK on top of field Number, in second one I would introduce generic ID to simplify clustered index structure and size.

Now we can get back to DDD itself - "In terms of object-oriented programming it means that the structure and language of software code (class names, class methods, class variables) should match the business domain. For example, if a software processes loan applications, it might have classes like LoanApplication and Customer, and methods such as AcceptOffer and Withdraw."

ID logically is a result of function executed against the attributes that uniquely identify your record and produce integer as output, since it is a synthetic attribute of your domain model. It may be required to shorten object identification or not.

However worth to mention that applying different structure to different tables confuse developers (and that is major reason, why people use ID), practically you truly needed rarely. So it is also about balance in code and ability to maintain it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.