KissSpecifications
A KISS approach for specification pattern
Install / Use
/learn @giacomelli/KissSpecificationsREADME
KissSpecifications
A KISS approach for specification pattern. http://en.wikipedia.org/wiki/Specification_pattern
Setup
NuGet
PM> Install-Package KissSpecifications
Features
- ISpecification : interface to define any kind of specification
- SpecificationBase<TTarget> : base class to easy create new specifications
- SpecificationService : Service class with features to validate specifications
- SpecificationGroups : attribute to define groups for a specification
- Commons specifications
- MustHaveNullOrDefaultPropertySpecification
- MustNotBeNullSpecification
- MustNotHaveEmptyPropertyTextSpecification
- MustNotHaveNullOrDefaultPropertySpecification
- Globalization
- IGlobalizationResolver interface to define any kind of globalization for commons specifications
Using
- Create your specification classes:
public class CustomerMustHaveValidNameSpecification : SpecificationBase<string>
{
#region Constants
public const int MinCustomerName = 5;
public const int MaxCustomerName = 30;
#endregion
#region Methods
public override bool IsSatisfiedBy(string target)
{
if (String.IsNullOrWhiteSpace(target))
{
NotSatisfiedReason = "Customer name should be specified.";
return false;
}
if (target.Length < MinCustomerName)
{
NotSatisfiedReason = String.Format(CultureInfo.CurrentUICulture, "The minimum length for customer name is {0} chars.", MinCustomerName);
return false;
}
if (target.Length > MaxCustomerName)
{
NotSatisfiedReason = String.Format(CultureInfo.CurrentUICulture, "The maximum length for customer name is {0} chars.", MaxCustomerName);
return false;
}
return true;
}
#endregion
}
- Call the SpecificationService on your Domain method:
public static class CustomerService
{
public static void CreateCustomer(Customer customer)
{
SpecificationService.ThrowIfAnySpecificationIsNotSatisfiedBy(customer, new CustomerCreationSpecification());
// TODO: Logic to create customer...
}
}
Create Groups of specification
Defining groups
You can use any object to declare a group key for your specification, but is always better to define constants or enumerators.
/// <summary>
/// Just a enum to define my specification groups.
/// </summary>
public enum SampleSpecificationGroup
{
Save = 0,
SendEmail = 1,
}
[SpecificationGroups (SampleSpecificationGroup.Save, "Sell")]
public class CustomerMustHaveNameSpecification : ISpecification<Customer>
{
...
}
[SpecificationGroups (1, 5)]
public class CustomerMustHaveValidAccountSpecification : ISpecification<Customer>
{
...
}
[SpecificationGroups (SampleSpecificationGroup.SendEmail)]
public class CustomerMustHaveEmailSpecification : ISpecification<Customer>
{
...
}
[SpecificationGroups (Constants.AConstantValue, "Sell", 1)]
public class CustomerCanNotHaveDebitSpecification : ISpecification<Customer>
{
...
}
Validate
- Call the SpecificationService on your Domain method defining groups that you want to validate:
public static class CustomerService
{
public static void CreateCustomer(Customer customer)
{
SpecificationService.ThrowIfAnySpecificationIsNotSatisfiedBy(customer, SampleSpecificationGroup.Save);
// TODO: Logic to create customer...
}
}
Best practices
Naming
Let everyone know exactly what you are trying to specify! Create meaningful names for your specification classes. It will keep your code readable and easy to maintain.
public static class CustomerService
{
public static void CreateCustomer(Customer customer)
{
SpecificationService.ThrowIfAnySpecificationIsNotSatisfiedBy(
customer,
new CustomerMustHaveNameSpecification(),
new CustomerMustHaveValidAccountSpecification(),
new CustomerMustHaveEmailSpecification(),
new CustomerCanNotHaveDebitSpecification());
// TODO: Logic to create customer...
}
}
License
Licensed under the The MIT License (MIT). In others words, you can use this library for developement any kind of software: open source, commercial, proprietary and alien.
Change Log
- 1.1.9 HelperSharp updated.
- 1.1.8 Added MustExistsSpecification.
- 1.1.7 Added MustHaveUniqueTextSpecification.
- 1.1.6 Added specification groups feature.
- 1.1.5 Added MustNotBeNullSpecification.
- 1.1.4
- KissSpecificationsConfig
- IGlobalizationProvider
- Commons specifications
- MustHaveNullOrDefaultPropertySpecification
- MustNotHaveEmptyPropertyTextSpecification
- MustNotHaveNullOrDefaultPropertySpecification
- 1.1.0 Added SpecificationService.ThrowIfAnySpecificationIsNotSatisfiedByAny.
- 1.0.0 First version.
Related Skills
product-manager-skills
34PM skill for Claude Code, Codex, Cursor, and Windsurf: diagnose SaaS metrics, critique PRDs, plan roadmaps, run discovery, and coach PM career transitions.
devplan-mcp-server
3MCP server for generating development plans, project roadmaps, and task breakdowns for Claude Code. Turn project ideas into paint-by-numbers implementation plans.
