Should behaviors be exposed through the Actor object or can it be done on any object? - oop

Lets say we are writing a Seat Booking functionality in object oriented programming. User is the primary actor here. We might implement the booking flow as follows
var booking = user.BookSeat(seatid);
Subsequently, the user might Cancel the booking. In proper object oriented design, should this operation be exposed through the actor ie the user object(representing the real world user) as follows?
user.CancelBooking(booking);
or can it be called directly on the booking object?
booking.Cancel();

Related

OOP-correct way of notifying about a has-a relationship

The has-a relationship is the following: a Product has a collection of Events. Events are not simple primitives, they represent for example a price change.
In this scenario who is more natural to assume the responsibility to notify the current user about an Event on a Product?
If this is the Product - Product#notify(Event).
If this is the Event - Event#notify(Product). This one might be a little awkward/loopy, since the call in Product would look like this: this.events[i].notify(this).
User#notify(Product, Event) is not an option since the system has no notion of users.

How to update shared information between 2 representations of the same entity in different contexts?

This question is related, but more specific than this question.
I'm going to use a simple example here. Say we have a User entity in one context and a Customer entity in another context. These are 2 different representations of the same entity.
Let's say the User and Customer both have an email address, but the email address is always changed via the bounded context that the User belongs to. So the user context is the source of truth for the email address. So ideally I would like the email address in the Customer context to be immutable from the point of view of the customer context.
So when the email address is changed in the user context, an EmailAddressChanged event is emitted. This is fine; I subscribe to the event in the Customer context. However, I now need to handle this event by mutating the Customer email address. So I need some sort of command method to make this change.
How can I ensure that the command method is not used, other than when handling the event from the User context?
If I allow mutation in both contexts then they both become sources of truth and I need double the number of events and handlers to ensure that the information remains consistent in both contexts
Maybe there is a hidden customer/supplier relationship between these bounded contexts? If User bc is the source of truth for Customer bc, then User bc might expose an API to be accessed by downstream contexts (Customer, maybe something more?). In your question you said only the email address should be "immutable" and dependent on User context - however, I think it might a hint that entire Customer context is a consumer/customer of User context and should use its public API (which should not expose internal user domain model directly - some facade classes are required to hide the details).
If that's not the case, and there is no such relationship between the contexts - you can use a specialized component in your Customer bc to make changes to the database, without directly invoking domain methods. Then, the repository can be used to query customers and recreate them with updated email address. My point is - if you want customer bc to apply EmailAddressChanged events, you obviously need something to alter the database, but you don't need to do that via domain methods. The component applying EmailAddressChanged events would be part of the infrastructure layer of Customer context. If you use this solution, then there is no risk of modifying customers via business case scenarios.
Btw, isn't your Customer in fact a specialized read model of User context?

Confusion about classes

I am quite new to OOP concepts and I'm trying to create a food delivery system system, and I have different users(admin,clerks,officers) that access the system
I have customers that will be registered into the system and orders that will be placed for the customers.
Therefore I have created methods for registering customers(registerCustomer) and placing orders(placeOrder) alongside other methods. Now I am quite confused which classes these methods will go under. Should the registerCustomer go under my User class(which different users inherit from) or Customer class. Same thing about the order placement. Should I create an order class or will placeOrder go under Customer or User class
There are quite a lot of ways you could do this, and many books and online resources that can teach you about object oriented programming. In general, you want to place your methods in classes that those methods operate on, and not in classes that can't be affected by those methods. So, if only Customers can be registered, and Clerks and Officers cannot, then the registerCustomer() method should be accessible only from the Customer class and not the User class it inherits from. Similarly, if only a Customer can place an Order then that's where the placeOrder() method should be located.
However, you should also consider what other object participates in each operation. For instance, perhaps the registerCustomer() method really belongs in a FoodDeliverySystem class. For instance:
FoodDeliverySystem mySystem = new FoodDeliverySystem();
Customer myCustomer = new Customer();
Order myOrder = new Order();
mySystem.registerCustomer(myCustomer);
myCustomer.placeOrder(myOrder);

How do you represent domain object behaviors using methods when a domain object is acted upon and not the actor?

