Don’t use Ids in your domain entities!

How often do you see code like this in your domain model?

public void Ship(int orderId, int customerId, string address)


    Shipment shipment = _existingShipments.Single(x => x.OrderId == orderId);

    if (shipment.CustomerId == customerId)


        // Do something



Seems pretty good, doesn’t it? Well, it doesn’t. I’ve already pointed using Ids in domain entities as a bad practice, but I see developers – even sophisticated ones – write such code over and over again, so this topic definitely deserves a separate article.


One of the main DDD principles is separation of concerns. You should isolate your domain model from non-domain logic as fully as possible to avoid complexity overhead. That is especially true for domain entities because they are heart of your application.

Ids are essentially persistence logic implementation details; they have no relation to your domain. For example, you could use composite primary key instead of single-column key, but the meaning of the code would remain the same:

// Single-column key

if (shipment1.Id == shipment2.Id)


    // The shipments match



// Multi-column key

if (shipment1.Id1 == shipment2.Id1 && shipment1.Id2 == shipment2.Id2)


    // The shipments match


In addition to poor separation of concerns, the use of Ids breaks entities’ encapsulation (aka Law of Demeter, aka Tell Don’t Ask):

// Seems nice

if (shipment1.Id == shipment2.Id)




// Still not bad

if (shipment1.Customer.Id == shipment2.Customer.Id)




// Well, maybe that’s enough

if (shipment1.Customer.Address.Id == shipment2.Customer.Address.Id)




// Stop it!

if (shipment1.Customer.Address.City == shipment2.Customer.Address.City

    && shipment1.Customer.Address.Street == shipment2.Customer.Address.Street

    && shipment1.Customer.Address.State == shipment2.Customer.Address.State

    && shipment1.Customer.Address.Post == shipment2.Customer.Address.Post)



The last statement has an obvious design smell: it violates entities’ encapsulation. The first (and the other two) statement has essentially the same drawback, the only difference between them is size of the code.


You don’t need Ids to operate your domain objects. In most cases, all you need is define equality members in the base entity class so that you could rewrite your code like this:

if (shipment1 == shipment2)


    // The shipments match



if (shipment1.Equals(shipment2))


    // The shipments match


Also, Ids in domain entities often indicate a hidden abstraction:

public void Deliver(

    int fromAddressId,

    int toAddressId,

    int orderId,

    int customerId)


    if (_existingShipments.Any(x =>

        x.FromAddressId == fromAddressId &&

        x.ToAddressId == toAddressId &&

        x.OrderId == orderId &&

        x.CustomerId == customerId))


        // Attach to existing shipment




        // Create new one



In this example, Ids can be encapsulated in a separate entity:

public void Deliver(Shipment shipment)


    if (_existingShipments.Contains(shipment))


        // Attach to existing shipment




        // Create new one



Such approach allows to keep complexity under control hiding all of the implementation details underneath of a separate entity.

I must point out an important note, though. All stated above refers to domain entities only. You can – and should – use Ids in infrastructure and application services, because Ids are natural for objects identification. Such application services operate on a different level of abstraction: they need Ids to map domain entities to database tables, to identify a web page requested by user and so on; they don’t contain any domain logic.


Ids in domain entities is a design smell. In most cases, they indicate poor entity encapsulation. If you want proper separation of concerns, you should reduce the number of Ids in your domain entities to as low as possible.

Heavy Ids usage is common for anemic model. There’s nothing wrong in it if you have a simple CRUD-like application. But if your application is large and complex, you should definitely choose rich model instead of anemic one, and thus, don’t use Ids in your domain classes.

Related articles:

Edit 2019-03-12:

A long overdue clarification:

