31

obj.id seems fairly common and also seems to fall within the range of something an object could know about itself. I find myself asking why should my object know its own id?

It doesn't seem to have a reason to have it? One of the main reason for it existing is retrieve it, and so my repositories need to know it, and thus use it for database interaction.

I also once encountered a problem where I wanted to serialize an object to JSON for a RESTful API where the id did not seem to fit in the payload, but only the URI and including it in the object made that more difficult.

Should an object know it's own id? why or why not?

update: Terms

  1. id: Identifier attribute on an object. in database terms, a surrogate key not a natural key.
  2. Object: an Entity, or otherwise uniquely identifiable object within the system.
9
  • 1
    To remain abstract, if there is no reason to store information, don't store it. It just creates headaches.
    – user7043
    Commented Sep 29, 2012 at 20:52
  • 3
    If you don't know the unique key of an object how would you update the data in a database or let the user select an occurrence from a list?
    – NoChance
    Commented Sep 29, 2012 at 21:40
  • 1
    @EmmadKareem what I'm saying is that the collection (repository) knows the id, so why does the object itself need to. If I was rendering a list I'd probably be rendering the collection, which knows the id's. Commented Sep 29, 2012 at 21:43
  • If you dont use the id thats stored with the object, and never intend or want to use it, its clearly not needed. Commented Sep 29, 2012 at 22:48
  • @GrandmasterB well of course you use the id, the question is whether you store the id in memory with the object, and why. Commented Sep 30, 2012 at 0:03

10 Answers 10

8

It's fairly common to include the ID, but it's also common to use dictionaries, i.e. the data structures where each object is associated with its ID in a way that you can easily retrieve this object knowing the corresponding ID, but the object doesn't know it.

For example, if you're creating an API with two methods:

Then you don't need to resend the ID 452 in the JSON response of the second request. The user of the API already knows the ID.

6

In an attempt to leave my answer as abstract as your question, I think you've actually answered your own question.

An object should know its own ID if it needs to.

An object shouldn't know its ID (or that it even has one) if it doesn't need to.

As you pointed out, there are cases where it is either inconvenient or unnecessary for the object to retain or know if its ID. But there are other cases where it is more convenient for the object to be aware of its ID. Code your objects as appropriate to their usage.

4
  • what cases is it convenient for it to be aware of its id? I've been pondering it and thinking that most of them could just be based on that's the way it was coded, perhaps a for loop used to render obj.id as opposed to rendering the collection itself. Commented Sep 29, 2012 at 21:46
  • 1
    @xenoterracide - asynchronous viewing and updating of DB records is one example. In some cases, I won't have sufficient information to uniquely identify a record except for its ID so it makes sense to keep the ID with the record object.
    – user53019
    Commented Sep 29, 2012 at 21:54
  • but is that a cause or an effect? is it a requirement? if your repository/collection/datamapper (or some chain thereof ) is responsible for persisting the updates, and it knows the id and is able to pass it on... I'm trying to understand if there's a reason for it following or if it's there because many people use and active record pattern. Commented Sep 29, 2012 at 21:58
  • @xenoterracide - in the cases I'm thinking of, it definitely was a causal need. For some cases I've been in, it was a lot more convenient to keep the ID associated with the object. Your question was good because it challenged a baseline assumption a lot of folk make. We tend to learn when we dig into assumptions like that. On the other hand, don't over analyze and go in the opposite direction. Otherwise you'll end up making the same time of sacrosanct declarations that you were breaking down in the first place.
    – user53019
    Commented Sep 30, 2012 at 0:25
6

Short Answer: Including object identifier within the object is a must if it is going to be referred.

For a scenario where you are planning to use a collection of objects and have plans to refer an individual object/entity then identifier should be included. However, there might be cases where natural key/identifier like DateTime can artificially fulfill that need.

In addition, you may have your DTO's as a lightweight container of your object, that may skip/include object identifier in itself. Really all this choices are really depend on your business use cases and needs.

Edit: if you want to identify your object you need to have an identifier. That identifier can be a surrogate Id, date-time, guid, etc... basically, anything that identifies your object from others in a unique way.