In Domain Driven Design, there is an emphasis of placing behaviors where they correctly belong. I'm not always sure what exactly constitutes "correct," though.
Consider this scenario: "The client withdraws an amount of money from a bank account."
Grammatically, we have that:
'client' is a subject
'withdraw' is a verb
'amount' is a direct object
'account' is an affected prepositional object
Classically, the client would execute this: account.withdraw(amount).
This could be read as: "The client commands a bank account to withdraw an amount of money." However, this does not grammatically correspond to the original scenario, since 'bank account' is now the direct object and an infinitive removes 'withdraw' and 'amount' from the main clause so that the primary idea conveyed is that 'client commands account'.
To adhere to DDD, we should regard this code as precisely describing the original scenario. This implies that the 'withdraw' method does not model a behavior performed by the account (the account is not a subject), but rather it models a behavior that indirectly affects it (the account is a prepositional object) and could very well be renamed 'wasWithdrawnFrom'. Moreover, the method argument represents something being affected by the client as opposed to by the object (it is a direct object for a client subject, not an object subject).
If we extrapolate from this example, we can see that methods may represent behaviors that affect the object (object is not the subject) and method arguments may represent direct objects of a client subject.
However, whether or not methods should represent behaviors performed by objects is unclear.
So my question is: How should we use methods to model object behavior?
1) Methods should strictly represent behaviors that affect the object. (The object cannot act as a subject, only a grammatical direct/indirect/prepositional object)
2) Methods may represent both behaviors that affect the object as well as behaviors performed by the object. (The object may act as a subject or a grammatical direct/indirect object)
You seems to be stuck in a theoretical thesis. I'm not sure you can apply a theory that works for every scenario/project. Behaviors usually appears when you start bombarding your Model with Use Cases. I try to let the cases dictate behaviors.
To follow your example:
Actor Customer want to withdraw money from Account. The way to do it is like you do Account.Withdraw(Money amount)
But your question "How should we use methods to model object behavior?" is a common DDD question. How to enrich your model with behavior? My best hints is to find your Value Objects. Value objects usually comes with behavior.
In example Account is and Entity (Aggregate root probably). Money (Value object with Currency and Amount) should be withdrawn from an Account. That should be Account Single Responsible (Principle) to control that Account balance and all access to it.
Regarding your (2) question in the end. Methods are absolutely used for change the objects inner state. But when it comes to behaviors performed by the entity/value object like
Customer.Order(newOrder) or advert.Apply(candidateCV) we can make entities communicate with each other. We can also create chained behaviors through Domain Events which can help us not to leak to much business logic to our application services. See Udi Dahan's blog for that or my blog article regarding Anemic Domain model http://magnusbackeus.wordpress.com/2011/05/31/preventing-anemic-domain-model-where-is-my-model-behaviour/
I Hope you got some ideas. It's difficult to give concrete hints when we are so abstract here.
/Best regards Magnus
I find that scenario too simple to be real, hence too simplistic to model too. I would reformulate the
"The client withdraws an amount of money from a bank account."
to something like
"The client submits withdrawal request of value xxx $ from his account" (when I go to my bank I have to fill out a form in order to withdraw money where I state amount, the account number, date and my signature)
There one can spot a request (command) to a service (withdrawal service) of an client (client identified by ID) from his account (account identified by ID) and the money value (money as value object).
I don't care much about the grammar, as English is my second language so when trying to understand the Domain, I try to understand how the business sees the concepts (Account) and workflows (withdraw an amount) and not to do grammar analysis.
The point of DDD is to model things like they are in the business, so behaviour shows up according to Domain understanding.
in this scenario, for me it's clear that we're working within the Account Operations Bounded Context and at least the Account aggregate root is involved. Of course, in banking terms, probably (I'm guessing here) there will not be a withdrawl but an operation to increase the Debit/Credit part of an account, so most likely the account will register that a debit/credit operation has happened. And a Domain Event is born and published. Then let the domain expert tell you what will happen next.
"The client deletes an order" => order.delete
Probably the order is never deleted, but its status will changed to 'canceled' or similar. However for that case when an order really should be deleted, the order doesn't delete itself, the Orders repository deletes that order.

How to design an api to be called by different applications

Application A has an api setAge(String staffName). Application B and C both call this api.
If a staff Jack has different names in A, B, C: JackA, JackB, JackC, so how to design application A to map JackB=>JackA and JackC=>JackA?
You need to model identity in some way. If your business objects (e.g. staff members) are persisted in a relational db you can use the table's primary key, but this is a rather bad practice, as technical keys should not be relied upon on the application level. Instead use a unique business-id for your entities. That can be a String or a UUID for example. When accessing the entities in your API, clients have to pass that business-id as a parameter.
If you are in an OO language like Java, you might have to consider implementing object equality through equals and hashCode contracts (see here).