Clarification on when to use Ids


  • disqus_kCEFVbbFLB

    why is it a crime to expose an id? i just did it so what? it’s not a secrete, anyone who wants to mess with it is welcome to do that (for an atomic entity it;s not really a problem), so seeing ids doesn’t break things, using them improperly is something that does, and in more advanced type systems there are means to tackle it, not in c# though

    i really can’t see what you call a problem here

    • Vladimir Khorikov

      Thanks for your comment. There are 2 problems with ids in my opinion:

      1) They expose the inner details of how a class works. For example, if you need to compare two instances of a class, you may either use the == operator, or examine their ids and do the comparison manually. The second option has a problem – it requires you to make the decision based solely on the members of the class, which means it violates its encapsulation.

      2) The second problem is that Ids don’t belong to ubiquitous language. They are technical details that we have to bring with us because of environmental constraints. It’s ok to have them of course (we can’t avoid it anyway), but it’s a good idea to hide them from the outside world.

      • disqus_kCEFVbbFLB

        1. presence of ids represents the fact that they came from a database, that is an id is a reference to a master record, in this sense an object is just a snapshot of that record, unless the id is irrelevant (we only focus on the information that snapshot is carrying) it should be omitted, in all other cases based on the knowledge that the snapshot is bound to a record somewhere the id is very relevant and required

        back to your example with comparing objects, if your semantics calls for comparing the data you don’t use ids, if your semantics requires comparing a reference to the database record then you compare ids regardless of what data is, all in all it all depends on the situation and both methods might be needed, it is reckless to ditch one in favor of another

        2. mind drawing a line that separates technical details from the domain? again it depends on the situation where you either focused on processing the payload data or details about how that data was retrieved

        it is only a good idea to hide them when they are irrelevant, but you cannot decide for the outside code whether they need it or not (the decision is up to the outside code that uses it), all you can do is to provide both the data and id and let the decision be made by whoever is in charge

        • Vladimir Khorikov


          presence of ids represents the fact that they came from a database

          Unless you don’t have a domain model whatsoever (which is also a valid case in many situations), domain entities shouldn’t know how they are stored in the database. The only thing they should be responsible for is business logic. Separation of concerns is one of the main DDD principles. Ids have their own field of application, of course, but this area resides outside the domain entities.

          if your semantics requires comparing a reference to the database record then you compare ids regardless of what data is, all in all it all depends on the situation and both methods might be needed

          You are talking about the notion of equality, it has a different meaning for entities and value objects. This dichotomy is one of the reasons why we should encapsulate the comparison operation. A client class shouldn’t be aware of how to compare two objects, all it needs to do is call “object1 == object2” or “object1.Equals(object2)”, and leave the actual implementation to the class to which these objects belong. Basically, it’s the definition of the encapsulation concept. Check out these articles where I write about the notion of equality in more detail:

          2. This article is applicable to domain entities only (hence its name). Technical details in this situation is any code that is not directly related to the domain knowledge a domain entity represent. Ids is one of such details. At the same time, a link to a parent entity (for example, a Customer property in the Shipment class) is not a technical detail because it represents a relation between the two domain entities.

          it is only a good idea to hide them when they are irrelevant

          100% agree. The thing is, when inside domain entities, Ids are always irrelevant. Outside of it, they are absolutely relevant, for sure. And to make it clear what I mean by that, here is a rough diagram which represents an application built with DDD principles in mind. The domain entities are at the inner-most level of it:

          • Aleksey Bykov

            there are at least three notions of so-called equality out the box:

            – by ids, meaning being bound to the same record in the database
            – by reference, meaning pointing to the same location in memory
            – structurally, meaning deep value-to-value comparison

            all three of these have their applications benefits and shortcomings

            now you suggest we need to pick one and stick with it for life, because it is the most right to any situation out there, and to achieve that we employ encapsulation as a black box so that no one knows what is actually being compared

            i can see a few drawbacks of doing so, what benefits can you see?

            it’s a bad idea to decide for others which way they need to go, a better way is to let the calling side pick the equality function according to what they think equality is

          • Vladimir Khorikov

            now you suggest we need to pick one and stick with it for life

            It’s not what I was saying. Every class has its own way of dealing with equality: either using structural equality (value objects) or identity equality (entities).

            it’s a bad idea to decide for others which way they need to go

            The comparison logic belongs to the class itself. It’s not that someone decides how to use the class, it’s the clients use the class’s public interface to work with its instances. Comparison operations are part of this interface.

            Encapsulation gives us many benefits, the main one is that the comparison logic is not getting duplicated across the code base.

          • Aleksey Bykov

            encapsulation indeed brings benefits, the main one is that it lets you (according to wiki)1. hide the implementation details 2. bundle your data with your logic

            it is orthogonal to being able to reuse the code, let me explain, in the example with comparison one can define a static method (without having to encapsulate anything) and reuse it all over the application instead of calling the Equal method ..

            in fact there can be as many static methods as needed to cover all nuances of how the comparison can be done, contrary to one and only implementation of the Equals method

            how comparison works never depends on the entity which is not even aware of how it is being used, it is always up to the needs of the calling side

            lastly it’s not the only problem with missing ids here, i am still hesitating to ask what you going to do with a stale domain entity that needs a refresh, the id of it is unavailable (encapsulated/hidden/whatever) but the DB needs it in order pull a fresh load of data.. so would you encapsulate data retrieval logic into the data entity too?

          • Vladimir Khorikov

            how comparison works never depends on the entity which is not even aware of how it is being used, it is always up to the needs of the calling side

            I see, this is the point we disagree upon. In my opinion, this type of thinking leads to anemic domain model as it pulls the logic out of entities to external “services”. Anemic domain model has its own pros, but in projects with a complex domain, they generally do worse than rich domain model. The main disadvantage here is that such logic – when pulled out of data it operates – tends to be inconsistent across different implementations. This, in turn, leads to maintenance problems.

            what you going to do with a stale domain entity that needs a refresh

            Domain entities still have Ids, it’s that they themselves shouldn’t use it. The upper layers (repositories for example), can refer to their ids and work with it in order to map an entity instance to a DB row.

          • David Raab

            I can understand both of you, and your points. A domain model should be persistent ignorance. So it should have no Ids. IDs are a problem from the storage layer, not from the domain layer. But on the other side, even in a domain layer you probably want to indicate an entity by some “id”. The reason for that is that when you change a domain object, you still can refer to the previous domain object. And you knew that for example two objects refer to the same piece of data.

            As for anemic domain model or encapsulation. The point of encapsulation was never to solve code duplication. As a simple static method outside of the object would also solve the problem. And as long as you provide getter someone always can write his own logic without using a provided method on a object.

            The term anemic domain model that was introduced by Martin Fowler is for me a good example that people have long forgotten of wh we have encapsulation in the first place. And by forgetting the problem they think that violating encapsulation is something bad, what is just a dumb idea.

            In functional programming it is a normal thing to separate data and functions. And i think that separating data and behaviour is a good thing. While doing this in OO automatically raises the “Anemic Domain Model” and thinking of it as something bad.

            You are saying that anemic domain model is bad for complex application, but on the same side, this is a normal thing in functional programing and i even think complexity is better handled in a functional way.

            So which one is right? Both. But i think separating is “more correct”. The purpose of encapsulation was not of providing a common behaviour. As already stated. Every function (static method) inside a class, module, namespace and so on already allows you to not have duplicated logic.

            The idea behind encapsulation or what we call OO today raised from simple structs in C. structs in C can contain a whole bunch of data. In fact you also can program OO with this. OO or methods in general is nothing more as just having an implicit argument that takes an additional data structure. Typically named “this” or “self” in languages. In some other languages passing the object itself is not even hidden. There is technically no difference between



            As both version provides a common logic without that you ever have to duplicate something. So which problem tried encapsulation to solve?

            The problem is that the first version has a mutable public struct. Everyone always can access all internals of the struct, can read or change the internals. In this way it is easy to bringt a struct into some invalid state. Directly changing it can basically break the program at some other places.

            So encapsulation was introduced to solve this problem. Instead of allowing access to everyone, you only allow the access to some fields from specific functions. So how do you mark which functions are allowed and which not? by introducing a class and whole bunch of new complexity with public/private/internal and so on. So you can mark things as private not visible to outside functions and only visible to functions inside a class.

            So thinking of that idea. Makes the term term “Anemic Domain Model” even sense, or is it automatically bad of having a function not inside a class? Does it automatically lead to voilation of encapsulation? Not at all. As if the state of an object is preserved and you cannot bringt an object into an invalid state is not important at all of wether a function is part of the class or not. Not writing it inside a class is not a violation of Encapsulation. And that is also the reason why “Anemic Domain Model” is a useless term. Because it doesn’t try to understand of why we have Encapsulation. It simple vies every function not part of a class as a violation of encapsulation, what doesn’t make sense in the first place. And giving it a name. It’s the typical thing i see from a lot of “only OO-Progamers”. Those programmers are just so often told what is right/wrong without explaining the real purpose behind techniques that they don’t even knew why they have techniques in the first place.

            And that leads to stuff like the “Anemic Domain Model”. A misunderstanding on encapsulation leads to the fact that they think that every violation leads to another bad thing.

            So how does functional programing solve the problem of invalid objects? Easy. Only a function (compared to a constructor in OO) can create a datastructure. And after that every datastructure is immutable. So with immutability in place it just cannot happen that some code changes a mutable field and invalidates an object. So you also don’t need methods that must be part of an object. There is no additional benefit behind it.

            Encapsulation was the problem of solving the problem of mutable data and solving the problem that they cannot be changed to get invalid. Immutable data-structures also solves the problem. But in a different way.

            Don’t understanding this leads to people like Martin Fowler that thinking that every method not in a class violates encapsulation and must be bad, what is just insanely stupid. With an immutable data-structure nothing needs to be part of an object and nothing violates encapsulation because the problem that an object cannot become invalid was just solved in a different way.

            That’s also the reason why a Record in F# don’t need public/private accessors. Everything is just public and immutable by default. And functions are put inside a module. There is also no need that a function has to be part of a record.

            So how important is it to expose a field like “id” in a immutable data-structur or an object where you cannot change the “id” to bring the object into an invalid state? Not important at all. It also breaks no encapsulation.

            As for comparison. I even think it is a good think that F# for example allows to disable comparison of Records. in my experience providing a comparision for every object out-of-the-box is something bad. Because you never really knew how comparision works.

            If i try to compare two persons. What does it really compare? Does it also compare things like a “friends” attribute that contains additional Persons? Does comparing two Person even makes sense? Does it just compare Name and Lastname? Or probably even age and birthday? Or does it only check if it is the same person? And probably in your application it can be that you just want multiple of those comparisons not just one specific. And which comparision is so important to give it the default “==” equal operation? If you want to sort Person in a table you probably even compare just by “LastName” and then “Name”.

            It often makes more sense to disallow equal/comparision completly and don’t give any default implementation. Instead users have to either write their own comparision by comparing fields like they want. You also can provide a lot of comparision functions that you think make sense. But instead providing them just as functions that someone can use. It makes code a lot more understandable as just seeing a “a == b”. With “a == b” you never knew what it really does.

            In that sense. Also some interesting blog:


            And if you have some hours to read (took me ~4 hours to read it completely, but it is an awesome blog)


            It also contains a lot of things that i said here with a lot of criticism.

          • Vladimir Khorikov

            Wow, that was a really long comment 🙂

            Thanks, you have many good points. I’d like to comment on some of them.

            Regarding Anemic Domain Model – this term is indeed applicable to OO languages only because it’s drawbacks go away completely if we introduce immutability. That’s the reason why we don’t say functional way of dealing with logic is anemic. I was thinking about writing a separate article on this a while ago, but decided there’s not much to talk about besides the immutability concept.

            Regarding encapsulation vs code reuse. While I agree encapsulation is not about the code reuse and the same benefits can be archived just by creating a single static method outside the entity for checking equality, in practice such approach does lead to code duplication. A common way to deal with logic that works on top of some entity is to place it to that entity, either as a instance or a static method. If there’s no such method, developers tend to create different versions of it in different places, hence code duplication.

          • David Raab

            Immutability is not a functional only thing. Immutable design is also possible in OO and is more and more common today. Because of this i would not say “Anemic Domain Model” is in general an OO thing. It only applies to OO code that is not written with immutability behind it.

            As for code duplication i don’t see why it should lead to code duplication. Probably it’s a matter of what is “inside” and “outside”. With “outside” i mean outside the class. So a static method itself is always outside.

            And normally for a Person object you would add the static method to the Person class. So instead of having “person.SomeMethod()” you have “Person.SomeMethod(object)”. Sure the first way of doing is more common for OO. If you already have an object you can just add a dot to it and you just see all methods. With the second approach you have to type “Person.” first.

            But i don’t really think the last one would increase code duplication. Checking a Class for static methods should be the first thing someone checks first before writing his own function.

            And the second version is also not really so much more terrible. Given that we often do data manipulation/transformation with LINQ today. A static method works better (IMHO) with it instead of having a method. The difference is between.

            var jsons = persons.Select(person => person.ToJson())
            var jsons = persons.Select(Person.ToJson)

            Sure that is not the reason i would rewrite it to always static methods. The point is more that i don’t see any reason why the second approach should lead to code duplication.

            And at some points you anyway have a problem. If you don’t have control over the domain code, it means you anyway have to write static methods, because you cannot add methods to a class you cannot control. At least you could use Extension Methods for this so self-written static methods appears on objects. That’s also another reason why static methods in other classes besides “Person” don’t have to be harder to find.

            At least this has even an addition benefit. Because it solves the problem with coupling. Because now you can just load the namespaces/libraries you need. The “ToJson” method also could be in a “PersonJsonExtension” (in its own binary) and you only load and use it when you need it. It just don’t have any coupling because Data and behaviour was separated (like mentioned in the first link i provided at the end of my previous post)

            And you could even have a better code-reuse and sharing. If you don’t need JSON serialization. Don’t load it, don’t use it. You can provide your own additional logic for Person objects. You can share it, and other can use it or not.

            In that sense i found it even funny that with simple static methods and extension methods i can achieve easily a system that is more flexible, is modular, don’t forces coupling on libraries and do all of it better than any “OO approach” has to offer. And it is funny because typically we are told that these are features we get when we do OO.

            But a lot of people don’t do it because when they see a static method they fear that it could be an “Anemic Domain Model”, believing it’s not OO, believing it violates “Law of Demeter”, believing it violates “Tell Don’t Ask” …

            I don’t say you said all of those stuff. What i just want to make clear is that we should really look more closely on what we do, what we get and what we want to achieve. It happens to often in my experience that (probably better) ideas are dropped just because someone sees a violation of some “guidelines”.

          • Aleksey Bykov

            He has completely forgot his original statement by this point. It’s like you still should not use the Id’s in the data entities because of OOP nada nada. But we have to admit sometimes it’s rather hard not to do so nada nada. And in fact those few cases constitute somewhat like 97.8% of all situations where it is still OK to use Id’s because although it breaks a couple of dogmas OOP is still great, loving and forgiving. To me this is a total bs. Man, you gotta get some opinion about what you are trying to talk.

          • David Raab

            Yeah the discussion drifted a little bit of. As for me. Just exposing an “Id” is not wrong. As an Id is also usually immutable i also don’t think someone can say it leads to “Anemic Domain Model” or it violates Encapsulation. So i don’t see any reason to not provide an “Id”.

            As for the usefulness. In some situation as you already said you need just something like an Id. Because you really want to compare if someone is the same person, and not comparing some fields.

            That especially becomes true when we have an immutable design. When whenever we do a change a new version is created you just need some way to still be able to identify two things that refers to the same thing. So a public “Id” that someone can compare becomes even more important.

            But even in a mutable design. Just make sure that the Id itself cannot be changed, and sharing is fine. In general i learned that trying to hide some data often just creates more problems as it solves.

          • Chris Rush

            I agree. Exposing an Id is not necessarily wrong. It can be a reasonable part of a Domain Entity. It’s also a necessary evil in many cases to have that unique identifier for an Entity.

            We say idealy that an entity should be persistence ignorant (PI), but if we remove Id, are we able to persist the Domain Entity back to the storage layer when the time comes?

            Take your example of the last name changing on an entity. If the Domain Entity was mapped to a storage record with Id 1 and last name Jones, how does the Domain Entity get mapped back to storage record with Id 1 when the last name is changed to Smith?

            It’s impossible. In such case, a UID is the only bit of information that can maintain the relationship between the Domain Entity and the entity that goes into storage.

            In these terms, one could think of Id as a kind of SSN. A unique identifier of a person that is immutable, even if the other details of the person changes. Thus, it makes sense in the Domain Entity.

            From that we could surmise that a Domain Entity must have immutable identity. In some cases, a standard int might not be required to satisfy the requirement of immutable identity. However, most of the time it is the easiest and most well understood mechanism for immutable identity.

  • Marcos Douglas Santos

    Imagine that you have no Id and no any kind of ORM frameworks, how you will instantiate a Person, for example, without your Id?

    Person p = new Person(?);

    • Vladimir Khorikov

      That’s a great question!

      Maintaining proper separation of concerns would be a harder task in this case. Without an ORM, a “clean” way to do this would be to actually mimic the ORM ourselves. That is to write our own mappers to map an entity to a DB row. And it’s actually the way some programmers did it before (N)Hibernate gained traction in the enterprise world back in early 2000’s.

      Now, this is a difficult path and it probably makes sense in really large projects only. A more pragmatic way to deal with this kind of situation would be to disregard this guideline and just assign an Id in the constructor, because the clean way wouldn’t justify its costs in this particular case.

      I would say purity is not something we should try to archive at all costs. At the same time, if the cost is reasonable, we should take it. ORMs make this cost reasonable for us. Without one, it would probably make more sense to reside “closer to the ground” and deal with Ids from the database in our domain model.

      • Marcos Douglas Santos

        I understood your comments about “purity vs cost” and I agree. But about ORM’s, you consider them a good thing… I not.
        Some people also doesn’t like and, maybe, you would like to write some comments about it here

        • David Raab

          I could anyway bang my head against the wall whenever i read an article from Yegor. But you really think his approach is good?

          And just for the matter. What he shows is just exactly what an ORM does. He basically implements his own (absolutely crap) ORM.

          The point of an ORM is to map data to objects and hide this mapping behind classes. Exactly like he do in his post. Just so much more worse.

          in his example fetching a table with 100 rows (every row just have id,date,title) would mean 1 query just for the ids. And then for every element two extra queries for the title and then date. So it would already do 201 SQL queries to fetch 100 rows. Even when he does cache every row afterwards in its own object it is just too much with a completely worse performance. Having some more data or doing that style on a web page would mean that with 5 concurrent user the whole server would probably not be usable anymore because already 5 users create too much sql queries. And if he does that style everywhere probably even 1 user could do that.

          On top you probably want to create some dynamic SQL queries. Doing his approach you either have completely static content or you need to build SQL strings by yourself at runtime. What is just completely horrible.

          I worked with that approach a long time ago in a company, because they had an old system pre-2000 that was written without an ORM and it was so horrible. Especially that the requirement was to have flexible queries for users. Even a date you probably want that a user can.

          pick date, month and year seperately. filter by title. Doing Date filtering betweens two dates. Just implementing those stuff by hand probably takes 500-1000 lines of code, what is solved by 2 lines of code by any modern ORM.

          And you have to do that every time again whenever you have a date field. And now suggest you have tables with 15 columns and hirachical data.

          You sure can write a mapper to map some DataStructure that creates an SQL Query for you (And i did that myself) so you don’t have to reinvent the wheel every time you want to query a table. But doing so just means you exactly reimplement what an ORM already does.

          And what you see there by Yegor is exactly that. His own ORM implementation. And he even don’t see that he basically reimplements his own ORM evn thinking he does something different.

          What he shows

          Posts posts = new PgPosts(dbase);
          for (Post post : posts.iterate()){
          System.out.println("Title: " + post.title());
          Post post = posts.add(new Date(), "How to cook an omelette");
          System.out.println("Just added post #" +;

          is just his own self-written an ORM. A solution without ORM, that means something that does not map to objects would more look like this.

          Posts posts = new PgPosts(dbase);
          for (Post post : posts.iterate()){
          System.out.println("Title: " + post.title());
          Post post = posts.add(new Date(), "How to cook an omelette");
          System.out.println("Just added post #" +;

          i don’t knew the exact interface of JDBC but the code would look like something like this. And that is nearly the full implementation what he does.

          var dbase = /* Some code to open database connection */
          var posts = JdbcSession(dbase).sql("SELECT id,date,title FROM post").fetchAsArray();
          for ( var data in posts ) {
          System.out.println("Title: " + data.getColumn("title"));

          var newId = JdbcSession(dbase).sql("INSERT INTO post (date,title) VALUES (?,?)")
          .set(new Utc(new Date()))
          .set("How to cook an omelette")
          .insert(new SingleOutcome(String.class));
          System.out.println("Just added post #" + newId);

          But this time really without an ORM, and also not trying to write one on his own. Everything what he shows is just a really bad implementation of exactly that what he thinks dislike. An ORM.

          • Marcos Douglas Santos

            I agree with you, Yegor’s approach is crap — considering his example.

            The idea of have an ORM that is not good for me. Of course has advantages and disadvantages but I never found an ORM that makes the SQL more smart than me, using strings. Horrible you say, yeah it is. But if you needs more performance and customization, doing the SQL by hand is more simpler than using many fluent interfaces to do the same, in many cases.

            To CRUD, of course you needs some objects/functions to do this more simpler than makes by hand.

            I saw and I keep seeing many programmers using ORM to do simple things but when they needs performance or make a complex fucking report, they don’t play with objects, they use SQL by hand e pure data.

            So I think: if I continue to write SQL by hand and “making my code horrible”, why continue using an ORM?

            PS: I made a software to make filters — I mean, fuck filters by users that don’t care about your DBMS, memory, nothing — and this software was made in a couple weeks. If I had used objects with an ORM to make these filters, maybe it would take a couple of months, trying to convert “objects” into data.

          • David Raab

            It probably depends on which ORM you used. The day back when i worked on websites and also later with ORMs was when i did perl programming. There we had DBIx::Class as an ORM it was just great.

            The SQL queries that thing builded together was just insane. You usually could provided a query and you provided a query with a datastructure. And it automatically joined every needed table and only fetched the data it needed everything in one go and that also across different tables.

            You could create classes and he created the database structure out of it. Or you designed the database and he created the classes for you. Or you even could Paste SQL directly and he created a class that just abstracted that hand-written SQL-query. If you really wanted you still could use hand written SQL.

            I also don’t think that ORM are the best thing in everything. But coming up with my own solution that did all this would probably take my years. Sure it also comes with it costs as such an ORM is still full of features and has a lot to offer. So you have to learn a lot before you can use it. But i never regret to use such an ORM.

            While i still criticize ORMs i don’t think coming up with own code gives much benefit. Especially not what Yegor did, as that is just a self-written ORM he shows.

            But what i would criticize the most is more how data are saved today. And i in general think that RDBMS and ORMs don’t do a good job at this. Looking into other stuff i for example find MongoDB a lot better. It has an easy query syntax, and saving full documents also is much more how objects are represented. I think objects in general just maps bad to a relational database.

            And providing other solutions also F# has nice approaches with his Type providers. The SQlProvider Type providers don’t create any code at all, instead they just create a type that you can query. But that query is like SQL but as a type-safe variant. So you get auto-completion in your IDE for tables, fields and so on.

            With the SQLClient Type Provider on the other hand you just can post some SQL itself and based on that it creates a F# data type that represents that query.


            That also looks for me better as the heavy ORM approach. But most of the part of why it looks like this is that it doesn’t try to map some data to some classes. Data is just data. A clear separation between data and behaviour. And i think that approach is better. Sure a guy like Yegor with his insane “everything has to be an object or it is bad” will probably not come to something like this. Instead he bashes ORMs and writes his own ORM instead.

            But i cannot say how good such things scale. Currently i don’t do any heavy data/SQL based things anymore.

            I also cannot compare it to (N)Hibernate. But usually ORMs getting better. As far as i know also NHibernate does support “Domain model” quite good. So you just write plain classes without inheriting from some base classes and it can save/load stuff into a database. At least i can say that with my experience with ORMs, i never want to go back and try to mess with building SQL strings. And at least with what i saw, an ORM even came up with better optimized SQL that i couldn’t even write hand-written.

          • Marcos Douglas Santos

            The ORM was Hibernate, Java.

            I not know MongoDB. I continue using relational databases because all my work is centralized them… just because that. If some one hire me to work using a non-relational database, I’ll learn of course.

            Yeah, F# (.NET in general) has a lot of cool stuff and you already talked with me about FP, but I have not learned yet.

            An ORM even came up with better optimized SQL, I doubt! 🙂

          • David Raab

            If you work with Java you also have Scala or Clojure as functional-first languages. Scala and F# are very similar. And i think in the future i will probably learn Clojure or Lisp.

            As for MongoDB there exists an interactive web tutorial. It is quite good as you can directly create queries against a real MongoDB database.


            Doesn’t take much time to work through it, but with this you already get a grasp on how it works. It’s definitely worth to look at it, to see some other ways. The benefit of MongoDB is that it saves full documents that are expressed as JSON objects. And like JSON you already can include arrays or other objects. While in a relational-database you have to split everything into multiple tables and connect it with PKs/FKs that is simple not needed in MongoDB. You just can save arrays or additional data as a full data structure. And sure you still can query those data structures even on nested fields.

            As for SQL i don’t see the problem. Typically programs are better in optimizing things as humans are. Even a compiler can typically optimize code better than a human can do. Trying to hand-optimize stuff also can lead to the result of destroying compiler optimization. Sure all of that still means the algorithm itself stays the same when i’m talking about “hand-optimization”. For SQL it is not so much a difference. Also SQL ends up in a Tree that can be optimized like program-code. As what i’m referring is the ability to prefetch data. At least in DBIx::Class (the Perl ORM i worked later with) you could specify a query and you could specify which tables should be prefetched. He then created a single SQL Statement that prefetched only the specified data. I even saw examples that he ended up with queries that very multiple pages big when you prefetched lets say like 20 tables. Doing that stuff from hand is nearly impossible. What you will end up is probably creating like 20-50 separates SQL Statements to query all the data you need in such a case.

          • Marcos Douglas Santos

            I do not work directly with Java. Some people at team does.

            The most time I’m working using Object Pascal (Delphi and FreePascal). We have a big system coded in Delphi and some tools coded in Delphi and FreePascal. Other parts using Java and C# too.

            Thanks for the link about MongoDB.

            I had read about NoSQL. But I never worked with it. Sounds strange for me put all data in one place (not in tables and columns) 🙂 but I will study more.


    What about Aggregates relationships, Vaughn Vernon /?p=879 consider using IDS

  • Vitor Cruz

    I agree with you, but how do you keep IDs out of domain classes? Most ORM will force you to define an ID field on you domain class.

    • Vladimir Khorikov

      The idea is basically to keep as few of them as possible. So for example, an Id to declare an identity of the domain class itself is OK but to refer to another entity, it’s better to use a pure reference instead of an Id (i.e. Order, not OrderId).

      • Lars Gyrup Brink Nielsen

        Or just don’t include ORM-specific details in you domain entities. Keep them in the low-level infrastructure layers.

  • Ahmed Dridi

    Totally agree with this thanks!
    I’ll add an advice: if you find yourself needing an Id in your domain you must surely review your Domain design and make sure you’re not giving it some extra responsabilities than it should

    • Marco Pierucci

      And how do you map your domain entity to a data entity. Lets say you have a domain Card class, you modify it and send it to de data layer (BD) to update, how does the data layer know wich entity to update precisley

  • Rajan Prasad

    Sir, I was of the view that domain objects should not have ID’s, as they are almost always persistence level details, as you have mentioned here.

    But in this page, that you have linked here, , you say this, “Okay, but what logic do we need in the base domain class?
    Obviously, it should have an Id field, which is mapped to a table’s primary key.”

    Aren’t you contradicting yourself?

    • Vladimir Khorikov

      I would distinguish between the entity’s own Id and the way this entity references other entities. Entity’s own Id represents its inherit identity which we use to differentiate it from other instances of the same class. At the same time, it’s an internal implementation detail which other entities shouldn’t be aware of. And so when this entity references another entity, it shouldn’t know how that other entity represents its identity, this concern should be encapsulated away.

      Hence this difference. The entity can and should know about its own Id, but shouldn’t be aware of ids of other entities.

  • Kaspar Kallas

    In my shop, we reserve navigation properties only for aggregate relationships. My experience is that it’s a good restriction to withhold to. The main reasons are:

    1) When reserving navigation properties only for aggregates, the aggregate boundaries are easier to reason about and harder to break. For example, if I have an Order aggregate which controls OrderLines, and another entity had to reference an OrderLine outside the aggregate, it would scare me if I it was a full object reference instead of an identifier because it would not be immediately clear if the other entity could call state-changing methods on the OrderLine or not (which it should not).

    2) Heavy use of navigation properties can lead to circular interactions between objects. I see object interactions as a graph. I like to keep my interaction graphs simple if possible — one-way and flowing “down”. For example, OrderLine from the previous example referencing “up” to Order would create a horrible circular reference. And I’m familiar with the fact that OrderLine can have absolutely no reference to the parent aggregate Order (but if there was, an ID reference would be better choice).

    Bonus reasons are:

    1) Navigation properties only for aggregates works perfectly with a document database. Object references outsides aggregate would cause duplicate serializations when no special action is taken to remedy this. I’ve seen you use functional programming to reason about some concepts in OOP; I like to use document database to reason about modelling an aggregate.

    2) Using ID references plays well with the specification pattern, no matter the ORM, because they’re really easy to wrap in a database queryable expression.

  • alireza Rahmani khalili

    If we remove ID then what is the criterion for equality? Also if we do not compare by ID we would compare it by value? is it still entity? or it’s value object?

    • Vladimir Khorikov

      It’s not that you should remove the id from the entity itself, it’s that you shouldn’t refer to it from the outside of that entity.

      • alireza Rahmani khalili

        then how we can refer to it from outside? I think we can just refer to entity with Id.

        • Vladimir Khorikov

          Outside a BC – sure. Inside of it, straight references are preferable.

          • kunamistu

            Does that mean that, it is ok for the Entity to contain the ID, as long as I only use it during “persisting” time?

          • Vladimir Khorikov

            Correct. As long as you use it for persistence and don’t use it from other entities and value objects within the same bounded context.

  • corneliu

    Hi Vladimir, I’ve followed your Pluralsight course about DDD and now that I have the chance I’m trying to apply it. One thing that I cannot figure is, how do you remove child Entites (the part removing from domain is easy), but persisting the change to the DB, how is it done ?

  • stefan123456

    A database entity is not a domain entity. Domain knows nothing about a database, ever. So we can use for example the ECB pattern to make this happen. If we use Ids in a database entity this is ok.

  • Misha Chekin

    I subscribe wholeheartedly to the notion of the Law of Demeter.
    But there is something that is either confusing or wrong regarding this article.

    The main difference between Entity and Value Object, as I understand it, is Entity having an identity (Id) while Value Object being defined by it’s attributes.

    In other worlds, the equality of the Entity is defined by it’s identifier (Id), regardless of it’s other attributes, while the equality of Value Object is defined by it’s attributes.

    You wrote about this distinction yourself:

    So Entity must have an Id regardless of the existence of any Persistence layer.

    As a simple example:
    We can have a User Entity witch incorporates an immutable Value Object Age. A year passes and we substitute the Age of the User by another immutable Value Object.
    How can we still find this User? By his identifier of course.
    Which could be anything, from his Social Security number to an UUID to any other identifier that is unique enough for the Domain.

    • Vladimir Khorikov

      I agree, the article’s point could be expressed better, I’ll feature the comment you referenced for better visibility. Also, the example you provided is correct.

  • T204

    ID is a domain concern, it is not an implementation detail. You see IDs everywhere in the real world and there were IDs even before software systems. IDs are identifiers, it’s what you use to refer to the entity. If you call a food service because the order you had delivered was not correct, you give them the order ID – not all information about the order. Another thing I disagree with is that it seems that your aggregate is querying other aggregates (assuming _existingShipments is a repository). This is bad practice, your aggregate shouldn’t be querying about stuff, what will you do when you introduce asynchronous operations in your repository? Your aggregate will need to become asynchronous, which is a leak. Instead, pass the Shipment entity as a parameter.
    That way, the application layer will do the fetching. One thing I agree with is using equality operators to see if the entities are equal, and not compare the IDs directly, for the reason that you mentioned in this article.

  • Wouter

    When you agree that Id is an implementation detail and consider the database an implementation detail. I think an implementation example can clarify how to hide the Id? I would use an interface without Id and never expose the implementation only the interface. (Dependency Inversion.)