Most common ORMs implement persistence by reachability, either as the default object graph change tracking mechanism or an optional.
Persistence by reachability means the ORM will check the aggregate roots object graph and determines wether any objects are (also indirectly) reachable that are not stored inside it's identity map (Linq2Sql) or don't have their identity column set (NHibernate).
In NHibernate this corresponds to cascade="save-update", for Linq2Sql it is the only supported mechanism. They do both, however only implement it for the "add" side of things, objects removed from the aggregate roots graph must be marked for deletion explicitly.
In a DDD context one would use a Repository per Aggregate Root. Objects inside an Aggregate Root may only hold references to other Aggregate Roots. Due to persistence by reachability it is possible this other root will be inserted in the database event though it's corresponding repository wasn't invoked at all!
Consider the following two Aggregate Roots: Contract and Order. Request is part of the Contract Aggregate.
The object graph looks like Contract->Request->Order. Each time a Contractor makes a request, a corresponding order is created. As this involves two different Aggregate Roots, this operation is encapsulated by a Service.
//Unit Of Work begins
Request r = ...;
Contract c = ContractRepository.FindSingleByKey(1);
Order o = OrderForRequest(r); // creates a new order aggregate
r.Order = o; // associates the aggregates
c.Request.Add(r);
ContractRepository.SaveOrUpdate(c);
// OrderAggregate is reachable and will be inserted
Since this Operation happens in a Service, I could still invoke the OrderRepository manually, however I wouldn't be forced to!. Persistence by reachability is a very useful feature inside Aggregate Roots, however I see no way to enforce my Aggregate Boundaries.
Am I overlooking something here? How would you deal with such a scenario?
EDIT: In NHibernate it would indeed be possible to enforce the aggregate root boundary by not marking the aggregate root association with cascade="save-update". I'm stuck with Linq2Sql however.
Honestly, persistence by reachability isn't really an issue with aggregate root boundaries. Remember, aggregate roots can reference each other just fine. Often, I'll use one aggregate root to create another (Customer.CreateOrder for example). The Order is a root as is Customer, and I can still do Customer.Orders[0].Comments = "Foo".
I'm not in the habit of changing the domain model and not persisting changes, but letting them evaporate. It's just not a realistic use case IMO.
Related
In my DDD design, a Command Handler is asked to create a conversation. This is done by calling a third party API.
I use conversation as an abstraction, as today it is a phone call, tomorrow could be something else. I will represent that conversation as a Conversation aggregate in my domain model.
Since it's not a CRUD thing from a database that I am retrieving/updating, do I continue to use a Repository or is there another pattern I should use in it's place? Or should I simply inject my adapter (IConversationAPIAdapter, not depicted in the diagram) into my Command Handler and let it create and return the aggregate back to the handler?
UML Design
If the 3rd party is creating the Conversation, then you don't really have an aggregate. You have at best a facade (the command handler) which just relays the command.
This is actually good, because it simplifies things. However, you should be aware that the returned object is not really an aggregate (as far as DDD is concerned), but a simple business (domain) object (in lack of another term).
You can still use the Repository as a pattern and send that object to be persisted if your app needs it.
Repository is a commonly pattern used in DDD.
The ConversationRepository (an interface) should be in your Domain Layer.
You can totally inject your implementation/adapter (from your Infrastructure Layer) into your ConversationRepository to retrieve your Conversation aggregates from the BDD and return it to your handler (your "Application Service").
We have a solution based in DDD and we want to get all the information of certain entity, including all its aggregates. For example, something like this:
Which could be the best approach to get all the information of the Order aggregate including the Buyer aggregate data?
I was thinking that using the API Gateway to get these entities and provide a DTO as a response could work, but I don't know if it would be the best practice in this case.
So, our goal is call a service (here it's the problem) that could provide the information of the main entity (e.g. Order) and all information of its related entities (e.g. Buyer), but the Order model is related to it through a property named BuyerId.
You already know some component needs to be responsible for data aggregation. It usually boils down to deciding whether the aggregation will occur downstream (e.g. UI) or upstream (e.g. server).
If the APIs are already in place to gather the Buyer's data and the Order's data and the downstream client has the necessary correlation IDs on hand then it becomes possible for the downstream client to deal with the complexity of aggregating data. Whether this is acceptable or not is another story.
If you want to solve data aggregation issues upstream then you will most likely have two main strategies to choose from:
Aggregate in the application
public OrderDetailsDto orderDetails(OrderId orderId) {
//Repositories could be switched to remote API calls
Order order = orderRepository.findById(orderId);
Buyer buyer = buyerRepository.findById(order.buyerId);
return dtoAssembler.orderDetailsFrom(order, buyer);
}
Aggregate in the database
public OrderDetailsDto orderDetails(OrderId orderId) {
ResultSet resultSet = orderDetailsFromDb(orderId);
return dtoAssembler.orderDetailsFrom(resultSet);
}
Probably, we need to use a DTO
As you can see, both implementations could return the same DTO. Using explicit DTOs is a very useful and popular approach to deal with contract & serialization issues. How data is mapped into such DTOs is completely up to you and there are a multitude of implementation strategies.
Does anyone know of a way to mix static object instances with those managed by NHibernate. I have an application where I use the repository pattern to manage db object instances, and those instances have some complex many-many, one-many, and many-one relationships. There are some scenarios where I'd like to have a guaranteed object (like a "User" type instance of "sys_user", for example). The instance must be able to participate in relationships, and I'm willing to have a hardcoded primary key for the few objects I want.
Basically I'm looking for a way to make my repository intermingle statically defined objects into the output, so if I ask for a list of "User"s i get the static "sys_user" plus those defined in the database. Furthermore, I'd like to be able to have that "sys_user" participate in a relationship with DB objects, i.e. - MyClass("db instance").UserProperty == "sys_user" instance, as defined by a fk on the MY_CLASS db table with a special value (say -1)
In essence, this is just a way to avoid an installation time requirement of pre-loading predefined objects that the app expects into the DB, as well as preventing them from being modified after installation. I want to code some logic that relies on special instances being present, and not allow users of the app to inadvertantly break that contract.
this should be exactly the case you describe, no need for repository though, just NHibernate http://fabiomaulo.blogspot.com/2009/08/from-db-to-ram-wellknowinstancetype.html
as you know, in Seam there are no problems with LazyInitializationException when reading entities's references to subobjects. So is there any problem if I favor running through the tree of relations in order to read the data that I need, instead of sending specific queries to releveant entities' DAOs? Do I break some important guidelinies/priciples?
Consider that the phrase:
"in Seam there are no problems with LazyInitializationException"
It's not true.
In seam there are no problems with LazyInitializationException if you use a pattern where your session is being persisted in the boundary of a long-running conversation.
This means using a Seam injected persistence context like:
#In
private EntityManager entityManager;
Or, if you are using stateful EJBs (bound to conversation scope too):
#PersistenceContext(type = PersistenceContextType.EXTENDED) EntityManager em;
BTW, once you have understand that, there is no problem navigating the relation tree. You should really do it, if you want to bind it to the interface using JSF.
Consider that you may incur in some speed problem if you access to ManyToOne or OneToMany relations in queries that returns more than one result. This is known as n+1 problem, when you basically runs one more roundtrip to the database for each record returned.
Let's summarize:
single detail object -> navigate relation tree
List of other object -> make a single query to the DAO using left join fetch.
I am new to programming (6 weeks now). i am reading a lot of books, sites and blogs right now and i learn something new every day.
Right now i am using coldfusion (job). I have read many of the oop and cf related articles on the web and i am planning to get into mxunit next and after that to look at some frameworks.
One thing bothers me and i am not able to find a satisfactory answer. Beans are sometimes described as DataTransferObjects, they hold Data from one or many sources.
What is the recommended practice to handle this data?
Should i use a separate Object that reads the data, mutates it and than writes it back to the bean, so that the bean is just a storage for data (accessible through getters) or should i implement the methods to manipulate the data in the bean.
I see two options.
1. The bean is only storage, other objects have to do something with its data.
2. The bean is storage and logic, other objects tell it to do something with its data.
The second option seems to me to adhere more to encapsulation while the first seems to be the way that beans are used.
I am sure both options fit someones need and are recommended in a specific context but what is recommended in general, especially when someone does not know enough about the greater application picture and is a beginner?
Example:
I have created a bean that holds an Item from a database with the item id, a name, and an 1d-array. Every array element is a struct that holds a user with its id, its name and its amount of the item. Through a getter i output the data in a table in which i can also change the amount for each user or check a user for deletion from this item.
Where do i put the logic to handle the application users input?
Do i tell the bean to change its array according to the user input?
Or do i create an object that changes the array and writes that new array into the bean?
(All database access (CreateReadUpdateDelete) is handled through a DataAccessObject that gets the bean as an argument. The DAO also contains a gateway method to read more than one record from the database. I use this method to get a table of items, which i can click to create the bean and its data.)
You're observing something known as "anemic domain model". Yes, it's very common, and no, it's not good OO design. Generally, logic should be with the data it operates on.
However, there's also the matter of separation of concerns - you don't want to stuff everything into the domain model. For example, database access is often considered a technically separate layer and not something the domain models themselves should be doing - it seems you already have that separated. What exactly should and should not be part of the domain model depends on the concrete case - good design can't really be expressed in absolute rules.
Another concern is models that get transferred over the network, e.g. between an app server and a web frontend. You want these to contain only the data itself to reduce badnwidth usage and latency. But that doesn't mean they can't contain logic, since methods are not part of the serialized objects. Derived fields and caches are - but they can usually be marked as transient in some way so that they are not transferred.
Your bean should contain both your data and logic.
Data Transfer Objects are used to transfer objects over the network, such as from ColdFusion to a Flex application in the browser. DTOs only contain relevant fields of an object's data.
Where possible you should try to minimise exposing the internal implementation of your bean, (such as the array of user structs) to other objects. To change the array you should just call mutator functions directly on your bean, such as yourBean.addUser(user) which appends the user struct to the internal array.
No need to create a separate DAO with a composed Gateway object for your data access. Just put all of your database access methods (CRUD plus table queries) into a single Gateway object.