Say I have some Brands, each Brand have some Products. When define Entity follow CQRS pattern, is it good practice having List<Product> as a field of Brand? Or one Entity should never hold another Entity, I need to define another Entity BrandProductRelationship?
public class Brand {
private String id;
private String name;
private List<Product> products;
}
public class Product {
private String id;
private String name;
}
If so, when define brand created event, looks like I need to pass List<Product> as a parameter, which seems complicate.
public class BrandCreated implements Event {
public Brand apply() {
return new Brand(id, name, products);
}
}
Entities that contain other entities is fine, provided that they are all part of the same consistency boundary.
The story is different with aggregates; you don't normally want to have two different paths to modify the state of a single specific entity, so having one aggregate contain another is discouraged. In this case, you'll normally have one aggregate contain an identifier that can be used to look up the other.
public class Brand {
private String id;
private String name;
private List<String> productsIds;
}
Is better; but it demonstrates primitive obsession. In Domain Driven Design, entities are more likely to be expressed using values from the domain model itself.
public class Brand {
private Identifier<Brand> id;
private Name name;
private List<ProductId> productsIds;
}
or even
public class Brand {
private Identifier<Brand> id;
private Name name;
private ProductCatalog catalog;
}
Related
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);
}
}
I've generated a new project with JHipster v4.6.0 generator and I'm using its EntityMapper interface to do the mapping between domain and DTO objects.
public interface EntityMapper <D, E> {
public E toEntity(D dto);
public D toDto(E entity);
public List <E> toEntity(List<D> dtoList);
public List <D> toDto(List<E> entityList);
}
I need to use the Spring projection to have a smaller domain and DTO objects, (I don't want all fields of the entity), so I've created an interface with only the getters of the fields I need, and I've created a method in the repository which retrive this interface type (following the Spring reference guide)
public interface ClienteIdENome {
Long getId();
String getNome();
}
#Repository
public interface ClienteRepository extends JpaRepository<Cliente,Long> {
ClienteIdENome findById(Long id);
}
The query findById retrieve a ClienteIdENome object with only id and nome fields.
Now, I would like to map this object in the following DTO:
public class ClienteIdENomeDTO implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
#NotNull
#Size(max = 50)
private String nome;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
So, I created the mapper interface:
#Mapper(componentModel = "spring", uses = {})
public interface ClienteIdENomeMapper extends EntityMapper<ClienteIdENomeDTO, ClienteIdENome> {
}
But Eclipse report to me an error in the EntityMapper interface for the method "public E toEntity(D dto)" with the message:
No implementation type is registered for return type it.andrea.ztest01.repository.ClienteIdENome.
Any help?
Thanks a lot
Your ClienteIdENome is not really an entity. I would argue that you don't need to use the EntityMapper, but you need to define a one way mapper. From ClienteIdENome to ClienteIdENomeDTO.
Your mapper needs to look like:
public interface ClienteIdENomeMapper {
ClienteIdENomeDTO toDto(ClienteIdENome entity);
List <ClienteIdENomeDTO> toDto(List<ClienteIdENome> entityList);
}
I don't know JHipster, so I can't say what will mean using a mapper different than EntityMapper.
I've parent and child class with respective DTO's as follows
class Parent {
List<Child> children;
// setters and getters
}
class Child {
Parent parent;
}
class ParentDto {
List<ChildDto> children;
// setters and getters
}
class ChildDto {
ParentDto parent;
// setters and getters
}
When I try to map Parent to ParentDto I'm getting StackOverflowError.
Please help me in resolving the issue.
I know this post is old but I will try to give one answer in case someone from google to arrived here.
Probably you have a dynamic object creation.
Recently I had a problem like this. In my case I have a class Student that extends Person. And Person has three others attributes of type Person: father, mother and responsible. In case, I had a circularity relationship. When I ran my JUnits tests I got a circularity calls. I did't get a stakOverflow because the Spring (after some time) closes the data base connections.
I resolved this problem removing the dynamics objects creations from my Person class.
Another approach to solve this problem is adding a Condition in your mapper. You can read more about conditions here. For example, you can have some Conditions saying: "If the person attribute id is 10, then, doesn't need map it.". This way we can avoid infinity mapping.
Well, let's see some snippeds of code:
Student class:
public class Student extends Person implements IStudent {
private Person financialResponsible;
// Getters and setters.
}
Person class:
public class Person implements IPerson {
private Long id;
private String name;
private Person father;
private Person mother;
private Person responsible;
private Address address;
// Getters and setters.
// This is my real problem. I removed it and the mapper worked.
public IPerson getFather() {
if (father == null) father = new Person();
return father;
}
}
StudentDTO class:
public class StudentDTO extends PersonDTO {
private PersonDTO financialResponsible;
// Getters and setters.
}
PersonDTO class:
public class PersonDTO {
private Long id;
private String name;
private PersonDTO father;
private PersonDTO mother;
private PersonDTO responsible;
private AddressDTO address;
// Getters and setters.
}
Here is a example of conditions:
...
import org.modelmapper.Condition;
...
ModelMapper mapper = new ModelMapper();
// Define STRICT to give high precision on mapper.
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
/*
* Create conditions to avoid infinity circularity.
*/
// Condidions.
final Condition<IStudent, StudentDTO> fatherIsTen = mappingContext -> mappingContext.getSource().getFather().getId() == 10;
final Condition<IStudent, StudentDTO> motherIsTen = mappingContext -> mappingContext.getSource().getMother().getId() == 10;
final Condition<IStudent, StudentDTO> resposibleIsTen = mappingContext -> mappingContext.getSource().getResponsible().getId() == 10;
// Adding conditions on mapper.
mapper.createTypeMap(IStudent.class, StudentDTO.class) //
.addMappings(mapper -> mapper.when(fatherIsTen).skip(StudentDTO::setFather))
.addMappings(mapper -> mapper.when(motherIsTen).skip(StudentDTO::setMother))
.addMappings(mapper -> mapper.when(resposibleIsTen).skip(StudentDTO::setResponsible));
I hope help o/
Given an XML file of offerings that is then loaded into a class called Offerings via JAXB.
This class has the following:
Name, Price sub-Class, Modifiers, Ordering Rules etc.
I then create an order and within that order
Order
public class ProductOrder {
private String OrderId;
private Date createDate;
private OrderStatus orderStatus;
private int CustomerOrderID;
private ArrayList<ProductOrderItem> productOrderItems = new ArrayList<ProductOrderItem>();
}
Order Item
public class ProductOrderItem {
private int OrderItemID;
private **Offering** offering;
private Map<String, Integer> qtylist = new HashMap<String, Integer>();
private ArrayList<Modifier> modifiers = new ArrayList<Modifier>();
private int qty;
}
Offering
#XmlRootElement(name = "offering")
#XmlAccessorType(XmlAccessType.FIELD) // NONE)
public class Offering {
#XmlAttribute
private String id;
#XmlElement
private String offeringName;
#XmlElement
private String description;
#XmlElement
private Integer price;
}
The Offering and Modifiers are classes with JAXB already which I only want to push part of the XML. How would I change the anotations such that only part of the elements are sent? For example not the offering -> modifiers?
Use #XmlTransient instead of the #XmlElement tag.
I have a Userdetails class like the one below
public class UserDetails
{
public string ssn;
public string username;
public string emailid;
public Address address;
}
Here Address is another class that will have public fields like
public class Address
{
public int id;
public string address;
}
Now, when the user logs in the app, i construct the Userdetails object. Now i will not use address object inside the userdetails very frequently, but have got data.
In this scenario how can i use the Lazy initialization feature of C# 4.0.
Note that the data is taken from direct db query and none of these classes have constructors or other means to get the data. These are just representations of the database fields in C#.
Suggest me the best way to use lazy initialization here.
You can have a private lazy address:
private Lazy<Address> _address = new Lazy<Address>(() => {
---code to get the address---
});
public Address address {
get {
return _address.Value;
}
}