This is the first post in my series on Pragmatic DDD.

Every entity must be created, but how do we implement this? Which component decides when to create an entity? Which component contains the creation logic? In this post, we will explore various options, highlight their pros and cons, and hopefully come up with a guideline for future decisions.

<aside> đź’ˇ This post was initially focused on entity identifier generation. However, while writing it, I realized that the topic could be extended to any entity component that is not provided from an external source. Therefore, I decided to also introduce the creation timestamp to make the example more realistic. After further revision, I decided to expand the scope of this post to be about entity creation in general.

</aside>

For this study I will use the following model


case class Post(id: PostId, content: PostContent, createdAt: Instant)

I consider the generation of PostId and obtaining the current Instant to be an effect.

I consider determinism important for the sake of testability. Please see the pragmatic notes in each case to see how you can simplify things, if you don’t do unit testing and prefer integration testing.

The order of options corresponds to how far we push the concerns away from the very core of our system, i.e. domain.

Untitled

  1. Domain layer
    1. Entity companion object
    2. Entity factory
    3. Parent entity
  2. Application layer
  3. Infrastructure layer

Let’s introduce an alias type for out PostId generator

type PostIdGen = UIO[PostId]

In production wiring we will just use PostId.generate method.

Entity Companion Object

The idea is to put creation logic into companion object method. I inject the generator as one of the method’s parameters and Clock is provided by the ZIO runtime.

object Post {
	def create(generateId: PostIdGen, content: PostContent): UIO[Post] =
		for {
			id <- generateId
			now <- zio.Clock.instant
		} yield new Post(_, content, now) 		
}

And our application service