4
  • 4
    why should they be included in the object, rather than just the collection (assuming the collection is some kind of dictionary)? Commented Sep 29, 2012 at 21:40
  • my point was that, if you want to identify your object you need to have an identifier. it can be Id, date-time, etc... anything that identifies your object from others.
    – Yusubov
    Commented Sep 29, 2012 at 21:52
  • 2
    well of course, my question is more of why the object itself needs to be aware of that identifier. Commented Sep 29, 2012 at 22:09
  • to clarify a bit I mean a surrogate id, usually things like datetime's, or vin numbers, are natural and thus part of the data, and not named id (or at least I wouldn't) Commented Sep 29, 2012 at 22:19
5

I think that this is subjective and depends on your design.

Mostly though this appears to be a design that comes from an active record. In an active record your entity has methods to do database operations and therefore must also know it's database identifier.

When using other patterns such as a repository with a data mapper storing this data in the object becomes unnecessary and perhaps inappropriate.

Take for example a Person object. I am given a name which may or may not be unique within a family. As the population has grown larger names are no longer unique and so we have come up with surrogate identifiers for increasingly large system. Examples of these include: my drivers license, and social security number. I am not born assigned an id, all of these id's must be applied for.

Most of these do not make good primary keys/ids for software, as they are not universal. At least not outside of their specific system, obviously an SSN is unique, and consistent, to the Social Security Administration. Since we are not generally the providers of this information you would not call them an id but rather the data they represent, e.g. SSN. Sometimes even contain the full composed object such as a DriversLicense which could contain all of the information the driver's license does.

All general id's are thus surrogate keys in the system, and could be replaced with in memory references, only containing id's to make looking up and persisting records easier.

Since an id is not a piece of conceptual data, I doubt that it (generally) belongs within the object, as it does not come from the domain. Rather it should be retained to its purpose which is to identify an object which has no other way to represent a unique identity. This could be done in a repository/collection with easy.

