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

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.

Related

Liferay Service for Business Logics

I want to clear one doubt. I am creating my own service class to manipulate data. Should i create this service instance at class level(in MVCPortlet) or create new instance in my processAction/doView method.
Is there is any issue of thread safety while using instance level.
Fg:
public class MvcCycle extends MVCPortlet {
int counter;
LdapService ldapservice;
#Override
public void init() throws PortletException {
counter=0;
ldapservice = new LdapService(); // Option 1
super.init();
}
#Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
// TODO Auto-generated method stub
System.out.println("Counter hits "+ ++counter);
//
LdapService ldapservice = new LdapService(); // Option 2
ldapservice.authUser(request.getParameter("email"));
// -- some code--
super.doView(renderRequest, renderResponse);
}
#Override
public void destroy() {
System.out.println("Last counter "+counter);
counter=0;
super.destroy();
}
}
class LdapService{
public boolean authUser(String email){
if(//logic to authenticate user){
return true;
}else{
return false;
}
}
}
Here, my ldapservice initiate only once. So when multiple hits come. which code is beneficial on this time either Option1 or Option 2.
Hope i have cleared my problem.
Following up on your comment: in general: it depends. We don't have enough information to give you blank architectural recommendations.
In the context of Liferay it could make sense to utilize service builder, even if you don't have database interaction. Just create an empty entity, you'll have a service with no persistence.
<entity name="MyService" local="true"/>
That's it. Now implement MyServiceLocalServiceImpl added you're done
Edit, after your clarification: it doesn't make a difference. I'd still recommend to not instantiate at all in your portlet, because that makes your portlet dependent on the service implementation. E.g. I still go with service builder.
You're also asking about thread safety and that depends on your implementation as well. Your sample code is thread safe, but the actual code might not be. Your judgement.

Javafx: Automatic update of table cell using Thread

