Persisting an Entity that is a part of an Aggregate - domain-driven-design

Consider we have a BankCard Entity that is a part of Client Aggregate. Client may want to cancel her BankCard
class CancellBankCardCommandHandler
{
public function Execute(CancelBankCardCommand $command)
{
$client = $this->_repository->get($command->clienId);
$bankCard = $client->getBankCard($command->bankCardId);
$bankCard->clientCancelsBankCard();
$this->_repository->add($client);
}
}
class BankCard implements Entity
{
// constructor and some other methods ...
public function clientCancelsBankCard()
{
$this->apply(new BankCardWasCancelled($this->id);
}
}
class Client implements AggregateRoot
{
protected $_bankCards;
public function getBankCard($bankCardId)
{
if (!array_key_exists($bankCardId, $this->_bankCards) {
throw new DomainException('Bank card is not found!');
}
return $this->_bankCard[$bankCardId]);
}
}
Finally we have some domain repository instance which is reponsible for storing Aggregates.
class ClientRepository implements DomainRepository
{
// methods omitted
public function add($clientAggregate)
{
// here we somehow need to store BankCardWasCancelled event
// which is a part of BankCard Entity
}
}
My question is whether AggregateRoot responsible for tracking its Entities' events or not. Is it possible to get events of an Entity which is a part of an Aggregate from within its Aggregate or not?
How to actually persist the Client with all changes made to the bank card saving its consistency?

I would say the aggregate as a whole is responsible for tracking the changes that happened to it. Mechanically, that could be "distributed" among the aggregate root entity and any other entities within the aggregate or the aggregate root entity as the sole recorder or some external unit of work. Your choice, really. Don't get too hung up on the mechanics. Different languages/paradigms, different ways of implementing all this. If something happens to a child entity, just consider it a change part of the aggregate and record accordingly.

Related

DDD: should local Entity identity include the parent's?

In DDD, Entities have this concept of identity that uniquely identifies every instance regardless of all the other properties. Usually this identity has to be unique among the BC in which the Entity live, but there is an exception.
Sometimes we need to create Aggregates that are not only made by the root Entity and some Value Objects but have one or more child / nested Entities (that I understand to be called local Entities). For this kind of Entities the identity has only to be locally unique i.e. unique among the Aggregate boundaries.
Given this, let's also consider the fact that are two way to model a has-a relationship in DDD, depending on the actual business needs: separate Aggregates or Aggregate Root + child Entities.
In the first case the "child" Aggregate of the relation has a reference to the identity of the parent one, which in turn usually has a factory method to create and return an instance of the child:
class ForumId extends ValueObject
{
// let's say we have a random UUID here
// forum name is not a suitable identifier because it can be changed
}
// "parent" aggregate
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
method startNewThread(ThreadId threadId, string title): Thread
{
// make some checks, maybe the title is not appropriate for this forum
// and needs to be rejected
...
// passing this forum's ID,
return new Thread(this->_forumId, threadId, title)
}
}
class ThreadId extends ValueObject
{
// let's say we have a random UUID here
// thread title is not a suitable identifier because it can be changed
}
// "child" aggregate
class Thread extends AggregateRoot
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
If we consider instead the second case, let's say because for some business reason we need to have Thread as a local entity of Forum, what is the correct way to identify it? Should Thread still contain the ForumId of the parent Forum or it is redundant since it will only live inside that specific Forum and never accessed outside?
Which way is better and more importantly why? May the data model (i.e. the database level) steer the decision toward one way or another, or should we still ignore it as per good DDD design?
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
private List<Thread> _threads;
method startNewThread(string title): ThreadId
{
// or use and injected `ThreadIdentityService`'s `nextThreadId(ForumId)` method
var threadId = this.generateNextLocalThreadId()
var newThread = new Thread(/*this->_forumId, */ threadId, title)
this._threads.append(newThread)
return threadId
}
}
// "child" aggregate - case 1
class Thread extends LocalEntity
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
// "child" aggregate - case 2
class Thread extends LocalEntity
{
private ThreadID _threadId;
private string _title;
}
So the main purpose of having an aggregate is to make any change to this aggregate atomic.
The aggregate root contains the full child entity inside, for example Forum would have a collection of Threads.
Since the Thread is already inside a Forum wouldn’t make any sense having ForumId inside since the repository in charge of saving it would already know that id because we’d save the whole forum not a single thread.
Also wanted to add that Forum aggregate seems to be a huge aggregate, that implies some trade offs that you should take into account.

How to get an immutable entity from its aggregate in DDD

