I have an aggregate entitled Payment and I expose a method called Capture. From the API controller I am invoking the aggregate like so:
var payment = _mapper.Map<Payment>(request); // auto mapper
var response = await payment.Capture(_paymentCaptureDecorator); // decorator injected into controller
Question I have I am using a decorator pattern to help me with this flow of calls as it:
One, attempts to retreive a payment from the database, if so short circuits and returns it
Second, makes the call to the bank (this is not done in the domain but the interface is defined but implemented in another class library)
Thirdly and lastly it saves the payment as an entity
In all 3 decorators they call into the aggregate as the sole job of the decorator is to perform some mapping and invoke the aggregate. For example:
public class AcquirerDecorator : IPaymentCaptureDecorator
{
private readonly IPaymentCaptureDecorator _decorator;
private readonly IAcquirerAdapter _acquirerAdapter;
private readonly IMapper _mapper;
public AcquirerDecorator(
IPaymentCaptureDecorator decorator,
IAcquirerAdapter acquirerAdapter,
IMapper mapper)
{
_decorator = decorator;
_acquirerAdapter = acquirerAdapter;
_mapper = mapper;
}
public async Task<PaymentResponse> Execute(Payment payment)
{
var acquirerRequest = _mapper.Map<AcquirerRequestDto>(payment);
await payment.AcquireFunds(_acquirerAdapter, acquirerRequest);
return await _decorator.Execute(payment);
}
}
The aggregate then does this:
public async Task AcquireFunds(IAcquirerAdapter acquirerAdapter, AcquirerRequestDto acquirerRequest)
{
AcquirerResponse = await acquirerAdapter.CaptureFunds(acquirerRequest); // sets state on aggregate
}
// Called by another decorator
public async Task Save(ISavePaymentCommand savePaymentCommand, PaymentTransactionEntity entity)
{
Card.Sanitise(); // modify state of the aggregate removing sensitive card info
if (AcquirerResponse.IsSuccessful)
{
await savePaymentCommand.Execute(entity);
}
}
This allows me to use constructor injection in the decorator and then pass the dependencies into the aggregate.
Arguably, the aggregate can do all of this but it would also mean I would need to use property injection or have a fairly big contructor. It would also mean that it would be aware of mapping data types which I don't think the aggregate should do.
Is this a perfectly OK thing to do?
Related
When mocking a service injected into a controller, a service method should return a mocked object, something like that:
public class EmptyInterventionServiceMock implements InterventionService {
#Override
public Intervention findByInvoiceNumber(String invoiceNumber, String language) {
return mockedIntervention(invoiceNumber, language);
}
protected Intervention mockedIntervention(String invoiceNumber, String language) {
return mock(Intervention.class);
}
}
Is it possible to mock some values to be return by the above mocked object (Intervention) to test fi they should be present in the generated JSON template ?
For example, depending on if Intervention has spare parts, services, states (all of them are just collections of other objects), etc. If so, JSON should contain the corresponding keys: services: [{....}], states: [{}], etc.
It would be nice to get the mocked object in the test and stub its return values. The only way I see to achieve that for the moment is to create a separate Mock service class and inject it in a test class as follows:
public class InterventionsControllerSpec extends ControllerSpec {
#Before
public void before() {
Injector injector = injector().bind(InterventionService.class).to(BaseInterventionServiceMock.class).create();
}
Where BaseInterventionServiceMock just extends EmptyInterventionServiceMock and stubs some methods return values by overriding its mockedIntervention method:
public class BaseInterventionServiceMock extends EmptyInterventionServiceMock {
#Override
protected Intervention mockedIntervention(String invoiceNumber, String language) {
Intervention intervention = mock(Intervention.class);
when(intervention.getString("ITV_DOCUMENT_NUMBER")).thenReturn("123");
when(intervention.getString("ITV_INVOICE")).thenReturn(invoiceNumber);
...
etc.
As it is far from ideal, I wonder if there is a DRYer way to do that ?
Thank you.
You are not missing anything. Your assumptions are correct. Creating a mock subclass of a service is how we do the testing. If you want a more elegant way, you can submit a proposal for consideration: https://github.com/javalite/activeweb/issues for consideration.
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.
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.
My current implementation for service and business layer is straight forward as below.
public class MyEntity { }
// Business layer
public interface IBusiness { IList<MyEntity> GetEntities(); }
public class MyBusinessOne : IBusiness
{
public IList<MyEntity> GetEntities()
{
return new List<MyEntity>();
}
}
//factory
public static class Factory
{
public static T Create<T>() where T : class
{
return new MyBusinessOne() as T; // returns instance based on T
}
}
//Service layer
public class MyService
{
public IList<MyEntity> GetEntities()
{
return Factory.Create<IBusiness>().GetEntities();
}
}
We needed some changes in current implementation. Reason being data grew over the time and service & client cannot handle the volume of data. we needed to implement pagination to the current service. We also expect some more features (like return fault when data is more that threshold, apply filters etc), so the design needs to be updated.
Following is my new proposal.
public interface IBusiness
{
IList<MyEntity> GetEntities();
}
public interface IBehavior
{
IEnumerable<T> Apply<T>(IEnumerable<T> data);
}
public abstract class MyBusiness
{
protected List<IBehavior> Behaviors = new List<IBehavior>();
public void AddBehavior(IBehavior behavior)
{
Behaviors.Add(behavior);
}
}
public class PaginationBehavior : IBehavior
{
public int PageSize = 10;
public int PageNumber = 2;
public IEnumerable<T> Apply<T>(IEnumerable<T> data)
{
//apply behavior here
return data
.Skip(PageNumber * PageSize)
.Take(PageSize);
}
}
public class MyEntity { }
public class MyBusinessOne : MyBusiness, IBusiness
{
public IList<MyEntity> GetEntities()
{
IEnumerable<MyEntity> result = new List<MyEntity>();
this.Behaviors.ForEach(rs =>
{
result = rs.Apply<MyEntity>(result);
});
return result.ToList();
}
}
public static class Factory
{
public static T Create<T>(List<IBehavior> behaviors) where T : class
{
// returns instance based on T
var instance = new MyBusinessOne();
behaviors.ForEach(rs => instance.AddBehavior(rs));
return instance as T;
}
}
public class MyService
{
public IList<MyEntity> GetEntities(int currentPage)
{
List<IBehavior> behaviors = new List<IBehavior>() {
new PaginationBehavior() { PageNumber = currentPage, }
};
return Factory.Create<IBusiness>(behaviors).GetEntities();
}
}
Experts please suggest me if my implementation is correct or I am over killing it. If it correct what design pattern it is - Decorator or Visitor.
Also my service returns JSON string. How can I use this behavior collections to serialize only selected properties rather than entire entity. List of properties comes from user as request. (Kind of column picker)
Looks like I don't have enough points to comment on your question. So, I am gonna make some assumption as I am not a C# expert.
Assumption 1: Looks like you are getting the data first and then applying the pagination using behavior object. If so, this is a wrong approach. Lets say there are 500 records and you are showing 50 records per fetch. Instead of simply fetching 50 records from DB, you are fetching 500 records for 10 times and on top of it you are adding a costly filter. DB is better equipped to do this job that C# or Java.
I would not consider pagination as a behavior with respect to the service. Its the behavior of the presentation layer. Your service should only worry about 'Data Granularity'. Looks like one of your customer wants all the data in one go and others might want a subset of that data.
Option 1: In DAO layer, have two methods: one for pagination and other for regular fetch. Based on the incoming params decide which method to call.
Option 2: Create two methods at service level. One for a small subset of data and the other for the whole set of data. Since you said JSON, this should be Restful service. Then based on the incoming URL, properly call the correct method. If you use Jersey, this should be easy.
In a service, new behaviors can be added by simply exposing new methods or adding new params to existing methods/functionalities (just make sure those changes are backward compatible). We really don't need Decorator or Visitor pattern. The only concern is no existing user should be affected.
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.