In software if you need to represent the object as a list, or persist it, you can simply do so from the repository/collection object, or some other object associated with that. When passing on to the Data Mapper (if it's separate), you can simply pass .update( id, obj ).

Disclaimer: I have not yet tried to build a system that does not contain the id within the entity and thus may prove myself wrong.

2

As GlenH7 noted in a comment, it's a good question, because it challenges what many people take for granted. My take on it however is that even if leaving the id out might seem conceptually pure, the pragmatic thing to do would be to keep the id with the object across as many layers of the system as possible. It costs little, but can come in handy when things start to break down.

An entity might not need to know it's id, just like a person doesn't need to know his personal identification number, driver license number nor any other identifier that might be in use in your location. You could certainly do without it most of the time. It's wise however to carry some kind of identification on you, just in case.

The same can be said of an object. Regardless of the data access layer's intricacies, the object ultimately maps to a certain database entry. This entry might only be uniquely identifiable by object's id. If so, then I would prefer to have this information available to me at any time, regardless whether I'm debugging some UI code, number crunching in the business layer, the repository itself or a dependent system across a webservice. Or whether I'm browsing error logs for that matter.

In your case, if you're only fetching data from the db and pushing it through the webservice, leaving the id out might be be the right thing to do. I just don't believe that it makes more sense than keeping it in the general case.

1
  • "It's wise however to carry some kind of identification on you, just in case." I like that formulation.
    – xtofl
    Commented Jan 4, 2021 at 9:06
2

You are right, you don't need to store the id in the object, as long as you only need to know it in your repository context.

The situation changes when you pass the object to code outside that context, code that did not request the object by id (and therefore doesn't know it yet), but needs the id for whatever purpose (eg. to place it on a list of ids that will be requested from the repository later, by yet another code).

In that situation, you have two options:

  • introduce a new function argument 'id' in the whole chain of functions between the repository context and the function where the id is needed

  • include the id in the object

In most of these cases, storing the id inside the object will be the better solution. It will also reduce code changes when the id is needed in unforeseen places, plus it might be helpful with debugging at times.

That's why I do it when I do it.

1
  • Or ask the repository for object's id.
    – Basilevs
    Commented Oct 5, 2021 at 9:24
1

Because I like real world analogies: It would be decidedly more efficient if people kept their passports (or other identifying documents) on their person, instead of them being stored in some separate location.

The question is how you intend to link them when you need to, if you're storing them separately. This wouldn't be a problem if you're already storing the ID with the object that the ID identifies.

So the question becomes: what benefit are you trying to gain by separate the two; and does it outrank the added complexity and effort of having to handle and deal with a separated ID and identifiable object?


I also once encountered a problem where I wanted to serialize an object to JSON for a RESTful API where the id did not seem to fit in the payload, but only the URI and including it in the object made that more difficult.

This is the part where you have to consider that this particular API chose to have an API model (= without ID) that was different from the underlying domain model (= with ID).

Generally speaking, I'll advocate against reusing the domain model as the API model. However, if you want to do pure REST (and I mean 100% pure), then yeah you could get away with reusing your domain model. But at the same time, it wouldn't be the end of the world to include the ID both in the model and in the URL, regardless of whether you reuse your domain model or not.

One of the main reason for it existing is retrieve it, and so my repositories need to know it, and thus use it for database interaction.

You're glossing over the fact that someone asks the repositories to retrieve them, and that someone obviously needs to know the ID before they are able to ask the repository (directly or indirectly) what resource to retrieve using this ID.

Not providing an ID in a REST resource would cause issues down the line when the URL does not contain the identifier for the resource being returned. For example, /api/author/123/articles would return you a collection of articles written by author 123. But if the article IDs aren't in the article model themselves, how do you expect the consumer to be able to call any article-specific endpoints?

Adding the ID into the resource makes it significantly easier to track the identifier for a given object, instead of sending the consumer on a magical quest to find the link between a fabled identifier that's somehow not found with the object that it identifies.

2
  • > how do you expect the consumer to be able to call any article-specific endpoints? you'd have to wrap the action object in some way. Commented May 1 at 17:20
  • @xenoterracide The problem I'm pointing out is unrelated to action objects, it's related to how you expect your client to be able to refer to a specific article in a subsequent request, if the initial request (which does return articles) does not contain the identifiers of said articles? This is purely a matter of how you expect someone to be able to find out what an identifier to a resource is, which is obviously a prerequisite to any endpoint which would require the client to use such an identifier.
    – Flater
    Commented May 1 at 23:26
0

An object should probably not know its own ID most of the time.

The object is not identified by itself nor within itself but by some other part of the system and within the system, where it is identified in relation to other objects that might be similar to it.

The key here is that identifying an object implies the existence of other objects that you are distinguishing it from. The context of the Id is not the object but something that contains the object. So unless you have the common kind of dirty code where the business logic is built on top of the database schema, the object should probably not know its own ID in most cases. The fact that you need it for persistence does not mean that you have to have it inside the object itself, it just needs to be directly related to the object. Your persistence may need it, but not the object for the business logic.

Maybe if the object needs to inform itself directly to others of its ID for some reason, you would need to break this principle, but in general, I think it just makes sense and it will save you from having some messy duplicated indexes(or ids, which are most of the time functionally the same thing). I can't think of an example of this counter, but I am sure they exist.

0

My two cents

Two situations when an object should know its own ID:

  1. When ID column (or whatever column is used as ID) happens to also be a business key.
  2. For debudding purposes, so you can inspect the ID.
0

Something not mentioned in other answers is that whether an object should know its own ID depends on the type of ID.

If the id is sequential (ie 1, 2, 3, ...), or otherwise at risk of collisions, then probably no - it shouldn't know its own ID. This id refers to the object's position in a collection, and may need to be changed if collections are merged or reindexed for some reason. That means your object will either have to be mutable, or it will become "invalid" after the collection that its ID implicitly referred to has undergone the merge/reindexing.

If the id is random (e.g. a ULID like 01HW8Z5QBGE0JR7TY6KC2XRKVS), then probably yes - it should know its own ID. There is likely no reason you'll ever have to change this ID - and you don't have to think of the id as implicitly referring to the collection. A merger of two collections does not require changing IDs, and your object can be immutable.

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