Initial conditions:

There is a book with a given set of properties. The book is the essence.

public class Book { public Book(BookID id, string name, string author, double price) { ID = id; SetName(name); SetAuthor(author); SetPrice(price); } public BookID ID { get; } public string Name { get; private set; } public string Author { get; private set; } public double Price { get; private set; } public void ChangeName(string name) { SetName(name); } public void ChangeAuthor(string author) { SetAuthor(author); } public void ChangePrice(double price) { SetPrice(price); } private void SetName(string name) { if(name == null || name.Length == 0) { throw new ArgumentException("Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΊΠ½ΠΈΠ³ΠΈ"); } } private void SetAuthor(string author) { if(author == null || author.Length == 0) { throw new ArgumentException("Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ Π°Π²Ρ‚ΠΎΡ€Π° ΠΊΠ½ΠΈΠ³ΠΈ"); } } private void SetPrice(double price) { if(price < 0) { throw new ArgumentException("Π‘Ρ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ ΠΊΠ½ΠΈΠ³ΠΈ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ >=0"); } } } public class BookID { public int ID {get;} public BookID(int bookID) { ID = bookID; } } 

In the present case, the book has only 4 parameters:

  1. Entity ID
  2. Title
  3. Author
  4. Price

In this case, it is convenient to use a constructor to initialize the Book entity.

Situation

Let the book about 20 parameters. The situation is quite abstract. In the case of a book it may not be. However, this can occur when determining the model of the device and other similar cases.

In the case of a large number of parameters, I would create a separate class BookProperties for convenience, in which the properties of the book would be presented, but without a guarantee of their correctness. Then I would place an instance of the BookProperties class in the constructor of the Book entity in which validation would be performed.

Below is a variant code for a similar approach. For convenience, the same number of parameters is used as before.

 public class Book { public Book(BookID id, BookProperties bookProperties) { ID = id; SetName(bookProperties.Name); SetAuthor(bookProperties.Author); SetPrice(bookProperties.Price); } public BookID ID { get; } public string Name { get; private set; } public string Author { get; private set; } public double Price { get; private set; } public void ChangeName(string name) { SetName(name); } public void ChangeAuthor(string author) { SetAuthor(author); } public void ChangePrice(double price) { SetPrice(price); } private void SetName(string name) { if(name == null || name.Length == 0) { throw new ArgumentException("Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΊΠ½ΠΈΠ³ΠΈ"); } } private void SetAuthor(string author) { if(author == null || author.Length == 0) { throw new ArgumentException("Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ Π°Π²Ρ‚ΠΎΡ€Π° ΠΊΠ½ΠΈΠ³ΠΈ"); } } private void SetPrice(double price) { if(price < 0) { throw new ArgumentException("Π‘Ρ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ ΠΊΠ½ΠΈΠ³ΠΈ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ >=0"); } } } public class BookID { public int ID {get;} public BookID(int bookID) { ID = bookID; } } public class BookProperties { public string Name { get; set; } public string Author { get; set; } public double Price { get; set; } } 

The BookProperties class is intended solely for the convenience of creating a Book entity.

Question:

How much does this approach contradict DDD and how much is this approach correct in general?

    1 answer 1

    The essence of the class is distinguished by two main factors - individuality and life cycle.

    Than to come up with validation at the entrance, it is easier to do it on saving (assigning individuality at the database level, as an example).

    Those. You can create a class and change its properties-fields in any way you like, but on saving the entity there will be a validation of all the entered data. You do not need any additional class in this case.

    Additionally, the conservation validation helps a lot with the life cycle β€” almost always business requirements limit transitions from one state to another.


    UPD: Using an extra class looks superfluous, especially considering that only the constructor code has actually changed. The very appearance of the designer DDD does not limit, you can do as you like. Just remember that an idea with an always valid entity is important only in storage, and in work it is often exactly the opposite and the entity may be invalid at a particular point in time in a business process.

    • Many thanks for the answer, but my question was not about validation) As for validation, I don’t want to separate the rules set for the parameters, otherwise the model will become anemic. - Eladei
    • one
      @Eladei go further. Which one of the classes will you keep? How to restore a class from storage? Why do we need this class if it takes no responsibility? Your second code example has become more complicated exclusively, and only the signature of the constructor, which is unclear why it is needed in this form, has been simplified. - Monk
    • one
      @Eladei I propose to go further - remove these properties from the constructor. When you get out of the database - the properties in your essence get clogged up directly. When you save to the database, you validate the fullness and validity of the fields. No need to group anything. All that you can group with a decent probability will be either a separate entity or a child entity that exists within the parent, but is relatively independent. - Monk
    • one
      @Eladei Well, you created a valid book. And then it must be changed for any reason. Simple changes of the form "changed the property - immediately checked the validity" you can still maintain. But changes when the user changes 10 properties in turn and the entity in the interval between these operations is invalid - you can not? In general, I understand what you want easier. And yes, saving an entity can always be divided into the validation of the entity and the actual saving into the base, but stick it into one method of entity.Save() . Moreover, it is quite logical - so that it is impossible to preserve an invalid entity - Monk
    • one
      @Eladei no one bothers you to do this. The designer himself is not limited to the ideas of DDD. I just mean that your idea to create ready-made books at once with filled out required properties is quite controversial and can get you sideways in a bunch of places. - Monk