An aggregate (Article) has an entity (SmsContent) with a property (enabled) that only can change if a condition on the aggregate is met.
e.g.
<?php
//Aggregate
class Article {
/** #var User */
protected $user;
/** #var SmsOutput */
protected sms;
...
public function enableSms() {
if($this->user->hasPermission('sms')) {
throw new PermissionDeniedException('sms');
}
$this->sms->enable();
retutn $this;
}
public function getSms() {
return $this->sms;
}
...
}
//Entity
class SmsOutput {
/** #var boolean */
protected enabled = false;
...
public function enable() {
$this->enable = true;
}
...
}
How should you get the SmsContent entity from the Article without being able to change the enabled property from outside the aggregate?
For example:
$article->getSms()->enable();
How is this handled in DDD?
You have multiple options, depending on the architecture.
1. Use CQRS
In CQRS the Write is separated from the Read. This means that you don't interrogate the Aggregate, ever. You don't have any getters, only command handlers. If you can't interrogate the Aggregate you can't access any nested entity either. If you need to get data you do it only from a projection/read model that are read-only by default.
2. Use a different interface for returned entities
In this case you return the entity but it is type-hinted as being a sub-set of the actual entity. In your case you could have something like this:
<?php
interface SmsOutput
{
//...
public function isEnabled(): bool;
//...
}
//Entity
class SmsOutputWritable implements SmsOutput
{
/** #var boolean */
private $enabled = false;
//...
public function enable()
{
$this->enabled = true;
}
public function isEnabled(): bool
{
return $this->enabled;
}
//...
}
//Aggregate
class Article
{
/** #var User */
private $user;
/** #var SmsOutputWritable */
private $sms;
//...
public function enableSms(): void //no return values, see CQS
{
if ($this->user->hasPermission('sms')) {
throw new PermissionDeniedException('sms');
}
$this->sms->enable();
}
public function getSms(): SmsOutput
{
return $this->sms;
}
//...
}
Although the caller gets a SmsOutputWritable it does not know about this.
P.S. Anyway, even if the caller knows (or casts) that the returned value is SmsOutputWritable and call SmsOutputWritable::enable() nothing really happens because the caller can't persist the changes to the repository, only entire aggregates can be persisted not individual nested entities. This is because aggregates and/or nested entities don't persist themselves, only an Application service can do this, using a repository.
How should you get the SmsContent entity from the Article without being able to change the enabled property from outside the aggregate?
Short answer: You don't. You get an immutable representation (ie: a value type) of the SmsContent.State from the Aggregate Root.
That's the approach taken by Evans in Domain Driven Design. There have been a couple of innovations that have gained traction since then.
One is the idea that a single entity can serve in multiple roles. Rather than having a single repository that serves many different use cases, you might have many repositories that handle specific cases. Here, that might look like a repository that returns the Aggregate Root when you want to be able to change something, and a different repository that returns a view/projection for use cases that only inspect the data.
This separation goes really well with ideas like lazy loading; if you aren't going to need some data for a particular use case, you interact with a repository that doesn't load it.
Udi Dahan's essay Better Domain-Driven Design Implementation provides a high level overview.
This looks a lot like the CQRS suggestion of Constantin. I mean, when you start using different repositories for reads and writes, then you're already with one feet in CQRS
It does, but there are a few intermediate steps along the way; CQS, responsibility driven design.

Aggregate root and instances creation of child entities

I have an aggregate that includes the entities A, AbstractElement, X, Y and Z. The root entity is A that also has a list of AbstractElement. Entities X,Y and Z inherit from AbstractElement. I need the possibility to add instances of X, Y and Z to an instance of A. One approach is to use one method for each type, i.e. addX, addY and addZ. These methods would take as arguments the values required to create instances of X, Y and Z. But, each time I add a new type that inherits from AbstractElement, I need to modify the entity A, so I think it's not the best solution.
Another approach is to use an abstract add method addAbstractElement for adding AbstractElement instances. But, in this case, the method would take as argument an instance of AbstractElement. Because this method would be called by entities located outside of the aggregate, following DDD rules/recommandations, are these external entities authorized to create instances of AbstractElement? I read in the Eric Evans book that external entities are not authorized to hold references of entities of an aggregate other than the root?
What is the best practice for this kind of problem?
Thanks
From Evan's book, page 139:
"if you needed to add elements inside a preexisting AGGREGATE, you might create a FACTORY METHOD on the root of the AGGREGATE"
Meaning, you should create a factory method on the root (A) which will get the AbstractElement's details. This method will create the AbstractElement (X/Y/Z) according to some decision parameter and will add it to its internal collection of AbstractElements. In the end this method return the id of the new element.
Best Regards,
Itzik Saban
A few comments. As the previous answerer said, it's a good practice to use a factory method. If you can avoid it, never create objects out of the blue. Usually, it's a pretty big smell and a missed chance to make more sense out of your domain.
I wrote a small example to illustrate this. Video is in this case the aggregate root. Inside the boundaries of the aggregate are the video object and its associated comments. Comments can be anonymous or can have been written by a known user (to simplify the example, I represented the user by a username but obviously, in a real application, you would have something like a UserId).
Here is the code:
public class Video {
private List<Comment> comments;
void addComment(final Comment.Builder builder) {
this.comments.add(builder.forVideo(this).build());
// ...
}
}
abstract public class Comment {
private String username;
private Video video;
public static public class Builder {
public Builder anonymous() {
this.username = null;
return this;
}
public Builder fromUser(final String username) {
this.username = username;
return this;
}
public Builder withMessage(final String message) {
this.message = message;
return this;
}
public Builder forVideo(final Video video) {
this.video = video;
return this;
}
public Comment build() {
if (username == null) {
return new AnonymousComment(message);
} else {
return new UserComment(username, message);
}
}
}
}
public class AnonymousComment extends Comment {
// ...
}
static public class UserComment extends Comment {
// ...
}
One thing to ponder on also is that aggregate boundaries contain objects and not classes. As such, it's highly possible that certain classes (mostly value objects but it can be the case of entities also) be represented in many aggregates.