I have a Trade class which contains a property currentPrice, which downloads price data from a website using getPricedata() method. The Trade object will show up as a table row in TableView. Now, my task: is to
use the getPricedata() method to grab data from internet, populate the currentPrice cell, whenever the object is created.
relaunch the getPricedata() method to every 1 minute after the object has been created and update table cell.
Below is the basic structure of my code. But I have no idea how to implement this ?
Which package do I need ? Task ? Service ? ScheduledService ?
public class Trade{
private DoubleProperty currentPrice;
// need thread here
public double getPricedata(){
.......
}
}
Use a ScheduledService<Number>, whose Task<Number>'s call() method retrieves and returns the value. Then you can either register an onSucceeded handler with the service, or just bind the Trade's currentPrice to service.lastValue(). Call setPeriod(..) on the service (once) to configure it to run every minute.
Since the currentPrice is being set from the service, you should only expose a ReadOnlyDoubleProperty from your Trade class (otherwise you might try to call currentPriceProperty().set(...) or setCurrentPrice(...), which would fail as it's bound).
I would do something like
public class Trade {
private final ReadOnlyDoubleWrapper currentPrice ;
private final ScheduledService<Number> priceService = new ScheduledService<Number>() {
#Override
public Task<Number> createTask() {
return new Task<Number>() {
#Override
public Number call() {
return getPriceData();
}
};
}
};
public Trade() {
priceService.setPeriod(Duration.minutes(1));
// in case of errors running service:
priceService.setOnFailed(e -> priceService.getException().printStackTrace());
currentPrice = new ReadOnlyDoubleWrapper(0);
currentPrice.bind(priceService.lastValueProperty());
startMonitoring();
}
public final void startMonitoring() {
priceService.restart();
}
public final void stopMonitoring() {
priceService.cancel();
}
public ReadOnlyDoubleProperty currentPriceProperty() {
return currentPrice.getReadOnlyProperty();
}
public final double getCurrentPrice() {
return currentPriceProperty().get();
}
private double getPriceData() {
// do actual retrieval work here...
}
}
(Code just typed in here without testing, but it should give you the idea.)

Allow only one user to access a page at a time in struts application

Having an huge customers profile page if two or more users start using same page and start editing big change will happen in my database so planing to implement Threads concept where only one user can use that customer page
i'm aware about threads concept but confused how to implement it
hope i need to use Singleton class as well
Any suggestion or Logic's will be helpful
I'm using Struts,Hibernate frame work
You may use application context to store a flag variable. Action will use its value to allow only one simultaneous execution.
public class TestAction extends ActionSupport implements ApplicationAware {
private static final String APP_BUSY_KEY = "APP_BUSY";
Map<String, Object> map;
#Override
public void setApplication(Map<String, Object> map) {
this.map = map;
}
#Override
public String execute() throws Exception {
if (map.containsKey(APP_BUSY_KEY)) {
return ERROR;
} else {
map.put(APP_BUSY_KEY, "1");
try {
// action logic here
} finally {
map.remove(APP_BUSY_KEY);
}
return SUCCESS;
}
}
}
If you plan to implement similar logic for two requests (lock after displaying values and release lock after submitting new values) then logic will be more complex and you will also need to handle lock release after timeout.

Aggregate root design and presentation layer

I was wondering if how my presentation layer is structured could be a lead to design my aggregate roots.
Lets have an entity ProjectEntity and its related entity ProjectMemberEntity (1:M)
The page is structured as follows:
The top of the page is a form for ProjectEntity
Underneath the form is a grid that shows a list of ProjectMemberEntity.
If a new ProjectMember will be added, the user have to go to this page and click on the button "add new member" which is located in the header of the grid.also edit and delete has the same analogy.
I'm wondering if this behavior/'page structure' could be a hint for a aggregate root(projectentity)
That's a hint for sure. But no more.
Better way to clarify kind of that entity relationship is to ask domain expert:
does project member makes any sense without project?
can member participate in multiple projects?
If those are answered positively, it's highly likely that You should model project member as an aggregate root itself. Otherwise - demote it as an entity that cannot live w/o a project.
Here is some code that might give You some ideas:
public class Project:Root{
private List _members;
public IEnumerable<Member> Members{get {return _members;}}
public string Name{get;private set;}
public bool IsFinished{get;private set;}
public bool FinishedOn{get;private set;}
public Project(string projectName){
_members=new List<Member>();
Name=projectName;
}
public Member AssignMember(string memberName){
var member=new Member(memberName);
_members.Add(member);
return member;
}
public void UnassignMember(string memberName){
var member=_members.First(m=>m.Name==memberName);
if(!member.HasCompletedAllTasks())
throw new Exception
("Cannot unassign member with incompleted tasks!");
_members.Remove(member);
}
public void AssignTaskToMember(string taskName, string memberName){
var member=_members.First(m=>m.Name==memberName);
member.AssignTask(taskName);
}
public void MemberHasCompletedTask(Member member, Task task){
EnsureListContains(_members,member);
EnsureListContains(member.Tasks,task);
task.MarkAsCompleted();
}
public void FinishProject(){
if(_members.Any(m=>!m.HasCompletedAllTasks()))
throw new Exception
("Can't finish project before members have completed all their tasks.");
IsFinished=true;
FinishedOn=DateTime.Now;
}
private void EnsureListContains<T>(IList<T> lst, T itm){
if(!lst.Contains(itm)) throw new Exception();
}
}
public class Member:Entity{
public string Name{get;private set;}
private List<Task> _tasks;
public IEnumerable<Task> Tasks{get{return _tasks;}}
internal Member(string memberName){
Name=name;
_tasks=new List<Task>();
}
internal void AssignTask(string taskName){
_tasks.Add(new Task(taskName));
}
public bool HasCompletedAllTasks(){
return _tasks.All(t=>t.IsCompleted);
}
public Task GetNextAssignedTask(){
return _tasks.Where(t=>!t.IsCompleted)
.OrderBy(t=>t.AssignedOn).First();
}
}
public class Task:Entity{
public string Name{get; private set;}
public bool IsCompleted{get; private set;}
public DateTime CompletedOn{get; private set;}
public DateTime AssignedOn{get; private set;}
internal Task(string name){
Name=name;
AssignedOn=DateTime.Now;
}
internal void MarkAsCompleted(){
if(IsCompleted) throw new Exception
("Task is already completed!");
IsCompleted=true;
CompletedOn=DateTime.Now;
}
}
public class App{
public static void Main(){
var project=new Project
("Question: Aggregate root design and presentation layer");
var me=project.AssignMember("Arnis Lapsa");
project.AssignTaskToMember("Try to help user137348","Lapsa");
var currentTask=me.GetNextAssignedTask();
//SpamStackOverflow();
project.MemberHasCompletedTask(me,currentTask);
if(me.HasCompletedAllTasks()) project.Finish();
else throw new Exception("Enough for today...");
}
}
Keep in mind that I got little knowledge of what Your business is about. This is just an improvisation. :)
When it comes to DDD, make sure you don't get analysis paralysis when trying to design your domain and aggregates. It happened to me. My project got literally STOPPED for a whole month because i wasn't enable to get my aggregates straight. And i am talking about a simple 3 database tables situation. User, Address and UserProfile.
The thing with DDD is that there is no such a thing like DONE THE RIGHT WAY. If you post the same question here with an interval of 3 months from each other, you will always get the "experts" giving you completely different answers in each question. Amis L. was kind enough to give you a solid simple example. Most people would copy and paste from Eric's books.
Do whatever floats your boat. At the end of the day, no matter how handcrafted your domain is, it's never RIGHT to the community. Just chill and enjoy coding.

Email notifications - In the domain object or a service?

