Domain Driven Design - I find it hard to come up with a solution for this kind of business logic - domain-driven-design

Introduction
Let's say I have three Domain Objects:
Proposition
Phase
Task
A Proposition can have one or more Phases. A Phases can have one or more Tasks.
If I completed the last Task in the last Phase, the Proposition must be set to 'Closed'.
In code I've created something like this to complete the last Task of a Phase
//My Business Layer does this:
--------------------------------------
pseudo:
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();
// My Domain Entities look like this:
------------------------
public class phase()
{
public Task LastTask { get; set; } // not real code of course
}
public class Task()
{
public Phase Phase { get; set; }
public void SetComplete()
{
Phase.IsFinished = true;
}
}
Question
Where do I put the code to set the Proposition to 'Closed'?
Options
I think have a few options:
1) In the Domain Entity: Task.SetComplete
public class Task()
{
public Phase Phase { get; set; }
public void SetComplete()
{
Phase.IsFinished = true;
Phase.Proposition.IsClosed = true;
}
}
2a) In the Business Layer
var phase = _phaseRepository.GetById(id);
phase.LastTask.SetComplete();
var proposition = _propositionRepository.GetById(phase.PropositionId);
proposition.IsClosed = true;
2b) In the Business Layer, maybe a bit nicer way:
var phase = _phaseRepository.GetByIdIncludingProposition(id);
phase.LastTask.SetComplete();
phase.proposition.SetClosed();
3) Let everything pass thru Proposition:
//My Business Layer:
var proposition = _propositionRepository.GetById(id);
proposition.CompleteTask(taskId);
// Domain Object:
public class Proposition()
{
public List<Phase> Phases { get; set; }
public void CompleteTask(long taskId)
{
var task = // psuedo: select relevant task from Phases.Tasks, using taskid
task.SetComplete();
task.Phase.SetFinished();
//psuedo: if task.Phase is last phase in proposition
Phase.Proposition.IsClosed = true;
}
}
About the options
Option 1 is problematic on the line
Phase.Proposition.IsClosed = true;
because Proposition doesn't have to be loaded, and if it's not loaded we get an exception.
Option 2a is problematic because after phase.LastTask.SetComplete() is executed the proposition is not in the correct state. And everywhere in code where one has access to Phase, "phase.LastTask.SetComplete()" can be executed without doing the relevant operations on Proposition.
Option 2b has the same problem as 2a.
Option 3 gives the Proposition class too much responsibilities.
Do you guys have any suggestions?

