7

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.

  • What do you mean by "ID property"? – Euphoric Apr 8 '14 at 14:05
  • @Euphoric The ID would be a primary key, basically a database artefact. – BanksySan Apr 8 '14 at 14:30
  • surely 'Number' is unique? – Ewan Oct 12 '15 at 13:57
  • @Ewan no, it's definately not. – BanksySan Oct 12 '15 at 16:44
8

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".

  • Should my Domain be unaware of my database? – BanksySan Apr 8 '14 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 '14 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. – Arnaud Bouchez Oct 12 '15 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. – Steven Jeuris Nov 8 '17 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 '17 at 11:29
4

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

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.

  • 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 '14 at 15:05
  • 1
    Good point. Then there might not be a need for Id at all. – CodeART Apr 8 '14 at 15:07
  • 4
    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 '14 at 16:08
  • 1
    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 '14 at 22:01

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.