I'm looking for recommendations on how to approach the following design problem (using a fictitious example based on stackoverflow). I'd trying to avoid an anemic domain model and seek general "best-practice" advice for this type of case.
Scenario:
Suppose a new feature is being developed for stackoverflow that sends an email notification to a question's owner whenever his/her question receives 10 upvotes.
The domain object model is something like this:
public class Question
{
string Question { get; set; }
IList<Votes> Upvotes { get; set; }
User Owner { get; set; }
public void AddUpvote(Vote upvote)
{
Upvotes.Add(upvote);
}
}
Potential Implementations:
Change AddUpvote() to take an IEmailerService parameter and perform the logic within the AddUpvote() method.
public void AddUpvote(Vote upvote, IEmailerService emailer)
{
Upvotes.Add(upvote);
if ( Upvotes.Count == 10 )
{
emailer.Send(Owner.EmailAddr);
}
}
Detect this state within AddUpvote() and have AddUpvote() resolve an IEmailService from an IoC container (instead of passing the IEmailerService as a parameter).
Detect this state in the external service object that invokes question.AddUpvote().
public void UpvoteClickHandler(Question question)
{
question.AddUpvote(new Upvote());
if ( question.Upvotes.Count == 10 )
{
_emailer.Send(question.Owner.EmailAddr);
}
}
Your better solution here!
You really don't want to mix these two together since they have separate concerns. Let the Question class care about questions and the message service care about what to do when the voting hits 10, or 20, or 100 or...
The following example is meant for demonstration purposes only, but you will get the point. There is a clear separation of concerns, so the Question class doesn't have to change if the requirements for sending messages changes. Remember according to the SOLID principles, a class should only have one reason to change.
public class Question
{
public string Description { get; set; }
public Int32 Votes { get; set; }
public User Owner { get; set; }
public event EventHandler<QuestionEventArgs> OnUpvote;
private void RaiseUpvoteEvent(QuestionEventArgs e)
{
var handler = OnUpvote;
if (handler != null) handler(this, e);
}
public void Upvote()
{
Votes += 1;
RaiseUpvoteEvent(new QuestionEventArgs(this));
}
}
public class MessageService
{
private Question _question;
public MessageService(Question q)
{
_question = q;
q.OnUpvote += (OnUpvote);
}
private void OnUpvote(object sender, QuestionEventArgs e)
{
if(e.Question.Votes > 10)
SendMessage(e.Question.Owner);
}
}
public class QuestionEventArgs: EventArgs
{
public Question Question { get; set; }
public QuestionEventArgs(Question q)
{
Question = q;
}
}
So there you have it. There are a lot of other ways to accomplish this, but the event model is a great way to go, and it accomplishes the separation of concerns you want in your implementation in order to make maintenance earlier.
Both options 1) and 2) jump out as being the wrong place to send out an email. A Question instance shouldn't know these two things:
It shouldn't know about the policy, ie when to send out an email.
It shouldn't know about the mechanics of notification for a policy, ie the email service.
I know that this is a matter of taste, but you're tying in the Question closely with both a policy as well as the mechanism to send out an email. It would be really hard to move this Question class to another project (like ServerFault, which is StackOverflow's sister site for instance)
I'm interested in this question, because I'm creating a notification system for a Help Desk that I am building. This is what I did in my system:
Create a NotificationManager (Basically, completely move the concern of notifications to a separate class).
public Class NotificationManager
{
public void NotificationManager(NotificationPolicy policy, IEmailService emailer)
{
}
}
I then did something along the lines of this (The UpvoteClickHandler has a dependency to a NotificationManager instance):
public void UpvoteClickHandler(Question question)
{
question.AddUpvote(new Upvote());
_notificationManager.Notify(Trigger.UpvoteAdded, question);
}
All the UpvoteClickHandler does is tell NotificationManager that an upvote was added to question and let NotificationManager determine whether and how it should send out an email.
The answer depends on your fundamental approach to application and object design. And (edit here) what you view as your most important trait of the system. Looks like you have data, questions, and business rules, up votes. Not question objects at all. So you should treat your data as data and allow data tools to work on them, by not mixing behavior into them. Traditional object design would have all the behaviors and data in the object, so sending eMail would belong in the object. (option 1 and 2) I guess this is the black box, or self contained object approach. Modern practices, as I've come to learn, has objects as simple data holders. Which are meant to be moved around, persisted, transformed and have stuff done to them. Perhaps living as little more than structs in C. The behavior comes from the services and transformations that are applied to the simple objects.
HI all,
In my opinion "sends an email notification to a question's owner whenever his/her question receives 10 upvotes" is domain logic and therfore it should be into domain object, in order to avoid an anemic domain.
It's the action of sending the email (i.e. communicate with smtp server) that MUST go into the infrastructure layer.
So i think that option 1 is not totally wrong. Keep in mind that you can always test your object by passing a mock implementation of the IEmailerService.
Best Regards,
Stefano

Resources