I'm guessing that Proposition is the aggregate root.A task is part of a proposition in the end and I think that the Tssk should notify that is completed i'd try this approach (basically option 3 a bit modified)
public class Proposition()
{
public Task GetTask(int taskId)
{
//find and return task
}
}
//in business layer
var p= _repository.GetProposition(id);
p.GetTask(taskId).SetComplete();
public class Task
{
public event Action<Task> Completed;
public void SetComplete()
{
if (Completed!=null) Completed(this);
}
The Phase should handle the completed event of Task and when it is triggerd, chek if it's the last task and notify the proporisiton to closeitself. NOw maybe using events is not the best implemetnation, probably the Observer pattern is better, but the main ideas are:
You get a task via a Proposition method (as Proposition is an AR)
Tasks notifies phase when it's finished
Phase notifies proposition when the last task is completed
Proposition should check if there aren't any phases in progress and close itself.
save Proposition in the repository
Come to think of it, this is basically the domain event pattern.

Related

Delete entity after specified time with JpaRepository

I am using Spring Boot and H2 db. I have a Product entity and I want my application to be able to remove the product from the database, but my requirement is this: first set the active flag to false ( then this row will not be taken into account during fetching ) and after a specific period of time completely remove this row from db.
#Entity
#Table(name = "products")
public class Product {
#Id
#GeneratedValue(generator = "inc")
#GenericGenerator(name = "inc", strategy = "increment")
private int id;
private boolean active = true;
// getters & setters
}
And my method from the service layer responsible for setting the active flag to false and later complete deletion (I have nothing that does the second part of my requirement - complete deletion after specific period of time)
#Transactional
public void deleteProduct(int id) {
var target = repository.findProductById(id)
.orElseThrow(() -> new IllegalArgumentException("No product with given id"));
target.setActive(false);
// what should I add here to remove the target after a specific time?
}
EDIT
OK, I solved my problem:
#Transactional
public void deleteProduct(int id) {
var target = repository.findProductByIdAndActiveTrue(id)
.orElseThrow(() -> new IllegalArgumentException("No product with gicen id"));
target.setActive(false);
// complete removal after 150 seconds
new Thread(() -> {
try {
Thread.sleep(150000);
repository.deleteById(id);
} catch (Exception e) {
logger.error("Error removing the product");
}
}).start();
}
But now my question is if this is a safe solution as the user may start too many threads now so I think there is a better solution to my problem (safer in terms of multithreading)
I am not an expert but i think what you trying to achieve is bad practice.
I believe you should do a scheduling, for example ones per day.
You should update in db the value active. Set a schedule that will check the entries each time and if they have an active value of false then delete. Something like this:
public void deleteProduct(int id) {
//update value to false
repository.updateProductValue(id,false);
}
and your scheduling method:
#Scheduled(fixedRate = 150000)
public void deleteNonActiveProducts() {
List<Product> products = repository.findAllByFalseValue();
products.forEach(product -> repository.deleteById(product.getId());
}
With this what you are doing is that every 150000 milliseconds you repeat that task and each execution of this task is independent and non parallel.
Hope is useful to you.

DDD entity with complex creation process

How entities with complex creation process should be created in DDD? Example:
Entity
- Property 1
- Property 2: value depends on what was provided in Property 1
- Property 3: value depends on what was provided in Property 1
- Property 4: value depends on what was provided in Property 1, 2 and 3
I have two ideas but both looks terrible:
Create entity with invalid state
Move creation process to service
We are using REST API so in first scenario we will have to persist entity with invalid state and in second scenario we move logic outside of the entity.
You can use the Builder Pattern to solve this problem.
You can make a Builder that has the logic for the dependencies between properties and raise Exceptions, return errors or has a mechanism to tell the client which are the next valid steps.
If you are using an object orienterd language, the builder can also return different concrete classes based on the combination of these properties.
Here's a very simplified example. We will store a configuration for EventNotifications that can either listen on some Endpoint (IP, port) or poll.
enum Mode { None, Poll, ListenOnEndpoint }
public class EventListenerNotification {
public Mode Mode { get; set; }
public Interval PollInterval { get; set; }
public Endpoint Endpoint { get; set; }
}
public class Builder {
private Mode mMode = Mode.None;
private Interenal mInterval;
private Endpoint mEndpoint;
public Builder WithMode(Mode mode) {
this.mMode = mode;
return this;
}
public Builder WithInterval(Interval interval) {
VerifyModeIsSet();
verifyModeIsPoll();
this.mInterval = interval;
return this;
}
public Builder WithEndpoint(Endpoint endpoint) {
VerifyModeIsSet();
verifyModeIsListenOnEndpoint();
this.mInterval = interval;
return this;
}
public EventListenerNotification Build() {
VerifyState();
var entity = new EventListenerNotification();
entity.Mode = this.mMode;
entity.Interval = this.mInterval;
entity.Endpoint = this.mEndpoint;
return entity;
}
private void VerifyModeIsSet() {
if(this.mMode == Mode.None) {
throw new InvalidModeException("Set mode first");
}
}
private void VerifyModeIsPoll() {
if(this.mMode != Mode.Poll) {
throw new InvalidModeException("Mode should be poll");
}
}
private void VerifyModeIsListenForEvents() {
if(this.mMode != Mode.ListenForEvents) {
throw new InvalidModeException("Mode should be ListenForEvents");
}
}
private void VerifyState() {
// validate properties based on Mode
if(this.mMode == Mode.Poll) {
// validate interval
}
if(this.mMode == Mode.ListenForEvents) {
// validate Endpoint
}
}
}
enum BuildStatus { NotStarted, InProgress, Errored, Finished }
public class BuilderWithStatus {
private readonly List<Error> mErrors = new List<Error>();
public BuildStatus Status { get; private set; }
public IReadOnlyList<Error> Errors { get { return mErrors; } }
public BuilderWithStatus WithInterval(Interval inerval) {
if(this.mMode != Mode.Poll) {
this.mErrors.add(new Error("Mode should be poll");
this.Status = BuildStatus.Errored;
}
else {
this.mInterval = interval;
}
return this;
}
// rest is same as above, but instead of throwing errors you can record the error
// and set a status
}
Here are some resources with more information and other machisms that you can use:
https://martinfowler.com/articles/replaceThrowWithNotification.html
https://martinfowler.com/eaaDev/Notification.html
https://martinfowler.com/bliki/ContextualValidation.html
Take a look at chapter 6 of the Evans book, which specifically talks about the life cycle of entities in the domain model
Creation is usually handled with a factory, which is to say a function that accepts data as input and returns a reference to an entity.
in second scenario we move logic outside of the entity.
The simplest answer is for the "factory" to be some method associate with the entity's class - ie, the constructor, or some other static method that is still part of the definition of the entity in the domain model.
But problem is that creation of the entity requires several steps.
OK, so what you have is a protocol, which is to say a state machine, where you collect information from the outside world, and eventually emit a new entity.
The instance of the state machine, with the data that it has collected, is also an entity.
For example, creating an actionable order might require a list of items, and shipping addresses, and billing information. But we don't necessarily need to collect all of that information at the same time - we can get a little bit now, and remember it, and then later when we have all of the information, we emit the submitted order.
It may take some care with the domain language to distinguish the tracking entity from the finished entity (which itself is probably an input to another state machine....)

How to create service in C# which will perform some operations asynchronously in scenario mentioned below?

I have WebApi Controller as mentioned below. This controller having Update method which will internally call service called CustomerDataService to Update Customer Records.Assume we have n customer records to update.
UpdateMethod in CustomerDataService will perform update and return the update response.
I have requirement to do some heavy processing asynchronously after the update response like manipulating data / managing the data cache. As this processing is time consuming not relevant to the consumer of this API as Update successfully happens So I have to perform this asynchronously. Can I do this with C# with the given scenario? Please suggest.
Note: I do not want to create any batch job to achieve this as I want to perform operation(s) which are user session specific.
Controller
public class CustomerController : ApiController
{
[HttpGet]
public string UpdateCustomer()
{
ICustomerService obj = new CustomerDataService();
return obj.UpdateCustomer(GetCustomerList());
}
private List<CustomerModel> GetCustomerList()
{
return new List<CustomerModel>()
{
new CustomerModel
{
CustomerId="1",
Name="John",
Category="P1"
},
new CustomerModel
{
CustomerId="2",
Name="Mike",
Category="P2"
}
//....n Records
};
}
}
Model
[Serializable]
[DataContract]
public class CustomerModel
{
[DataMember]
public string CustomerId { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Category { get; set; }
}
Interface and CustomerDataService
public interface ICustomerService
{
string UpdateCustomer(List<CustomerModel> customerList);
}
public class CustomerDataService : ICustomerService
{
public string UpdateCustomer(List<CustomerModel> customerList)
{
//Do Data Processing - DB Call
//Return Confirmation Message
return "Data Updated Successfully!!!";
//Needs to perform some processing asynchronously i.e. Call ProcessResults()
}
private void ProcessResults()
{
//DO Processing
}
}
What you are looking for is using async/await in c#, see this article on Microsofts website: Asynchronous Programming with Async and Await. Here is another article with plenty of examples: C# Async, Await.
Once you understand how this works it will be very easy to change your code to take advantage of this pattern. Let us know if you have specific questions or run into problems.

Am I writing duplicate domain logics when synchronise query database in CQRS and EventSourcing?

I'm confused with how to synchronise data to the query database.
Let's say I have an aggregate: CreditAccount and some commands may produce CreditAccountBalanceChangedEvent:
public class CreditAccount extends AbstractAnnotatedAggregateRoot<Long> {
#AggregateIdentifier
private Long id;
private int balance;
private DateRange effectiveDateRange;
#CommandHandler
public CreditAccount(CreateCreditAccountCommand command) {
apply(new CreditAccountCreatedEvent(command.getAccountId(),
command.getEffectiveDateRange()));
apply(new CreditAccountBalanceChangedEvent(command.getAccountId(),
command.getAmount()));
}
#EventHandler
private void on(CreditAccountCreatedEvent event) {
this.id = event.getAccountId();
this.effectiveDateRange = event.getEffectiveDateRange();
}
#EventHandler
private void on(CreditAccountBalanceChangedEvent event) {
//notice this line, some domain logic here
this.balance = add(this.balance, event.getAmount());
}
private int add(int current, int amount) {
return current + amount;
}
}
public class CreditAccountBalanceChangedEvent {
private final long accountId;
private final int amount;
//omitted constructors and getters
}
And everything works fine on the command handler side. And I set off to the query side but I find I'm writing some duplicate domain logic here:
#Transactional
#Slf4j
public class CreditAccountEventHandler {
private CreditAccountReadModelStore creditAccountReadModelStore;
#EventHandler
public void handle(CreditAccountCreatedEvent event) {
log.info("Received " + event);
creditAccountReadModelStore.store(accountDevriveFrom(event));
}
#EventHandler
public void handle(CreditAccountBalanceChangedEvent event) {
log.info("Received " + event);
final CreditAccountReadModel account = creditAccountReadModelStore
.findBy(event.getAccountId());
//notice this line, some domain logic here
account.setBalance(account.getBalance() + event.getAmount());
creditAccountReadModelStore.store(account);
}
//omitted setters and private methods
}
As you may notice, I wrote balance calculation code on both command and query side. My question is that is this inevitable in some situations or I write domain logic in wrong place?
As my study so far, events represent something have occured, so no business logic in them, they're just data holder(but reveal users's intent). So should I add a 'balance' field to CreditAccountBalanceChangedEvent and move balance calculation code to command handler method?
public class CreditAccount extends AbstractAnnotatedAggregateRoot<Long> {
//omitted fields
#CommandHandler
public CreditAccount(CreateCreditAccountCommand command) {
apply(new CreditAccountCreatedEvent(command.getAccountId(),
command.getEffectiveDateRange()));
apply(new CreditAccountBalanceChangedEvent(command.getAccountId(),
command.getAmount(), add(this.balance, command.getAmount())));
}
#EventHandler
private void on(CreditAccountBalanceChangedEvent event) {
//notice this line, some domain logic here
//event.getAmount() is no use here, just for auditing?
this.balance = event.getBalance();
}
}
In this case, I can remove balance calculation on the query side by using event.getBalance().
Sorry for a screen full question, any idea is appreciate.
I see two options.
One is for the command to contain the change in balance, the command handler to calculate the new balance, and the event to contain the new balance. If nothing is recalculated in the event handler, it ensures that if the business rules change in the future, they do not affect your object's history when when it is reconstituted from the events.
An alternative would be to place the business rules in a separate class that is called from both the command handler and the event handler to avoid duplication, and then to version those business rules -- via subclassing for example. So you could have an abstract class called CalculateBalanceRule with a subclass of CalculateBalanceRuleVersion1 that is initially referenced by both. If the rule changes, you create CalculateBalanceRuleVersion2, change your command handler to reference it, but keep the reference to Version1 in your event handler, so that it will always replay the rules it did originally.
The second approach is definitely more maintenance, but can answer HOW something change, not simply WHAT changed, if that's something that's important to your business.
Edit: A third option is for the event to only contain the new balance like in the first option, but to version the events. So you have BalanceChangedEvent, BalanceChangedEvent_v2, and so on. This is the direction I could take, as I don't really care to keep a history of how things changed, but I do need to account for the possibility that the events themselves might take on additional members or rename its members. Logic is then needed to determine which event version to use to reconstitute the object at each step.

Can Prism EventAggregator be used for threading needs?

I was looking at Prism EventAggregator and its' great. I part i was most concerned was its capability to marshal thread correctly to UI thread.
I was wondering if i can use this capability to provide module developers a class which could be used to create threads in a similar way as BackgroundWorker. Interface of class can be somewhat similar to
public interface IMyTask
{
event DoWorkEventHandler DoWork;
event RunWorkerCompletedEventHandler RunWorkerCompleted;
void RunTaskAsync(object obj);
}
I have kept types similar to backgroundworker for better understanding. In implementation i am registering taskstart and taskcomplete events
public class TaskStartEventPayload
{
public SubscriptionToken token { get; set; }
public object Argument { get; set; }
}
public class TaskStartEvent : CompositePresentationEvent<TaskStartEventPayload>
{
}
public class TaskCompleteEventPayload
{
public SubscriptionToken token { get; set; }
public object Argument { get; set; }
public object Result { get; set; }
}
public class TaskCompleteEvent : CompositePresentationEvent<TaskCompleteEventPayload>
{
}
In the constructor for the MyTask class i take which thread the completion is required on as
public MyTask(IEventAggregator eventAggregator, bool isUICompletion)
{
if (eventAggregator == null)
{
throw new ArgumentNullException("eventAggregator");
}
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<TaskStartEvent>().Subscribe(TaskStartHandler, ThreadOption.BackgroundThread, false, new Predicate<TaskStartEventPayload>(StartTokenFilter));
if(isUICompletion)
_token = _eventAggregator.GetEvent<TaskCompleteEvent>().Subscribe(TaskCompleteHandler, ThreadOption.UIThread,true,new Predicate<TaskCompleteEventPayload>(CompleteTokenFilter));
else
_token = _eventAggregator.GetEvent<TaskCompleteEvent>().Subscribe(TaskCompleteHandler, ThreadOption.BackgroundThread, true, new Predicate<TaskCompleteEventPayload>(CompleteTokenFilter));
}
here i am registering with filters where filter function returns the event only if it has Payload has same token as while got while subscribing.
further I use
public void RunTaskAsync(object obj)
{
//create payload
_eventAggregator.GetEvent<TaskStartEvent>().Publish(payload);
}
public void TaskStartHandler(TaskStartEventPayload t)
{
//fire dowork and create payload
DoWork(this, args);
_eventAggregator.GetEvent<TaskCompleteEvent>().Publish(tc);
}
public void TaskCompleteHandler(TaskCompleteEventPayload t)
{
RunWorkerCompleted(this, args);
}
This class can be used as
MyTask et = new MyTaskagg, true);
et.DoWork += new System.ComponentModel.DoWorkEventHandler(et_DoWork);
et.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(et_RunWorkerCompleted);
et.RunTaskAsync("Test");
Benefit I see in this approach is
1. It uses threadpool so no overhead of creating threads as in backgroundWorker.
2. Proper thread marshalling in case RunWorkerCompleted to be executed on UI thread.
Please advice if this would be correct to use eventaggregator as Threader.
This will work, although it's code you have to debug for very little performance gain. Micro-optimizing is rarely worth the effort and support costs in my opinion.
EventAggregator is meant to be a message bus for your application and I typically prefer to use things for their original intention, lest I have to debug a lot of code, but that's my personal preference.
Event Aggregator is going to have to work a little harder than it is meant to cleaning up all of those subscriptions, which will likely exceed any performance gain you get from the thread pooling, but that is just a guess.

Resources