Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Looking into DDD and something I noticed is that business logic should be in the model, otherwise you just have property bags. That said how do you handle pieces of validation that require a trip to the database?

For example, you have an domain object that represent categories for a blogging engine.

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

From a developer's perspective, you could create an empty category, but this isn't valid in the business world. A Category requires a Name to be a valid category, therefore we end up with:

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Category(string name)
    {
        Name = name;
    }
}

Now, a Category can't be created without a name. But, we can't have duplicate Category names either, that would just cause confusing and redundancy. I don't want the entity to handle it themselves because this would end up more of an Active Record Pattern and I don't want the model to be "self-aware/persisting" so to speak.

So to this point, where should this validation take place. It is important that if the user types an duplicate Category, we would notify the user of this. Should there be a "service" layer that takes a UI model and turns it into the domain model and attempts to validate it, pushing errors back to the UI, or should there be something closer to the data layer that handles this?

Someone please set me straight because I really like where DDD is going, I just can't make all the connections to get there myself.

share|improve this question
1  
DDD is a design methodology, not a coding methodology. The only place where you can do this reliably is in the database, since that is the only part of the system that has awareness of all of the transactions that have taken place for every user. –  Robert Harvey Oct 8 '14 at 22:14
    
@RobertHarvey Does DDD prescribe some coding methodology? For example, Anemic Domain Models. This is saying that the Domain models should contain behavior (not saying this isn't just a natural part of OOP, but it seems with all the design patterns, sometimes we just lose track). It is telling me code for behavior belongs in the Domain model. Surely, somewhere DDD states certain concerns should be handled at a certain "layer". –  Justin Oct 9 '14 at 13:08
    
If the design methodology/coding methodology you're using isn't doing what you want, why are you using it? –  Ampt Oct 9 '14 at 15:31
    
@Ampt It isn't that it isn't doing what I want, just where is the best place to handle this and does DDD prescribe a place, or the respective user's experience, that meshes better than placing it somewhere else. Is there a standard for placement, so to speak. If you looked at a project using DDD, where would YOU expect to find it with your experiences using DDD. This makes it more opinionated, but input from others is important for this if one isn't roughly outlined in DDD "specs". –  Justin Oct 9 '14 at 15:38
1  
In my experience, DDD is more about providing software developers and business stakeholders a common language by which they can describe business domains, than it is about rigidly dictating where every possible software artifact goes. –  Robert Harvey Oct 9 '14 at 15:46

4 Answers 4

Why don't you create a service holding a collection of all categories? Then you can do validation very easy. An example:

class BlogCategoryService 
{
   private List<Category> _categories = new List<Category>();

   public void AddCategory(string categoryName) 
   {
       if (_categories.Any(c => c.Name == categoryName)) 
           throw new DuplicateCategoryException(categoryName);

       var newId = ...

       _categories.Add(new Category(newId, categoryName));
   }
   ...
}

Do the name validation in your Category class:

public class Category
{
    public int Id { get; private set; }
    public string Name { get; private set; }

    public Category(int id, string name)
    {
        ValidateName(name);

        Id = id;
        Name = name;
    }

    private void ValidateName(string name)
    {
       if (string.IsNullOrWhitespace(categoryName))
           throw new ArgumentException('Category name may not be null or whitespace.');
    }

}

If you want to change name on a category, you could depend on your service:

public class Category
{
    ...

    public void ChangeName(BlogCategoryService service, string newName)
    {
        if (service == null)
            throw new ArgumentNullException('service');

        ValidateName(newName);

        if (!service.IsUniqueCategoryName(newName))
            throw new DuplicateCategoryException(newName);

        Name = newName;
    }
}

public class BlogCategoryService 
{

    ...
    public bool IsUniqueCategoryName(string name)
    {
        return !_categories.Any(c => c.Name == name);
    }
}

Also add a unique constraint on the name column of the blog category table to to guard against someone making changes outside of your BlogCategoryService.

share|improve this answer

business logic should be in the model, otherwise you just have property bags

What is business logic? Business logic is, that your object knows it's state and could answer questions like order.IsDistributed or order.IsQualityAssuranceDone or the like. It is no business logic, if you ask the question is this order already in the database. That is a different responsibility: It belongs not to the order itself, since it isn't a state of the order, it is the state of the database. Therefore you should ask the database for that answer.

From a developer's perspective, you could create an empty category, but this isn't valid in the business world

To maintain a clean state, you should use properties (in C#) / getter and setter, where you implement validation-logic, to keep the object's state clean and tidy.

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Category(string name)
    {
        Name = name;
    }
}

This design has a big flaw: It mirrors not your requirement exactly of having a name, since the constructor could be called with null, which is not in every sense a valid name. On the other hand, you could use the builder pattern and do the construction via a builder-interface.

Now, a Category can't be created without a name. But, we can't have duplicate Category names either, that would just cause confusing and redundancy.

These are two different concerns. One belongs to the object's state the other to the database's state.

Should there be a "service" layer that takes a UI model and turns it into the domain model and attempts to validate it, pushing errors back to the UI, or should there be something closer to the data layer that handles this?

Whether you use a service-layer is up to you. Sometimes it is drowning little puppies to make the indirection. It depends on how much logic is there.

share|improve this answer

Q:How do we create objects? A: Using Domain Factories!

Since the creation of a category contains complex logic (we need to validate uniqueness), we will utilize a domain factory to create the object for us.

Inside that factory I'll use a UniqueCategoryNameValidator service that calls into the data-store (a DB in ur case) and check if the category is unique. Some people might refer to this approach as using the specification pattern as follows:

UniqueCategoryNameSpecification.isSatisfiedBy(category); 

Using a specification makes the check for uniqueness explicit in your domain. The specification would use an infrastructure service to query the database.

share|improve this answer

I would create a domain service responsible for validating the uniqueness of the category. In my solution domain defines the interface of the service, infrastructural part implements it using a database.

Please also take a look at http://stackoverflow.com/questions/516615/validation-in-a-domain-driven-design.

share|improve this answer
3  
It probably makes more sense to have validation occur as part of the save process for the new category. Having a domain service whose sole responsibility is verifying the uniqueness of the new category only guarantees the new category is unique at the time you checked it; the save operation can still fail if some other user created the same category in the meantime (unlikely as that scenario may be, it's still possible). –  Robert Harvey Oct 9 '14 at 22:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.