DDD, CQRS, Event Sourcing: Where do entities come from? - entity

I'm a bit confused about the origin of entities in an environment which takes advantage of CQRS & Event Sourcing. To make my question clear let's take the following well known example of a web shop:
You may model an order as an aggregate root. An order accepts order lines which themselves are defined by a product and a quantity.
Since an order line is an entity which is constructed during the order process itself there is still the notion of a product which seems to be an entity as well. But where does the product or even the catalog of products come from? In my opinion there is no such a thing like a product aggregate root in the bounded context of an order. How then would the order context know about product entities? Are they maintained in another bounded context and somehow materialized in the read store of the order context?

In the BC that contains Order it might indeed be the case that Product, as part of an OrderLine, is a value object, consisting of values such as ProductId, Name etc.
The order context does not need to know about product entities, since order lines usually only contain simple value-only properties (productId/SKU, a name, quantity and price-per/item). Therefore, Order could provide a function such as
void addOrderLine(ProductId productId, String productName, BigDecimal pricePerItem, int quantity).
It's actually not relevant for the "Order"-BC where these values for productId, productName etc originate from.
In practice, however, it's probably very likely that these values can be obtained from another bounded context, say the "Product"-BC, which is responsible for inventory management etc.
It's quite common to let the UI orchestrate these BCs:
The UI (a web shop for customers, for example) loads the products and their prices from the "Product-BC"
The user places products into a shopping basket (let's assume for simplicity that this is also the "Order-BC"). For, the UI fires commands such as AddToShoppingBasketCommand(productId, productName, quantity, price) which are handled by the "Order"-BC.
When the user wants to place the order for the current shopping basked, it fires a PlaceOrderCommand.
The command handler for PlaceOrderCommand takes the current shopping basket and constructs a corresponding Order; all it needs are, for each product, the respective properties of products that were already listed in the shopping basket (and were originally in the AddToShoppingBasketCommand). Note that it does not need to know about the notion of a Product entity from the Product-BC.

Related

Consolidating business logic in one place - SQL Server

I have a situation, where with time, the same logic has been scattered at different places (stored procedures) in the application. I am trying to bring it in one place and re-use it as required.
Scenario:
We sell products online, that are classified into categories and the business rules vary by category. When performing a search, it is possible that multiple products are returned from the same category.
Examples of business rules are:
Can the agent sell a product from this category (permission, licensing etc.)?
Can the category be sold in a particular state?
Is there a tax to be applied on the category?
What is the markup for this category?
Does this 'product' meet the customer's requirements?
Current Implementation:
Step 1 - Searching
We have a stored procedure that takes #agent_id, #state_id, #markup_amount, #category_id, #customer_id as inputs and returns all products from a specific category, that meet the customer's requirements. The customer's requirements are derived using customer_id. (SELECT 'product' stored procedure)
Step 2 - Quoting
When adding a particular product to the shopping cart, the above logic is again executed with an additional parameter #product_id, to make sure that the product being added to the shopping cart, satisfies the original requirements (INSERT 'cart' stored procedure)
Step 3 - Re-Validation
If the customer's requirements change, it is possible that products already in the shopping cart still qualify. The ones that do not qualify have to be removed from the UI (is_active_flag is set 0 on SQL). So we re-use the same logic to determine what the products still meet the customer's requirements. (UPDATE 'cart' stored procedure)
Step 4 - Sale
The customer can only buy one product from a particular category. When the customer is ready to buy, we re-run the same logic to see if that particular product still passes all business rules including meeting the customer's requirements (INSERT 'sale' stored procedure)
Consolidation:
What I am looking to do is consolidate this logic in one place and reference it in different stored procedures, as required. The only variable is #product_id. When the initial search is performed, we do not know what products will qualify. Once we have a finite list of product ids, we are drilling down that list at each step.
For Example: The search stored proc may return 500 products which forms the finite list and the customer may end up adding 3 products to the shopping cart, and in the end can buy only 1. The 3 products that were added and the 1 product that was ultimately sold are a part of the finite list of 500 qualifying products.
What is the most efficient way to achieve this? Thank you.
If your goal is create something readable, you can create a boolean sql function that evaluates each product in each scenario.

One entity, several models in different bounded contexts with different databases

Let's say we have an Order entity that will be modeled in 2 diff. BCs in a e-commerce application.
The first BC is Order Placement. This BC takes care of collecting all orders placed by our customers from our different websites, validates them and populates its corresponding database by Orders with state either Placed or Rejected.
The 2nd BC is Shipment. This allows the employees in the warehouses to mark an Order as Shipped in its database once it leaves the warehouse.
Now since both BCs use different databases which are empty at first, there will be a need to inform the Shipment BC of the orders that were Placed, so that when a scanner wants to Ship an Order it will be there in the Shipment BC.
My initial approach was to create a domain event once an Order is placed in the Order placement BC and have the Shipment BC subscribe to that event and create a corresponding Order entity in its database for every order placed.
However, I can't stop that feeling that I'm duplicating data across different databases.
My second approach is to ask the Order Placement each time an order is being Shipped for an Order entity, but I still need to maintain the state of the Order in case a failure of a failure in the shipment.
Is there a better approach to all this from a DDD POV?
Your first approach is perfectly fine in my opinion. You are not duplicating data, because as you already noticed, that data is from another context. Same data in different contexts means different things.
As Vernon Vaughn pointed out in his book «Implementing Domain Driven Design»: "A greater degree of autonomy can be achieved when dependent state is already in place in our local system. Some may think of this as a cache of whole dependent objects, but that’s not usually the case when using DDD. Instead we create local domain objects translated from the foreign model, maintaining only the minimal amount of state needed by the local model.”
So copying data is okay as long as it is the only data other BCs need.
But he also mentions that if you use exact copies, it might be a sign of a modeling problem.

Advice on database model for ecommerce with custom products

I need some advice on modeling an ecommerce domain.
The client sells two products:
Custom art work, the design specified by the customer.
Prints of art with a message on the back specified by the customer.
Here is my cut down database model so far.
Products:
Id
Description
Price
Orderlines:
Id
OrderId
ProductId
Attributes:
Id
Name
OrderAttributes:
AttributeId
OrderlineId
Value
The products table will have the 2 products from above.
The order line links the selected product to an order.
The attributes holds the custom field names for each product.
For example the custom artwork product would have the attribute design.
The order attributes links the ordered product to it's customs attributes and has the value.
For example custom artwork product, with an attribute of design, with a value of paint a house.
I would also like to map this database model to code as well using nhibernate.
Is there a better way of modeling this data?
A couple of suggestions:
The Orderlines table should contain the price (and possibly the description) of the product so that item prices can change without affecting existing orders. Similarly, the Orders table (not shown) should contain customer information (e.g. shipping address) that may change. The data that makes up an order can't change and the easiest approach is to flatten and denormalize it.
The OrderAttributes structure is called an entity-attribute-value model and it has many drawbacks. In general I recommend avoiding it and adding the needed columns to the Orderlines table. If needed, your application can subclass Product and OrderLine so that a CustomArtWorkProduct creates a CustomArtWorkOrderLine when it's added to an order.
In an object-oriented program relations are expressed as associations.
That is:
If Product has Orders then Product must have a collection of Orders.
If an Order is for a Product, the Order must have a property Product.
and so on.
In object-oriented programming you don't associate by an identifier: you don't need this because this is a different world ruled by hierarchical data.
Honestly, if you follow what I said before, NHibernate will be a very powerful tool as it'll be able of loading objects and properties without your intervention.
Think about "getting all orders of some product": you're not going to intentionally execute an SQL Join but you're going to access to the Orders property of Product and NHibernate will translate this access to the database world.
This is the point of using an OR/M. It's not just "I map tables as is". It's about joining two very different worlds: the object-oriented hierarchical world with relational data with no pain.
Check this very old (2004!) CodeProject article and how it creates the Northwind SQL Server database-based model:
http://www.codeproject.com/Articles/8773/NHibernate-in-real-world-applications
Don't pay attention to how maps the model to the database but to the model design.
Check this article, it's more modern than the other one:
http://litemedia.info/introduction-to-nhibernate

Modelling the Domain from Two perspectives

I'm trying to model the domain of my system but I've come across and issue and could do with some help.
My issue is one of perspective. I'm modeling a system where I have a Customer entity which will have a number of Order entities and the system will be required to list all the Orders for a selected Customer (perspective 1). I therefore modeled a Customer class which contains a collection of Orders... simple. However I've just realised that the system will also need to list all Orders with the details of the Customer (perspective 2) which would mean that I had a single Customer reference from each Order.
The problem is that from each perspective I will be taking time to create object which I will not be interested in E.g. When I will display a list of Orders a Customer instance will be created for each order; in turn the Customer instance will then hold a collection of Orders they have made (which from this perspective I'm not interested in!!).
Could anybody help with suggestions? I've come across this issue before but I've never taken the time to design a proper solution.
Regards,
JLove
I have seen this before. The trick is to differentiate between Customer-Identity and Customer-Details (e.g. Orders). You can then link from all Order-Objects to the Customer-Identity-Object, and in the other view link from the Customer-Identity-Object to the Customer-Details-Object which further links to Order-Objects (you probably want this ordered chronologically).
The implementation can be held as on Object-System or as a relational Database (in which case you would have a table "Customers" with CustomerID as Key, their addresses etc; and a table "Orders" with OrderID as key, and CustomerID as another column.

SQL Server Business Logic: Deleting Referenced Data

I'm curious on how some other people have handled this.
Imagine a system that simply has Products, Purchase Orders, and Purchase Order Lines. Purchase Orders are the parent in a parent-child relationship to Purchase Order Lines. Purchase Order Lines, reference a single Product.
This works happily until you delete a Product that is referenced by a Purchase Order Line. Suddenly, the Line knows its selling 30 of something...but it doesn't know what.
What's a good way to anticipate the deletion of a referenced piece of data like this? I suppose you could just disallow a product to be deleted if any Purchase Order Lines reference it but that sounds...clunky. I imagine its likely that you would keep the Purchase Order in the database for years, essentially welding the product you want to delete into your database.
The parent entity should NEVER be deleted or the dependent rows cease to make sense, unless you delete them too. While it is "clunky" to display old records to users as valid selections, it is not clunky to have your database continue to make sense.
To address the clunkiness in the UI, some people create an Inactive column that is set to True when an item is no longer active, so that it can be kept out of dropdown lists in the user interface.
If the value is used in a display field (e.g. a readonly field) the inactive value can be styled in a different way (e.g. strike-through) to reflect its no-longer-active status.
I have StartDate and ExpiryDate columns in all entity tables where the entity can become inactive or where the entity will become active at some point in the future (e.g. a promotional discount).
Enforce referential integrity. This basically means creating foreign keys between the tables and making sure that nothing "disappears"
You can also use this to cause referenced items to be deleted when the parent is deleted (cascading deletes).
For example you can create a SQL Server table in such a way that if a PurchaseOrder is deleted it's child PurchaseOrderLines are also deleted.
Here is a good article that goes into that.
It doesn't seem clunky to keep this data (to me at least). If you remove it then your purchase order no longer has the meaning that it did when you created it, which is a bad thing. If you are worried about having old data in there you can always create an archive or warehouse database that contains stuff over a year old or something...
For data like this where parts of it have to be kept for an unknown amount of time while other parts will not, you need to take a different approach.
Your Purchase Order Lines (POL) table needs to have all of the columns that the product table has. When a line item is added to the purchase order, copy all of product data into the POL. This includes the name, price, etc. If the product has options, then you'll have to create a corresponding PurchaseOrderLineOptions table.
This is the only real way of insuring that you can recreate the purchase order on demand at any point. It also means that someone can change the pricing, name, description, and other information about the product at anytime without impacting previous orders.
Yes, you end up with a LOT of duplicate information in your line item table..; but that's okay.
For kicks, you might keep the product id in the POL table for referencing back, but you cannot depend on the product table to have any bearing on the paid for product...