C
C#6mo ago
M B V R K

Is this DDD Specification a good practice or not?

Hi friends, hope you're all doig well, I'm working on a project by implementing the DDD (Domain Driven Design), As you know that one of the core concepts of DDD is the Specification Pattern (Specifications), I have written the following Specification:
/// <summary>
/// Represents a specification that checks if a category with the same name for the same user already exists.
/// </summary>
public class IsUniqueCategoryNameSpecification: Specification<Category>
{
readonly ICategoryUniquenessChecker _categoryUniquenessChecker;

public IsUniqueCategoryNameSpecification(ICategoryUniquenessChecker categoryUniquenessChecker)
{
_categoryUniquenessChecker = categoryUniquenessChecker;
}

protected override void ConfigureConditions()
{
AddCondition(category =>
category.Id == Guid.Empty ? _categoryUniquenessChecker.IsUniqueCategoryNameAsync(category.Name, category.UserId).Result
: _categoryUniquenessChecker.IsUniqueCategoryNameAsync(category.Id, category.Name, category.UserId).Result, "Category name must be unique.");
}
}
/// <summary>
/// Represents a specification that checks if a category with the same name for the same user already exists.
/// </summary>
public class IsUniqueCategoryNameSpecification: Specification<Category>
{
readonly ICategoryUniquenessChecker _categoryUniquenessChecker;

public IsUniqueCategoryNameSpecification(ICategoryUniquenessChecker categoryUniquenessChecker)
{
_categoryUniquenessChecker = categoryUniquenessChecker;
}

protected override void ConfigureConditions()
{
AddCondition(category =>
category.Id == Guid.Empty ? _categoryUniquenessChecker.IsUniqueCategoryNameAsync(category.Name, category.UserId).Result
: _categoryUniquenessChecker.IsUniqueCategoryNameAsync(category.Id, category.Name, category.UserId).Result, "Category name must be unique.");
}
}
Please could you tell me if this is a good implementation for a specification, or this just wrong manner, because this is the first time I write a specification that needs to deal with database? Please share with me your experience guys, and massive thanks in advance <3 For more info and definition of the Specification<T> class take a look here : https://github.com/MbarkT3STO/ExpenovaApp/blob/main/Source/ExpenseService/ExpenseService.Domain/Specifications/Specification.cs
GitHub
ExpenovaApp/Source/ExpenseService/ExpenseService.Domain/Specificati...
Contribute to MbarkT3STO/ExpenovaApp development by creating an account on GitHub.
4 Replies
raZ
raZ6mo ago
you should only apply the rules on the specification.. do not make the async call in the configure rules. you should only configure the rules and someone else AKA as the repository is executing them. you can take a look in this repo for examples https://github.com/dotnet-architecture/eShopOnWeb/tree/main/src/ApplicationCore/Specifications you can always read some simle examples here: https://deviq.com/design-patterns/specification-pattern
GitHub
eShopOnWeb/src/ApplicationCore/Specifications at main · dotnet-arch...
Sample ASP.NET Core 8.0 reference application, powered by Microsoft, demonstrating a layered application architecture with monolithic deployment model. Download the eBook PDF from docs folder. - do...
DevIQ
Specification Pattern | DevIQ
One Domain-Driven-Design solution to the problem of where to place querying, sorting, and paging logic is to use a Specification.
M B V R K
M B V R K6mo ago
Thanks for your time and response, But as I know that the second link is implementing the specification pattern in generic case, but I'm here dealing with DDD and the Specifications of DDD should take a Domain Entity to tell you if satisfied or not ( and maybe I'm wrong ) But anyway thanks a lot for you time and help I appreciate
raZ
raZ6mo ago
I am aware that you are talking about DDD but i see almost no difference in any specification and ddd.. if we take your implementation i guess the check has access to the DB in order to check the uniqueness i would recommend to extract all the data in the application layer and then just push the aggregate that hold all the data into the specification. That way you are able to run multiple checks together and build some complex business rules in the specification.
M B V R K
M B V R K6mo ago
Clear man <3, What about this one ? what do you think ?
/// <summary>
/// Represents a specification that checks if a category with the same name for the same user already exists.
/// </summary>
public class IsUniqueCategoryNameSpecification: Specification<Category>
{
readonly ICategoryUniquenessChecker _categoryUniquenessChecker;

public IsUniqueCategoryNameSpecification(ICategoryUniquenessChecker categoryUniquenessChecker)
{
_categoryUniquenessChecker = categoryUniquenessChecker;
}

protected override void ConfigureRules()
{
AddRule(category => _categoryUniquenessChecker.IsUniqueCategoryNameAsync(category.Id, category.Name, category.UserId).Result, "Category name must be unique.");
}
}
/// <summary>
/// Represents a specification that checks if a category with the same name for the same user already exists.
/// </summary>
public class IsUniqueCategoryNameSpecification: Specification<Category>
{
readonly ICategoryUniquenessChecker _categoryUniquenessChecker;

public IsUniqueCategoryNameSpecification(ICategoryUniquenessChecker categoryUniquenessChecker)
{
_categoryUniquenessChecker = categoryUniquenessChecker;
}

protected override void ConfigureRules()
{
AddRule(category => _categoryUniquenessChecker.IsUniqueCategoryNameAsync(category.Id, category.Name, category.UserId).Result, "Category name must be unique.");
}
}