Which objects are responsible for maintaining references between aggregates? - events

Suppose I have one aggregate, Ticket. A Ticket will have one assigned Department and one or more assigned Employee.
When instantiating a Ticket, should a TicketFactory be responsible for ensuring that a Ticket is created with a valid/existent Department and Employee?
Likewise, when decommissioning a Department or Employee, what is responsible for ensuring that a new Department or Employee is assigned to a Ticket so as to maintain its invariants? Could there be a service in the domain responsible for decommissioning, or is this a case where eventual consistency or some form of event listening should be adopted?

The TicketFactory would be declare that in order to create a Ticket you need references to both a Department and an Employee. It would not verify that those actually exist. It would be the responsibility of the calling code to obtain the appropriate references.
If using eventual consistency, the decommissioning of a Department and Employee would publish events indicating the decommission. There would be a handler associated with a Ticket which would subscribe to that event and either assign a new department and employee or send some sort of warning to task.
Take a look at Effective Aggregate Design for more on this.

I've recently started exploring DDD, so I have ran into some of the issues you mention.
I think that TicketFactory should always return validated/properly built Ticket instances. If you model is complex, you can have a domain service that validates that a given Department or Employee can be attached to it and then the factory uses it. Otherwise, you can just put it all in the factory. But what comes out of the factory should be a proper ticket.
I'd say that if e.g. only Ticket knows about the other two, a domain service that uses the Department and Employee repos would get the job done. If the relationship is bidirectional, then you can utilize event sourcing. Also, if it's really a event that should be captured in your domain model, and has other consequences other than reshuffling tickets, you can attach one of the handlers to this event to be InvalidTicketHandler. But if it's a small scale thing, keep it simple, just have a domain service that maintains the invariants.
Sidenote: If the Department and/or Employee are aggregates themselves, then you can reference them within Ticket via their identifier (e.g. employee's company ID or ID-code of the department). In that way you'll achieve consistency easier as you will not cross consistency boundaries between different aggregates.

A FACTORY is responsible for ensuring that all invariants are met for the object or AGGREGATE it creates; yet you should always think twice before removing the rules applying to an object outside that object. The FACTORY can delegate invariant checking to the product, and this is often best. [Domain-Driven Design: Tackling Complexity at the Heart of Software]
A depends on question type, but from the look of it it seems like a great candidate for an application layer functionality, i wouldn't go for the event solution though cause i find it only suitable in between layers and not between objects in the same layer.

Related

How to implement constraints that are external to a microservice?

Suppose we have two microservices, Customers and Orders, with no dependencies between them, i.e. they don't call each other, they don't know each other. Every order, though, has a reference to a customer by means of a customer id. In other words one customer may have zero or more orders, and one order belongs to exactly one customer.
For the sake of the example, it's totally fine to delete a customer unless there are orders belonging to that customer. What is the most appropriate way to implement a constraint on Customers that prevents a customer from being deleted if one or more orders have a reference to that customer? Analogous to referential integrity in a relational database.
These are the approaches I can think of:
Let Customers ask Orders if a given customer has any orders, e.g. via API call.
Let Customers keep track of which orders are assigned to every customer, e.g. by having each customer record maintain a list of order ids.
Merge Customers and Orders into a single microservice and manage it internally.
I'm not sure which approach is the best for the given example in a microservices context. I can see pros and cons in all three approaches but I won't list them here because I'd like to hear other people's thoughts on the problem, including approaches not listed above. Thanks.
Probably the second approach would help if you're going to decouple through events, either tracking a list of ids or a counter just telling how many orders are stored for such a Customer.
On the Order microservice you will emit an event when there is a creation/deletion that will be captured by the Customer (or any other microservice interested) who will take care of updating the list of order ids (or increment/reduce the counter).
If customer order counter is 0 then you may delete the customer.
Let's start with your third approach: This will not work in a Microservice world, because you will always have those constraints between some Services. And if you want to solve all of them this way, you'll end up with a Monolith - and that's the end of your Microservice story.
The first and second approach have both the same "problem": These are async operations, that may return false positive (or false negative) results: It's possible to make api requests for delete customer and create order (or delete order) at the same time.
Though this can happen:
For your first approach: Customer Service asks Order Service if there are any Orders for this Customer. Order Service returns 0. And at the same time Order Service creates a new Order for that Customer in another thread. So you end up with a deleted Customer and still created an Order.
The same applies for your second approach: The messaging between those services is async. Though it's possible that Customer Service knows of 0 Orders, and permits the delete. But at the same time the Order Service creates a new Order for this Customer. And the OrderCreated message will hit the Customer Service after the Customer has already been deleted.
If you try to do it the other way around, you'll end up with the same situation: Your Order Service could listen to CustomerDeleted messages, and then disallow creating new Orders for this Customer. But again: This message can arrive while there are still Orders in the database for this Customer.
Of course this is very unlikely to happen, but it still is possible and you cannot prevent it in an async Microservice world without transactions (which of course you want to avoid).
You should better ask yourself: How should the system handle Orders where the corresponding Customer has been deleted?
The answer to this question is most likely dependent on your business rules. For example: If the Order Service receives a CustomerDeleted message, it may be okay to simply delete all Orders from this Customer. Or maybe the behavior depends on the Order's state property: It's okay to delete all Orders with state = draft, but every other Order from this Customer should still be processed and shipped as usual.

Use DB Relationships in spring boot micro services

I want to use the many to one and other DB Relationship in micro-service architecture. In monolithic architecture we can create the entity relationship easily as they belongs to same project but in micro-service architecture how we can achieve the same.
Example:
There is one userDeatil service and other is productDetail service.Now there is third service called orderDetail and an order will have userID and ProductIDs associated with it. So how can we manage the relationship between 'user and order' and 'order and product'.
I have searched over net but didn't able to get the fair idea.There is another thread having same query but not having the clear answer. Link
In my opinion your case is about how you specify your services especially how you define the bounded context of each service !!
According to the situation above-mentioned I don't see any reason why the product service should know anythings about orders (even if it s just the order-id) and backwards. One more problem I see in this case: your services will not work if one service is not available (E.g when the product service it not online, your order service will not be able to work, because he needs the product details from the product service...).
I Think you should rethink the bounded contexts of your microservices. You should keep in mind:
ensure a loose coupling of the microservices
a microservice has always to work even other Microservices are not available (Resilience / Reliability).
The DDD (domain-driven-design) paradigm with its tools provides her a great help to assist you, during the definition process of your services, you encourage these qualities.
So, the following is JUST an idea (it s not a recommendation and you should review whether it matters for your business case) :
It seems like the "order" process is your core business domain. So you have to focus on it.
The user service (i hope you mean here the customer and not a user in terms of authentication/authorization) has only the responsibility to manage the customers, and may be their adresses, bank-Accountings etc.. It should not know anything about your orders or products.
The same is valid for the product service. It owns only data about products. It has no relation either to the customer nor to the order-service.
The order service by itself deals only with orders and should own only data that belong to an order (like ship Adress and some information about the product-items ordered). I think the customer-Id is also important here to keep the relation between the order and the customer. This way you can e.g get all orders made by a certain customer-id....

Getting all aggregate root entities child entities?

I am attempting to refactor my application from a repository per entity to a repository per aggregate root.
A basic example would be I have an entity root of Cars. Cars have hire contracts. As far as I can see contracts don't exist without cars hence cars is the aggregate root.
I am trying to implement a user view which will shows every contract in the system(all the child entities of the root entities). Before refactoring I could just go to my contracts repository and get All. As contracts repository has been removed (as its not a root) I now need to get all cars out of my repository and then get all their contracts.
My repository has the interface
public interface ICarRepository
{
IQueryable<Car> All { get; }
IQueryable<Car> AllIncluding(params Expression<Func<Car, object>>[] includeProperties);
Car Find(long id);
void InsertOrUpdate(Car car);
void Delete(long id);
void Save();
}
I thought of creating an ICarManagementService and having it have a GetAllContracts method (perhaps with filter parameters). Would that mean to get all contracts I need to pull all car entities out with their contracts and then retrieve each entities associated hire contracts and filter them?
I can then pass these to the controller and AutoMap the contracts as before.
Is this best practice?
Thanks
Graeme
As far as I can see contracts don't exist without cars hence cars is
the aggregate root.
This is not necessarily true. 'Don't exist without' is not enough for an entity to become a part of an Aggregate Root. Consider classic order processing domain. You have an Order that is an Aggregate Root. You also have a Customer that is an Aggregate Root. Order can not exist without a Customer but it does not mean that Orders are part of the Customer Aggregate. In DDD entities inside one Aggregate can have references to other Aggregate Roots. From DDD book:
Objects within the AGGREGATE can hold references to other AGGREGATE
roots.
Aggregate is a life cycle and data exchange unit. It is essentially a cluster of objects that enforces invariants. This is something you want to be locked if you have multiple users changing domain at the same time.
Back to your question, my understanding is that the domain is something like rent / lease a car / truck / limo / bulldozer. I think that HireContract may not be a part of Car aggregate because they may have different lifecycles and HireContract just makes sense on its own, without a Car. It seem to be more of a Order-Product relationship that is also a classic example of two different Aggregates referencing each other. This theory is also confirmed by the fact that business needs to see "All Contracts". They probably don't think of Car containing all Contracts. If this is true than you need to keep your ContractsRepository.
On an unrelated note, you might be interested in reading this answer about repository interface design.
Separate the concept of read/query from the write/command, as guided by CQRS it is preferable to design the application by separating read model which consists of read only queries and the write model on the other hand which consists of commands to execute certain logic on the domain model.
thus querying all aggregate roots or creating custom queries to join sets of data is not a good candidate of domain repository, instead put these queries into read repository (or better named Finders).
if you find yourself wanting to query a collection of objects in order to execute some domain logic then it is an indicator that you have to abstract this collection and put it into an aggregate root to encapsulate them and make the business operation or method act on them.
check out (http://moh-abed.com/2011/09/13/pure-old-ddd-with-a-twist-from-cqrs/) and (http://simon-says-architecture.com/2011/08/23/repository)

Cocoa bindings: get old value upon change

I am writing a core data Cocoa application in which there are accounts and transactions (monetary). The account entity description contains a balance attribute. The transaction entity description has a relationship to an account.
I need the application to update account balances when transactions have their accounts set or changed. For example, if a transaction's account is changed from checking to credit, the balances of both checking and credit should be changed to reflect this.
The problem I am having is that I am unsure how to determine the transaction's old account so I can update its balance. I am using bindings.
Can anyone point me in the right direction?
I assume that the account entity has the inverse relationship to the transactions. (Apple strongly suggests you always have inverse relationships. So if you haven't, please set it up!)
Let's say you have a subclass Account of NSManagedObject for the account entity, and Transaction for the transaction entity.
Call the inverse relationship to transactions as transactions.
Then, when you change the account for the transactions, the inverse relationship is automatically updated by CoreData. So, all you have to do is to write a self-observation routine for transactions in Account so that the Account objects keep track of the balance themselves. I think it is more object-oriented-y to make Account objects to take care of themselves than changing the balance from the side of the Transaction object... although of course it depends on your taste.
To perform the observation, you use KVO. Basically, you register the KVO by addObserver:forKeyPath:options:context: with a suitable set of options. Then, you get the change by implementing observeValueForKeyPath:ofObject:change:context:. The changes can be found in the dictionary passed to that method.

Creating a Core Data Inverse Relationship

I'm trying to write my first Cocoa app, and Core Data is making it difficult to model my data objects. I have two entities that I want to manipulate: Account and Transaction. Account has a human-readable name and that's about it. Transaction stores a monetary value, and references to two accounts called debitAccount and creditAccount (I'm working on a double-book accounting app).
I want to be able to find all the Transactions for a given Account, whether they use debitAccount or creditAccount. How can I do this? Is there a way to do it that will work easily with Cocoa UI binding?
If I understand you correctly, you want Transaction to be related to Account via two relationships: debitAccount and creditAccount, yes? And you're wondering about creating inverse relationships.
In short, a relationship can only be the inverse of one other relationship. So you won't be able to create a relationship called, say, transactions that is the inverse of both debitAccount and creditAccount. Instead, you'll have to create two relationships, like debitTransactions and creditTransactions (I'm sure you'll think of more appropriate names for these...)
Now, since relationships are modeled as sets (specifically, NSSets), you can union the creditTransactions and debitTransactions relationships for a particular Account to get all transactions that account is involved with.
A (possibly better) alternative would be to introduce an intermediate entity, with a name like TransactionAccount that has a to-one relationship to both Account and Transaction as well as an attribute, like accountRole that identifies the account as being the debit or credit account relative to that particular transaction. You'd create inverse to-many relationships on both Transaction and Account with a name like transactionAccounts. That way, you could write something like this:
[account valueForKeyPath:#"transactionAccounts.transaction"]
to get all the transactions for a particular account. You could use an NSPredicate to filter the set to only transactions where the account was the debit/credit account.
The solution that worked best (and made the most sense) to me was to create a subclass of NSManagedObject to use as my Account entity:
#interface Account : NSManagedObject {
}
-(NSArray*)getTransactions;
#end
I have the actual lookup logic inside -getTransactions, which wasn't too hard to do by hand. This is working out well so far, especially because the method name conforms to KVO.
To make Core Data return Accounts instead of NSManagedObjects, I had to change the entity's "Class" property in Xcode's data modeling tool.

Resources