I've been looking managing Root Aggregate state/life-cycle and found some content about the benefits of using Explicit State Modeling or Explicit Modeling over State Pattern, it's much cleaner and I like how I can let explicit concepts of my domain handle their own behavior.
One of the things I read was this article that is influenced by Chapter 16 in "Patterns, Principles, and Practices of Domain-Driven Design - Scott Millett with Nick Tune" book (here's a code sample for the full example).
The problem is the idea is described very briefly and there is not much content around it and that appeared when I started to implement it and given that I am new to DDD, the concepts started to overlap, and here are some of the questions that I am hoping more experienced engineers in DDD would help or at least someone has interpreted the text better than me.
Following the article's example, how would I retrieve a list of all doors (that are both open and closed), what Domain Entity would this result-set map to?
If all the explicit states models are entities/aggregates, what would be the root aggregate?
would it be normal that there is no reference between Root Aggregate and those explicitly modeled entities?
And if the Aggregate Root (let's say a generic Door entity) returns an explicit state entity, how would the repository save it without exposing the state of the entity or aggregate?
Or are all these explicit entities root of their own aggregate?
I am not expecting to get all the above answered, I am just sharing the thoughts that am stuck at, so you are able to see where I am standing, as there is too much ambiguity for me to share code but I hope the snippets from the article and the book can help.
A git repository or a sample project addressing how would other DDD components with Explicit modeling would be really helpful (I have checked a million repositories but 90% with no luck).
Note: I am not using CQRS
Example from Medium Article:
interface ClosableDoor
{
public function close();
}
// Explicit State. (third attempt)
class CloseDoorService()
{
// inject dependencies
public function execute($doorId)
{
$door = $this->doorRepository->findClosableOfId($doorId);
if (!$door) {
throw new ClosableDoorNotFound();
}
$door = $door->close();
$this->doorRepository->persist($door);
}
}
Example from the book:
// these entities collectively replace the OnlineTakeawayOrder entity (that used the state pattern)
public class InKitchenOnlineTakeawayOrder
{
public InKitchenOnlineTakeawayOrder(Guid id, Address address)
{
...
this.Id = id;
this.Address = address;
}
public Guid Id { get; private set; }
public Address Address { get; private set; }
// only contains methods it actually implements
// returns new state so that clients have to be aware of it
public InOvenOnlineTakeawayOrder Cook()
{
...
return new InOvenOnlineTakeawayOrder(this.Id, this.Address);
}
}
public class InOvenOnlineTakeawayOrder
{
public InOvenOnlineTakeawayOrder(Guid id, Address address)
{
...
this.Id = id;
this.Address = address;
}
public Guid Id { get; private set; }
public Address Address { get; private set; }
public CookedOnlineTakeawayOrder TakeOutOfOven()
{
...
return new CookedOnlineTakeawayOrder(this.Id, this.Address);
}
}
Note: I am not using CQRS
I think this is the biggest challenge you have.
Retrieving explicitly modelled entities for the purpose of the use case being implemented would not cause such a headache if you were not also trying to use them for queries that may not be constrained to an explicit model designed for a specific use case.
I use Entity Framework which supports "table-splitting" that could help in this situation. Using this, many entities can be mapped to the same table but each can deal with a subset of the fields in the table and have dedicated behaviour.
// Used for general queries
class Door
{
public Guid Id { get; private set; }
public State State { get; private set; }
// other props that user may want included in query but are not
// relevant to opening or closing a door
public Color Color { get; private set; }
public Dimensions Dimensions { get; private set; }
public List<Fixing> Fixings { get; private set; }
}
class DoorRepository
{
List<Door> GetDoors()
{
return _context.Doors;
}
}
// Used for Open Door use case
class ClosedDoor
{
public Guid Id { get; private set; }
public State State { get; private set; }
public void Open()
{
State = State.Open;
}
}
class ClosedDoorRepository
{
List<ClosedDoor> GetClosedDoors()
{
return _context.ClosedDoors.Where(d => d.State == State.Closed);
}
}
// Used for Close Door use case
class OpenDoor
{
public Guid Id { get; private set; }
public State State { get; private set; }
public void Close()
{
State = State.Closed;
}
}
class OpenDoorRepository
{
List<OpenDoor> GetOpenDoors()
{
return _context.OpenDoors.Where(d => d.State == State.Open);
}
}
Related
What are your methods to deal with the communication of an admin panel with a domain in the case of changing values of properties of an entity without breaking the encapsulation?
public class Book : Entity {
public Book(string title, string author, string description, decimal price, short publicationYear) {
Title = title;
Author = author;
Description = description;
Price = price;
PublicationYear = publicationYear;
}
public string Title { get; private set; }
public string Author { get; private set; }
public string Description { get; private set; }
public decimal Price { get; private set; }
public short PublicationYear { get; private set; }
}
The only way to not break encapsulation is to include some parts of the presentation logic into the object itself. Not the details, mind you, but the parts which are highly coupled to this object.
I would do something like this (pseudo-code):
public class Book {
public Book(...) {
...
}
public InputComponent<Book> createAdminView() {
return new FormGroup<Book>(
new TextInput(title),
new TextInput(author),
...);
}
}
This way there is no need to publish any of the internal data fields of the object, nobody needs to know how to book looks like, and all changes related to the object will be localized.
In fact, I've been doing this for a couple for years now, and this design results in much easier to maintain code. Have a look at my presentation about Object-Oriented Domain-Driven Design to find out more: https://speakerdeck.com/robertbraeutigam/object-oriented-domain-driven-design
In a sequence diagram if my method get_user_by_id( id ) calls the database or uses a framework that have a dbSet containing collections of users for example. how do i call it in a diagram i can't find find documentation about this.
by documentation i mean maybe a lot of documents or a book that have it's content or part of it available for free. i know that using something like : Set(User) means it's a collection of that class that and the database is, well, data? magic?
Note : i am talking about UML 2 in case there is a difference with UML 1.x
the source code using dbSet
public partial class DBEntities : DbContext
{
public DBEntities()
: base("name=DBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<ClassA> AdmExportDefinition { get; set; }
public virtual DbSet<ClassB> AdmImportModels { get; set; }
public virtual DbSet<ClassC> AdmImportModFields { get; set; }
}
I'm struggling hard to find a proper design to avoid referencing a Repository from an Entity... Let's say I've got the classic Customer and Order classes like so:
public class Customer {
...
public IEnumerable<Order> Orders { get; set; }
}
public class Order {
...
public Customer Customer { get; set; }
public IEnumerable<OrderItem> OrderItems { get; set; }
public void Submit() {
...
}
}
public class OrderItem {
public Product Product { get; set; }
public decimal SellingPrice { get; set; }
}
Now, let's say that the Product's selling price depends for some reason on the fact that the Product was also purchased (or not) on the previous Order, the number of items on the current order and previous order, etc. I could do this:
public void Submit() {
Order lastOrder = this.Customer.Orders.LastOrDefault();
CalculatePrice(lastOrder);
but that would load the whole order list of Orders when I only really need the last one!
What I'd like to do is something more like this:
public void Submit() {
Order lastOrder = _orderRepository.GetLastOrderFor(Customer);
CalculatePrice(lastOrder);
But I understand referencing the OrderRepository in the Domain is bad DDD. So, what do I do? Do I have to put the Submit() elsewhere than in the Domain? If so, where do you suggest?
You have two varieties:
Create a domain service and add a dependency to the repository from it:
public class MyPricingStrategy : IPricingStrategy
{
public MyPricingStrategy(IOrderRepository repository)
{ ... }
}
this way you will make domain service reference repository which is not very bad idea.
Another option is to make the pricing strategy a domain object with application layer passing it required data from repository:
public class LastOrderPricingStrategy
{
public LastOrderPricingStrategy(Order lastOrder)
{ ... }
}
in application layer
var lastOrder = orderRepository.GetLastOrder(currentCustomer);
var pricingStrategy = new LastOrderPricingStrategy(lastOrder);
The Customer object could have a LastOrder property:
public class Customer {
...
public IEnumerable<Order> Orders { get; set; }
public Order LastOrder { get; set; }
}
So part of the logic of making an order sets this field, and this will be saved with the Customer. Then when you load the customer, you will quickly know what the last order way, and make your decisions based on that accordingly.
Another way, if you are using an ORM like NHibernate, you could create a multi query to eagerly load the Orders collection with only the last order. then you could go back to using this:
public void Submit() {
Order lastOrder = this.Customer.Orders.LastOrDefault();
CalculatePrice(lastOrder);
and it would not need to load anything because the order you need will be in there. Eagerly loading only the objects I'm going to need in a collection is a pattern I use quite a lot.
I see these types of model is many samples online.
public class User
{
public long Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Is it considered a good practice to instantiate a collection in the constructor like the code below? If so what are the reasons? How about objects in the model?
public class User
{
public User()
{
Products = new List<Product>();
}
public long Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Well, I would say it depends on the situation, but Products in this case would be filled from the database, via a repository, so most probably ORM of some sort, so no initialization to new List would be needed in the constructor. The meaning of null for Products is indicative that the list isn't loaded yet. On the other hand, let's say that your object must have this collection initialized. For simple objects DDD says constructors are perfectly fine to to these things, but in case of complex objects, move the construction to the Factory.
How do restrict access to a class property to within the same namespace? Consider the following class. The Content class cannot Publish itself, instead the ContentService class
will do a few things before changing the state to published.
public class Content : Entity, IContent
{
public string Introduction { get; set; }
public string Body { get; set; }
public IList<Comment> Comments { get; set; }
public IList<Image> Images { get; private set; }
public State Status { get; }
}
public class ContentService
{
public IContent Publish(IContent article)
{
//Perform some biz rules before publishing
article.Status = State.Published;
return article;
}
}
How can i make it so only the ContentService class can change the state of the article?
Are there any deisng patterns to help me deal with this?
You can use the "internal" access modifier so that only classes within the same Assembly can modify the Content class's State member (but everyone even in other assemblies can GET the value).
public State Status { get; internal set; }
So now ContentService can set the state because it is in the same Assembly, but outside callers can only get the state (they're not allowed to set it).
Java has the notion of "package visible" or "package private". This is in fact the default for anything where you don't specify a visibility (private or public). For some reason, almost no one ever uses this.
Declare ContentService as a friend?
Alternatively, Java has an access modifier that amounts to "package-private".