2

Let's start with an example: we have an entity: Book. It has unique identity: Isbn - a value object that wraps a String. This is an UUID.

The Book entity also needs a surrogate id from the repo (sql db). We need it so we can e.g. find the books in faster way, since databases find by number faster then by string.

From what I read, the surrogate key should be hidden from the Books interface. But we want to use it, to locate books much faster.

How to deal with this in a proper way?

[A] We can simply add a getSurrogateId() (or any better name) in the Book. This pollutes the entity, but its KISS.

[B] We can have the repo responsible for finding the surrogate keys for the natural ones. For example, BookRepository may have the following method:

long toSurrogateKey(Isbn isbn) {
     // lookup the cache
     // if not found, lookup the db
}

to return the surrogate key - of course, these values can be cached locally, so we do not need to search db every time. This method should not be public (right)?

[C] We can go even further: to think about surrogate key as a repository specific one. Book may be an interface, and SqlBook may be an repository-made implementation. This SqlBook implementation may then store any additional information needed for the repository. In this case, we would have the surrogate key as one of the properties of SqlBook - and we do not care it is visible, as users of SqlBook only sees it as a Book, i.e. not knowing about the surrogate id.

So above method becomes (defined in SqlBook class):

long toSurrogateKey(Book book) {
     return ((SqlBook)book).getSurrogateId();
}

The only drawback here is that Book (and other entities) must be created by a Factory that is repository-aware. In other words, we would need to have SqlFactory implementation of some factory that creates SqlBooks for us.

Any wisdom on this?

4

We need it so we can e.g. find the books in faster way, since databases find by number faster then by string.

Surrogate keys should primarily be added because they provide you a uniform way for building your primary keys, not because of any hypothetical performance issues. They will help you to avoid having business data like an Isbn distributed over half of your model in separate places because you misuse them as foreign keys.

"From what I read, the surrogate key should be hidden from the Books interface".

Maybe you just misunderstand the purpose of this? Surrogate keys are technical details which should be hidden when discussing the model with your domain experts, but it is perfectly ok to see them when you change your viewpoint to the implementation of the model. So go with [A], but make sure the getSurrogateId() accessor is not visible in your graphical form of your domain model.

  • Thanx! It's not hypothetical - it's implementation fact. But maybe it's not a 'surrogate key', I admit, just an 'additional technical/implementation information' of the Book. Anyway, I believe this is not just a matter of graphical visibility. The API should also express to developers the right usage. So if we expose this method as public one, developers may start using it for other stuff, instead of the real key. Then we do not need Isbn to be nothing more than just a simple value object. Any thought/experience? – lawpert Oct 31 '14 at 15:52
  • Honestly, your fears sound superstitious to me. I work with "technical keys" instead of "business keys" since almost 20 years and from that experience I can tell you you should encourage your devs to use the technical primary key instead of a business key whereever possible. The less places you use the business key as a unique identifier, the less places you will have to change when something changes in your business key (which will happen). – Doc Brown Oct 31 '14 at 16:03
  • 1
    Don't get me wrong. I also work with 'technical' keys all my life:) The focus here is not to have it working, but trying to figure the DDD concepts in practice. And the DDD says opposite, that we actually should use domain primary key in the code, too, as part of ubiquitous language. – lawpert Oct 31 '14 at 16:33
  • @lawpert: can you give a reference where "DDD says that"? I guess that's just a misunderstanding or misinterpreation. IMHO the usage of keys should be: use business keys like an ISBN in code when you have to deal with the "business meaning" of that key (for example: a end-users search function), and you use the technical or surrogate key whenever you need a key for persistent object identity. Here is a short article lostechies.com/jimmybogard/2008/06/05/designing-primary-keys reflecting exactly what I think about it. – Doc Brown Oct 31 '14 at 16:59
  • I think I am saying exactly the same: use business keys for domain talk, use tech key for underlaying persistence. But I also want to prevent to have developers choosing which one to use - from my point of view, that is dangerous in development environment. People may soon start using tech key for domain stuff. Therefore, the idea here is also to 'hide' the tech key until the place it is really used, in the repo/persistence. Would it make sense, in your opinion? – lawpert Oct 31 '14 at 21:56

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.