Reputation: 11
I am just getting my feet wet with my first Domain-driven Design project. The project's domain model involves a bounded context that deals with collision detection of moving geometries located in a three-dimensional scene.
A central part of the business logic would be the collision detection algorithm aka the CollisionDetector. The algorithm must be configured with some parameters that influence its behaviour and performance. So it has some state attached making me think of it as an entity or rather an aggregate in the first place. Note that there is no requirement to persist this entity to the DB - all its parameter values are transient. Also note that there is only a single CollisionDetector instance present in the domain, so implementing an in-memory repository giving access to that single aggregate seems a bit overdone to me.
Summing things up we have a stateful, transient entity with a singleton nature.
So here is my question: While "normal" aggregates in DDD should always be accessed via repositories, how should I deal with such a unique entity instance?
Please let me now if you need more context to help me with this issue.
P.S. And excuse my broken english. I'm not a native speaker.
Edit:
I feel I should give some further detail on CollisionDetector
class and the state attached to it.
Maybe calling it transient was misleading. My intention was to point out that CollisionDetector
will never be persisted to a storage. Its entire life is spent in active memory. Creation, modification and deletion are all part of its life cycle, persistence is not.
Another important quality of CollisionDetector
is what I refer to as its singleton nature meaning that CollisionDetector
is instanciated only once (but not necessarily using the GoF Singleton pattern). I am not sure whether the concept of identity is applicable to a singleton instance (at least there is no need for identification as there is just one), which is the only thing that keeps me from making CollisionDetector
an entity/aggregate.
So let me shed some light on CollisionDetector
's state as requested by @plalx, @guillaume31 and @arootbeer.
CollisionDetector
keeps track of the geometries and their pose inside the scene. This is achieved via Domain Events: When one of the geometries changes its pose an event handler will automatically trigger a collision test. Likewise newly detected collisions are published by the CollisionDetector
via Domain Events as well. Note that not all geometries are considered to be collision candidates, the user may exclude some of them from the test. Hence the CollisionDetector
holds a blacklist of geometry ids (beeing part of its state).CollisionDetector
. Whenever a geometry is added to or removed from the scene, the preprocessing becomes stale and needs to be refreshed. The CollisionDetector
is aware of that i.e. it knows whether a re-initialization is required or not.Hope this helps!
Rethinking my question I must admit that it's merely academic. A pragmatic solution could be to make CollisionDetector
an aggregate and just register it with the IoC container. What do you think?
Upvotes: 1
Views: 1014
Reputation: 18034
The algorithm must be configured with some parameters that influence its behaviour and performance. So it has some state attached making me think of it as an entity or rather an aggregate in the first place. (emphasis mine)
I don't consider the configuration of the CollisionDetector
to be its state. It is only configuration and cannot change once the CollisionDetector
is instantiated, so it is something much simpler than mutable state that you typically find in entities.
As a consequence, I clearly consider the CollisionDetector
a domain service. This means you should handle it as follows:
Register the CollisionDetector
service in IoC. The configuration of the CollisionDetector
is probably considered domain logic, so it could make sense to instantiate the CollisionDetector
in a CollisionDetectorFactory
. If that's the approach you take, register the factory in IoC instead. In any case, make sure the clients of the CollisionDetector
don't have to know about its configuration.
By the way, don't use singletons (i.e. the GoF singleton pattern) when you work with IoC. You can always register a service as single instance, which has the same effect as the singleton pattern, but avoids its problems.
Upvotes: 2