I have two objects. A Meeting object and an Action object (action raised in a meeting). An Action can also exist independent of a Meeting. I have two ways of linking the Action raised to the Meeting:
have a method on Meeting where I
pass in the Action object such as
"addToMeeting(Action action)".
WIthin the internals of Meeting
I then link the action to the
meeting. For this approach though the
Meeting object needs to know about
and use the methods on the Action
object so becomes coupled.
have a method on Meeting where I just pass
the action number to be linked such
as "addToMeeting(int actionID)".
Great now Meeting object does not
need to know anything about Action
but......now the code adding the
action to the meeting needs to know
how to get the action ID so has
turned from this
"meeting.addToMeeting(action)" to
this
"meeting.addToMeeting(action.getID())".
For good OO design, which approach should be used? Or is there a third way....
If the only think you ever plan on linking to Meeting instances are actions, then it would seem most appropriate to make Meeting aware of Action, rather than the other way around.
Having the Actions class manipulate the internals of Meeting breaks encapsulation and generally makes it harder to maintain such code. So, I would expose a method addAction(Action a) on Meeting in this case.
However, if there are other things that can be linked to a meeting, you may want to consider abstracting the concept of "meeting items".
Rather than have Meeting know about Action, or vice verse, you could define an interface such as IMeetingItem which exposes the necessary information that Meeting would need to link to such items. Action would then implement IMeetingItem, making it possible to do something like:
meeting.addItem( action ); // action treated as an IMeetingItem in this context
Note that in both approaches, it is the Meeting class that mediates the functionality of adding an item to itself, rather than having the item being added manipulate the internal representation of a meeting.
I would suggest that you create an interface "Identifiable" with the method getID() on it which is implemented by Action
Then you can do the following:
addToMeeting(Identifiable action);
and inside the method do
this.actionId = action.getID();
As long as meetings are associated with actions in any way, you'll have some coupling. However, you might consider a third approach, to build an "action factory" that generates action objects. ID would be a property on the Action object, once it's created (and maybe saved). All that meeting would do is tell the factory to generate an action, and be able to access the action's ID property.
I would go with option #1 -- coupling is not a bad thing, in your case, since there is a clear relation between objects. I would go with option #1. This gives you the option for a meeting to have a property of MeetingActions[] or something similar.
Related
I'm trying to follow DDD principles for my current project. Unfortunately I have to use RFCs due to technical constraints, so no OData and no REST. It's quite a long question I hope it's OK to ask this in Stackoverflow.
In any case, I have an entity class WorkOrder with a list of Operation objects.
I have a WorkOrderRepository class with a SAVE method that only receives a WorkOrder object and is able to save everything (header data, address, etc) in one go. No matter if it's creation, update or deleted. The repository hides the BAPI calls from the rest.
Now I want to implement the logic to add/update/remove Operations to the work order object and I'm not sure even if the names I give to the methods are correct. Maybe they should be insert/edit/delete... I'm quite confused with this since in every place I look they use different names.
But the most important are my 2 specific doubts:
Should I have only 1 RFC that receives all the updates to a WorkOrder entity including header, operations? Or should I create 1 RFC per operation that only handles one operation at a time? Bear in mind that the UI mockup expects that the user can add/delete multiple operations before clicking a SAVE button and RFC has implicit commit, and that to my knowledge a DDD entity should be updated always in one call.
Option 1:
FUNCTION ZWORKORDER_HDR_UPD
IMPORTING
VALUE(I_WORKORDER_ID) TYPE AUFNR
VALUE(I_WORKORDER_HDR_CHG) TYPE ZWORKORDER_HDR_CHG
VALUE(I_WORKORDER_HDR_UPD) TYPE ZWORKORDER_HDR_UPD "X structure for the BAPI
VALUE(I_OPERATIONS_CHG) TYPE ZOPERATIONS_CHG
VALUE(I_OPERATIONS_UPD) TYPE ZOPERATIONS_UPD
VALUE(I_OPERATIONS_DEL) TYPE ZOPERATIONS_DEL
EXPORTING
VALUE(E_ERRORS) TYPE BAPIRET2_T.
Option 2
FUNCTION ZWORKORDER_OPERATION_CRT
IMPORTING
VALUE(I_WORKORDER_ID) TYPE AUFNR
VALUE(I_OPERATION) TYPE ZOPERATION_CHG
EXPORTING
VALUE(E_ERRORS) TYPE BAPIRET2_T.
FUNCTION ZWORKORDER_OPERATION_UPD
IMPORTING
VALUE(I_WORKORDER_ID) TYPE AUFNR
VALUE(I_OPERATION_CHG) TYPE ZOPERATION_CHG
VALUE(I_OPERATION_UPD) TYPE ZOPERATION_UPD
EXPORTING
VALUE(E_ERRORS) TYPE BAPIRET2_T.
FUNCTION ZWORKORDER_OPERATION_DEL
IMPORTING
VALUE(I_WORKORDER_ID) TYPE AUFNR
VALUE(I_OPERATION_ID) TYPE ZOPERATION_ID
EXPORTING
VALUE(E_ERRORS) TYPE BAPIRET2_T.
How should my Workorder methods look to handle this? I'm specially confused with the update method, since I'm not sure if I should first get the existing operation and then update it or let the parent class do it. But maybe my approaches are completely wrong from the root.
Option 1:
workorder->add_operation( i_operation ). "Pass flat structure from RFC? Or first create object?
workorder->update_operation( i_operation_chg
i_operation_upd ).
workorder->delete_operation( i_operation_id ).
Option 2:
workorder->add_operation( ).
operation = workorder->get_operation(i_operation_chg->get_id())
operation->update( i_operation_chg
i_operation_upd ).
operation->delete_operation( i_operation_id ).
The simplest solution is always the best (KISS and YAGNI principles). It doesn't really matter if you create 1 or 3 RFC-enabled function module, so if you can achieve your goal with one function module, then do it with one.
I think you need to have two RFC-enabled function modules. One to validate the maintained operations (do the validations as far as possible), but that should not save anything to the database, and another one called after the user clicks the SAVE button, to save the whole "WorkOrder", including the maintained operations (at this time, there will be the complete validation also).
If you don't need to define an "operation" class for something else, right now, then keep it simple, no need to instantiate an object. Note that you may create an "operation" class with private static methods, and being a friend of the "workorder" class (only this class can use the operation class), just to organize better your code.
PS: although I don't know what is "Domain-Driven Design", I don't see how your question is related to it, because it just looks like simple program design.
We also work with DDD, although luckily not with RFCs but instead Gateway/OData. Since REST by defintion is stateless we always commit in our application service layer.
What we do is have three "DDD" entities
app_Service, domain_service, repository (and also some data containers like aggregates), where the app_service in your case would expose the methods create, update and delete, and possibly also validate.
Then I would write four thin RFCs (crud + validate) that basically passes the data to the app service.
As for being able to handle multiple updates in each save, we always model our OData (your RFC) after the UI requirements, then it's the app_service task to make sense of the data from a system point of view.
We make heavy use of Abap Clean Code (it's even part of our ATC check), and they clearly state that you should have seperate methods, which is also OO best practices.
https://github.com/SAP/styleguides/blob/master/clean-abap/CleanABAP.md#split-methods-instead-of-adding-optional-parameters
I'm trying to apply some DDD concepts and i'm just wondering what makes more sense: for an entity to invoke its own methods, or for the user (actor) to do so?
For example, let's say we have an Appointment entity.
A user is able to cancel the appointment only if s/he is the owner of that appointment (so we need to check that the user has the proper permissions before we can allow that action). We can do this one of two ways:
pseudocode
// method #1
User.Cancel(a *Appointment) result
// method #2
Appointment.Cancel(u *User) result
The bounded context is "Appointments", but it seems to make more sense for a user to invoke behaviours on the entity than the other way around.
Which way is better and why?
First of all you need to determine what is the Aggregate root (AR), the User or the Appointment. In order to determine that you should inspect the business invariants that must be protected, you should see what is the transactional boundary. There is a very nice article here. An AR is an entity that is used to access all its sub/nested entities.
So, there will be an AR and a sub-entity (the other entity in your design) or two ARs, depending on your design.
Then, you acces that command method on the aggregate by specifying only the ID of the other entity, and not the hole object.
Appointment.Cancel(uId *UserID)
Or
User.Cancel(aId *AppointmentID)
Now, the permission checking is in general a behavior that doesn't naturally belong in an Aggregate. That verification is done before the method is called. The aggregates design should not be influenced solely by this permission thing. For example a secretary could also cancel an appointment, not only the participants. Permission checking is in another bounded context.
From what I understand so far from your domain the Appointment should be an AR and your code should look like this:
Appointment.Cancel(byWhom *UserID)
One last thing, if you follow the CQS pattern then that method does not return anything.
If using CQRS and creating an entity, and the values of some of its properties are generated part of the its constructor (e.g. a default active value for the status property, or the current datetime for createdAt), how do you include that as part of your response if your command handlers can’t return values?
You would need to create guid before creating an entity, then use this guid to query it. This way your command handlers always return void.
[HttpPost]
public ActionResult Add(string name)
{
Guid guid = Guid.NewGuid();
_bus.Send(new CreateInventoryItem(guid, name));
return RedirectToAction("Item", new { id = guid});
}
public ActionResult Item(Guid id)
{
ViewData.Model = _readmodel.GetInventoryItemDetailsByGuid(id);
return View();
}
Strictly speaking, I don't believe CQRS has a precise hard and fast rule about command handlers not returning values. Greg Young even mentions Martin Fowler's stack.pop() anecdote as a valid counter-example to the rule.
CQS - Command Query Separation, upon which CQRS is based - by Bertrand Meyer does have that rule, but it takes place in a different context and has exceptions, one of which can be interesting for the question at hand.
CQS reasons about objects and the kinds of instructions the routine (execution context) can give them. When issuing a command, there's no need for a return value because the routine already has a reference to the object and can query it whenever it likes as a follow-up to the command.
Still, an important distinction made by Meyer in CQS is the one between a command sent to a known existing object and an instruction that creates an object and returns it.
Functions that create objects
A technical point needs to be clarified before we examine further
consequences of the Command-Query Separation principle: should we
treat object creation as a side effect?
The answer is yes, as we have seen, if the target of the creation is an attribute a: in this case,
the instruction !! a changes the value of an object’s field. The
answer is no if the target is a local entity of the routine. But what
if the target is the result of the function itself, as in !! Result or
the more general form !! Result.make (...)?
Such a creation instruction need not be considered a side effect. It
does not change any existing object and so does not endanger
referential transparency (at least if we assume that there is enough
memory to allocate all the objects we need). From a mathematical
perspective we may pretend that all of the objects of interest, for
all times past, present and future, are already inscribed in the Great
Book of Objects; a creation instruction is just a way to obtain one of
them, but it does not by itself change anything in the environment.
It is common, and legitimate, for a function to create,
initialize and return such an object.
(in Object Oriented Software Construction, p.754)
In other places in the book, Meyer defines this kind of functions as creator functions.
As CQRS is an extension of CQS and maintains the viewpoint that [Commands and Queries] should be pure, I would tend to say that exceptions that hold for CQS are also true in CQRS.
In addition, one of the main differences between CQS and CQRS is the reification of the Command and Query into objects of their own.
In CQRS, there's an additional level of indirection, the "routine" doesn't have a direct reference to the domain object. Object lookup and modification are delegated to the command handler. It weakens, IMO, one of the original reasons that made the "Commands return nothing" precept possible, because the context now can't check the outcome of the operation on its own - it's basically left high and dry until some other object lets it know about the result.
Some ideas:
Let your command handlers return values. This is the simplest option - just return what was created inside the entity. There is some disagreement about whether this is 'allowed' in CQRS though.
The preferred approach is to create your defaults (i.e.id) and pass them into your command - For example, https://github.com/gregoryyoung/m-r/blob/master/CQRSGui/Controllers/HomeController.cs in the Add method, a Guid is created and passed in to the CreateInventoryItem command - this could be returned in the response. This could get quite ugly if you have lots of things to pass in though.
If you can't do 1 or 2, you could try having some async way of handling this, but you haven't said what your use case is so it's difficult to advise. If you're using some sort of socket technology you could do sync-over-async style where you return immediately, then push some value back to the client once the entity has been created. You can also have some sort of workflow where you accept the command then poll / query on the thing being created
According to my understanding of CQRS, you cannot query the aggregate and the command handler could not return any value. The only permitted way of interogating the aggregate is by listening to the raised events. That you could do by simply querying the read model, if the changes are reflected synchronously from the events to the read model.
In the case the changes to the read model are asynchronous things get complicated but solutions exists.
Note: the "command handler" in my answer is the method on the Aggregate, not some Application layer service.
What I ended up doing is I created a 3rd type: CommandQuery. Everything gets pushed into either a Command or Query whenever possible, but then when you have a scenario where running the command results in data you need above, simply turn to the CommandQuery. That way, you know these are special circumstances, like you need an auto-id from a create or you need something back from a stack pop, and you have a clear/easy way to deal with this with no extra overhead that creating some random dummy guid or relying on events (difficult when you are in a web request context) would cause. In a business setting, you could then discuss as a team if a CommandQuery is really warranted for the situation.
I'm a novice with domain driven design and learning to apply it in my current project. I hope some of you guys have already walked the path and can help me out.
I have a question with regard to saving UI changes back to an Entity (Order).
The scenario:
a. An approver opens the Order (Aggregate root) pending approval on the Web. Makes some changes and clicks the button "Approve".
b. The UI translates the Order changes to a DTO and posts it across to a Web service for processing.
c. The service pulls the Order from OrderRepository via say call to orderRep.GetByID(ApplicationNumber)
Question
1. How do I post the UI changes available in the OrderDTO to Order?
2. What are the different things I need to take care while hydrating the Order?
(If we have to ensure that the domain object (Order) doesn't land up in
invalid state due to changes)
Each user operation should correspond to a different command method in the application service layer. Much of the time it will correspond to exactly one call on a domain object.
You probably don't have fine-grained enough methods on your Order domain object.
Approve() should probably only be a method, not a public setter. Throw an exception within Approve() if it would place the Order object in an invalid state.
This may be a basic question but I am pretty new to DDD.
I have an domain object that we'll call Adjustment which can be processed in bulk from the UI. Before we process the Adjustments, we need to validate the date those adjustments will be applied. My problem is with the location of that IsValidDate() method in my domain object.
Should it be a static method in the Adjustment class?
Should it be part of an AdjustmentService class?
Should I create a AdjustmentsGroup domain object to contain a collection of adjustments and which would also implement IsValidDate?
I would tend to think that the 3rd option is the best one but I have a hard time thinking of a domain term for the group of Adjustment objects. Is it ok to "force" a container type domain object for this type of scenario? Is there a common practice to handle this?
Thank you
Edit: IsValidDate actually contains business logic. This is not just a simple date validation method
I would vote for 2) Make it a DomainService. The code to implement it could be in either a DomainServices class, an AdjustmentServices class, or a ValidateAdjustmentService class, depending on what other services are in the domain model, and what makes the most sense from an organizational perspective.
Another option, (if the rules implemented by this service are business rules) is to implement this as a SPECIFICATION. (Check out pages 224 - 240 in DDD)
If you're doing simple is-this-actually-a-date string validation, the correct place for that method, in my opinion, is inside a Service class, as Charles suggested.
However, if data within the Adjustment or AdjustmentCollection objects can change the date validation logic, e.g. disallowing certain date ranges, the method belongs in that object.
I would favor the 3rd option, but create make a more generic function on Adjustment, like Validate(), which would return a collection of errors/validation faults on itself. That way you can add validation rules at a later time without changing your interface. The Validate() function of AdjustmentsGroup would simply call Validate() on each member in the collection. An equally valid (no pun intended) way would also be to have a separate validator class for the object that contains all validation logic.
Your AdjustmentService would then call Validate() on AdjustmentsGroup before processing the adjustments.