There's a task connected with changing state of an entity. And I'm quite confused thinking whether it should be an event-based approach which involves something like CQRS
or I can use a State pattern
and leave all logic inside the entities.
I have found an article which shows a domain model (or a piece of it) that uses a State pattern: http://www.prowareness.com/blog/?p=1448
Ordering system is quite close to my domain model. So the example is great. But still I'm wondering if it is a good practice considering MVC pattern and if it is possible to implement with RavenDB/NHibernate
?
EDIT: question rethought
Let's follow the example:
First, here's a domain entity called Idea
:
[Serializable]
public class Idea : AbstractEntity<Guid> {
private static IStateFactory stateFactory;
private AbstractState state = new InitiatedState();
[Required, StringLength(150)]
public String Title { get; set; }
[Required]
public String ProblemContext { get; set; }
public DateTime CreatedOn { get; set; }
public Guid InitiatorId { get; set; }
[Required]
public Decimal InvestmentAmount { get; set; }
public Boolean IsInitiated {
get { return this.state.IsInitiated; }
}
public Boolean IsRejected {
get { return this.state.IsRejected; }
}
public Boolean IsUnderInitialAssessment {
get { return this.state.IsUnderInitialAssessment; }
}
public Boolean IsConfirmedForImplementation {
get { return this.state.IsConfirmedForImplementation; }
}
}
Whereas AbstractState
is:
public abstract class AbstractState {
public virtual Boolean IsInitiated {
get { return true; }
}
public virtual Boolean IsRejected {
get { return false; }
}
public virtual Boolean IsUnderInitialAssessment {
get { return false; }
}
public virtual Boolean IsConfirmedForImplementation {
get { return false; }
}
}
and state factory interface is defined like this:
public interface IStateFactory {
AbstractState GetState(String state);
}
the final thought is to put the method:
public void AlterState(String stateString) {
this.state = stateFactory.GetState(stateString);
}
AbstractState
itself everything changes accordingly.Thanks!
A Domain Model identifies the relationship among the entities that are in the scope of the problem domain. It describes the various entities that are attributes, roles and relationships that govern the problem domain.
State has two main characteristics: the behavior of domain object (how it responds to business methods) depends on the state and business methods may change the state forcing the object to behave differently after being invoked.
Domain Layer (Model in MVC): Represents concepts of the business, information about the system situation and business rules. Business state is controlled and used here but the technical details of storing it are delegated to the Infrastructure layer. In MVC terms, this is the Model.
The Domain Entity pattern. Entities represent domain objects and are primarily defined by their identity, continuity, and persistence over time, and not only by the attributes that comprise them.
You maybe interested in Stateless, a hierarchical state machine by Nicholas Blumhardt. Read this my SO answer here regarding it's capability. Here is a simple workflow processor example from my blog, and I currently use it with the Pipe and Filter pattern, and it works quite nicely.
Edit
I also have an implementation that uses Stateless with RavenDB if you are interested.
CQRS and the state pattern are completely different things. The state pattern provides a way to implement a set of states or statuses for a single object whereas CQRS is an architectural style. MVC has nothing to do with the state pattern nor CQRS and is an architectural style for the presentation layer. You can use the state pattern in conjunction with NHibernate, however the mapping will be non-trivial and you will have to implement a custom IUserType to map to the appropriate state class based on fields. RavenDB is very different from NHibernate and mapping will be quite a bit easier with it, but it is a completely different database system.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With