Message-based domain object collaboration

Recently, i was thinking about how to use message to implement the domain object collaboration. And now i have some thoughts:
Each domain object will implement an interface if it want to response one message;
Each domain object will not depend on any other domain objects, that means we will not have the Model.OtherModel relation;
Each domain object only do the things which only modify itself;
Each domain object can send a message, and this message will be received by any other domain objects which are care about this message;
Totally, the only way of collaboration between domain objects is message, one domain object can send any messages or receive any messages as long as it need.
When i learn Evans's DDD, i see that he defines the aggregate concept in domain, i think aggregate is static and not suitable for objects interactions, he only focused on the static structure of objects or relationship between objects. In real world, object will interact using messages, not by referencing each other or aggregating other objects. In my opinion, all the objects are equal, that means they will not depend on any other objects.
For about how to implement the functionality of sending messages or receive messages, i think we can create a EventBus framework which is specially used for the collaboration of domain object. We can mapping the event type to the subscriber type in a dictionary. The key is event type, the value is a list of subscriber types. When one event is raised, we can find the corresponding subscriber types, and get all the subscriber domain objects from data persistence and then call the corresponding handle methods on each subscriber.
For example:
public class EventA : IEvent { }
public class EventB : IEvent { }
public class EventC : IEvent { }
public class ExampleDomainObject : Entity<Guid>{
public void MethodToRaiseAnExampleEvent()
{
RaiseEvent(new EventC());
}
}
public class A : Entity<Guid>, IEventHandler<EventB>, IEventHandler<EventC> {
public void Handle(EventB evnt)
{
//Response for EventB.
}
public void Handle(EventC evnt)
{
//Response for EventC.
}
}
public class B : IEventHandler<EventA>, IEventHandler<EventC> {
public void Handle(EventA evnt)
{
//Response for EventA.
}
public void Handle(EventC evnt)
{
//Response for EventC.
}
}
That's my thoughts. Hopes to hear your words.
Have you ever heard of event sourcing or CQRS?
It sounds like that's the direction your thoughts are heading.
There's a lot of great info out there. Many good blog posts about CQRS and Domain Events, messaging-based domains.
Some example implementations are available, and there's a helpful and active community where implementation details can be discussed.

Proper way to secure domain objects?

If I have an entity Entity and a service EntityService and EntityServiceFacade with the following interfaces:
interface EntityService {
Entity getEntity(Long id);
}
interface EntityServiceFacade {
EntityDTO getEntity(Long id);
}
I can easily secure the read access to an entity by controlling access to the getEntity method at the service level. But once the facade has a reference to an entity, how can I control write access to it? If I have a saveEntity method and control access at the service (not facade) level like this (with Spring security annotations here):
class EntityServiceImpl implements EntityService {
...
#PreAuthorize("hasPermission(#entity, 'write')")
public void saveEntity(Entity entity) {
repository.store(entity);
}
}
class EntityServiceFacadeImpl implements EntityServiceFacade {
...
#Transactional
public void saveEntity(EntityDTO dto) {
Entity entity = service.getEntity(dto.id);
entity.setName(dto.name);
service.save(entity);
}
}
The problem here is that the access control check happens already after I have changed the name of the entity, so that does not suffice.
How do you guys do it? Do you secure the domain object methods instead?
Thanks
Edit:
If you secure your domain objects, for example with annotations like:
#PreAuthorize("hasPermission(this, 'write')")
public void setName(String name) { this.name = name; }
Am I then breaking the domain model (according to DDD?)
Edit2
I found a thesis on the subject. The conclusion of that thesis says that a good way IS to annotate the domain object methods to secure them. Any thoughts on this?
I wouldn't worry about securing individual entity methods or properties from being modified.
Preventing a user from changing an entity in memory is not always necessary if you can control persistence.
The big gotcha here is UX, you want to inform a user as early as possible that she will probably be unable to persist changes made to that entity. The decision you will need to make is whether it is acceptable to delay the security check until persistence time or if you need to inform a user before (e.g. by deactivating UI elements).
If Entity is an interface, can't you just membrane it?
So if Entity looks like this:
interface Entity {
int getFoo();
void setFoo(int newFoo);
}
create a membrane like
final class ReadOnlyEntity implements Entity {
private final Entity underlying;
ReadOnlyEntity(Entity underlying) { this.underlying = underlying; }
public int getFoo() { return underlying.getFoo(); } // Read methods work
// But deny mutators.
public void setFoo(int newFoo) { throw new UnsupportedOperationException(); }
}
If you annotate read methods, you can use Proxy classes to automatically create membranes that cross multiple classes (so that a get method on a readonly Entity that returns an EntityPart returns a readonly EntityPart).
See deep attenuation in http://en.wikipedia.org/wiki/Object-capability_model for more details on this approach.

Resources