State pattern in entities

288 views
Skip to first unread message

Maciej Hadam

unread,
Aug 31, 2011, 4:34:11 PM8/31/11
to ddd-cqrs-sample
Hi ALL,

I've been using in my projects pattern for controled state transition
while executing activities on them.

The current version of this pattern is based on enum type with
activities that changes the enityty state.

I've changed the code of BaseEnityty to show the implementation.

Changes in BaseEntity.java
1. Redeclaration of status enumin BaseEnityty.java

public static enum EntityStatus implements BaseEntityActivity{


ACTIVE(new BaseEntityActiveStatusActivity()), ARCHIVE(new
BaseEntityFinalStatusActivity());

private BaseEntityActivity activity;

EntityStatus(BaseEntityActivity activity) {
this.activity = activity;
}

@Override
public BaseEntity.EntityStatus markAsRemoved() {
return activity.markAsRemoved();
}
}

2. Activity interface
public interface BaseEntityActivity {

public BaseEntity.EntityStatus markAsRemoved();

}

3. Activity implementation for final status activities
public class BaseEntityFinalStatusActivity implements
BaseEntityActivity {

public BaseEntity.EntityStatus markAsRemoved() {
throw new StatusChangeForbiddenException("Invalid status
transition");
}

}

4. Activity implementation for ACTIVE status
public class BaseEntityActiveStatusActivity extends
BaseEntityFinalStatusActivity {
@Override
public BaseEntity.EntityStatus markAsRemoved() {
return BaseEntity.EntityStatus.ARCHIVE;
}
}


5. Usage example
public void markAsRemoved() {
entityStatus = entityStatus.markAsRemoved();
//before was: entityStatus = EntityStatus.ARCHIVE;
}


The addin for the present implementation is that we prevent the
entity status from unforeseen transitions.

Based on this link:
http://www.javacodegeeks.com/2011/02/state-pattern-domain-driven-design.html



Sławek Sobótka

unread,
Aug 31, 2011, 5:23:15 PM8/31/11
to ddd-cqrs-sample
State is a powerful technique for dealing with certain class of
problems.
I have personally used it in cases where literally saved our ass -
especially wile implementing "graphical design tools".

So we may want to use State when:
- object can be in many states (in business systems state may be
associated with some domain statuses)
- object can perform may operations
- way of performing operations depends on the current state
all above can (and in most cases probably should) be implemented using
switch - yes, stupid switch. That's the easiest way.

...unless we expect following positive forces to emerge:
- we expect introducing new states in future - so we open our design
for expansion
- we do not expect introducing many new operations - because
maintaining state can be painful:/


So regarding proposed changes:
- in this particular case we are talking about "technical" entity
state associated with persistence
- there is no behavior, just trivial setting of value (separating
behavior to different classes in order to increase testability would
be a positive force favoring this approach)
- there won't be many more states. even if we add new it will happen
once a few years
- behavior is static - no need to abstraction via polymorphism


In general I would simplify impl so that ENUM performs logic with no
delegation to the other classes. But enum that implements interface is
a good decision that makes all design more supple.


But I must admit that we have planned for future introducing sample
code illustrating State in domain model. But not in this case - which
I described above.
Sample should be based on "positive forces" that favor State pattern -
described above.
So for example:
- we have a DeliveryPackage aggregate
- aggregate has some business responsibility (which is rather stable,
we do not expect many new methods)
- DeliveryPackage can be in many States - and for example we expect
that the set of possible states varies, depending on deployment (our
product/system is deployed at many clients, where each client has
different policies about cargo statuses/states; we want to maintain
common code base)

In my opinion in this case using State Pattern is justified. Or we can
think about rules engine:)

btw: I can suggest considering little changed design. In general State
is somehow "invasive". I mean it would "pollute" Aggregate. You can
consider designing what I call a cocoon. So You have Aggregate with
basic business responsibilities. You create a cocoon that wraps
Aggregate and implements all State Machine mechanic. This Mechanics
delegates to concrete States, concrete States delegates to aggregate.

So every time You want to work with Aggregate You do sth like this:

Aggregate a = repo.load(id);
AggregateStateMachine asm = new AggregateStateMachine(a); //at this
time machine sets current state by checking some statuses of the
aggregate (statuses must be accessible)
asm.doStrh();//delegates to current state, stat to aggregate,
eventually changes state
repo.persist(a)

This is just a suggestion for a possible solution for decoupling.


Sławek Sobótka
http://art-of-software.blogspot.com
http://www.bottega.com.pl/

Marcin Derylo

unread,
Sep 6, 2011, 3:29:49 PM9/6/11
to ddd-cqr...@googlegroups.com
I'm not really sure how implementation of an aggregate based State pattern "pollutes" it? If the part of the domain being modeled by the aggregate has some notion of different states it can be it, I think this pattern is the correct & clear way of expressing this concept in the model. It's like with using Composite pattern in your model - if something in your problem domain is composed of other entities, you model it as a Composite. 

Of course, I wouldn't use State pattern in the domain model only as a technical solution for some problem (avoiding if/switch statements?). That's like the explanation Evans gives why he wouldn't use Flyweight pattern in his domain.

Can you come out with a concrete example?

As for extracting the state machine from the Aggregate: I don't really like the idea of exposing aggregate's state for that state machine thing to see. As far as I understand, State pattern is about changing the behavior of an object based on it's _internal_ state. Besides, if you do that, don't you have to expose more behavior too? I mean things that would be private for the aggregate would become public now (not only private as private methods of the aggregate root class but also things that could be implemented as methods on internal parts of the aggregate).

Marcin Derylo

unread,
Sep 6, 2011, 3:43:11 PM9/6/11
to ddd-cqr...@googlegroups.com
On a second thought - by forcing client code to load your aggregate & wrap it into state machine thing, you actually provide two ways of using that aggregate - preferred: by using the state machine, unofficial - by invoking aggregate methods directly. In the latter case, client code is responsible for querying the state of the aggregate and knowing which method to call etc. 

I would rather NOT give developers such choice -the less choice they have, the lower the chance they will mess things up ;)

Of course, that could be solved by making the repository return the state machine thing, but that would mean that the AggregateStateMachine IS the aggregate root, so we're back at the beginning of the problem.

And I would surely consider as wrong a model in which some of the functionalities (business methods) require the state machine wrapper and some don't. Would rather try to model it as separate things to avoid such confusion.

Sławomir Sobótka

unread,
Sep 6, 2011, 4:41:47 PM9/6/11
to ddd-cqr...@googlegroups.com
Marcin - I agree with all in general.

But it can be discussed in specific context.
I just gave an example when team (OO freshmen) could not accept state
"mechanics" inside business, therefore we split it. So mentally
wrapper and aggregate were one thing (just like command and handler
are actually Command Design Pattern). But people felt better when code
was splited in 2 files - with all consequences including loosing of
encapsulation.

I think we can skip this topic and treat is just like a curiosity:)

Marcin Derylo

unread,
Sep 6, 2011, 4:46:26 PM9/6/11
to ddd-cqr...@googlegroups.com
W dniu wtorek, 6 września 2011, 22:41:47 UTC+2 użytkownik Sławek Sobótka napisał:

I think we can skip this topic and treat is just like a curiosity:)


Sure we can :) I'm looking forward to seeing your example of implementing part of domain model using State pattern. Never got a context to use it in domain, always in user interfaces (I think I've picked this technique from you). 

Sławomir Sobótka

unread,
Sep 6, 2011, 5:14:14 PM9/6/11
to ddd-cqr...@googlegroups.com
I have sketched sample domain scenario based on state machine. In free
time (maybe on weekend) I'll implement it.

btw: state machines are powerful tools to deal with complex problems,
we just don't know them or we have bad experience from school:
http://www.skorks.com/2011/09/why-developers-never-use-state-machines/

They also help to "make explicit what is implicit" - i love this
principle by Eric Evans.


According to using them in some class of GUI problems: what really
taught me that state machine is a "must have" is understanding how
simple graphical tools works, like MS Paint or Gimp.
So we have a canvas.
When pressing toll (brush, rubber, etc) on the tool box, we switch
state on the canvas.
When clicking/moving/dragging mouse on canvas, canvas delegates job to
the current state.
Canvas pass itself as a parameter to the state "doJob" method; canvas
provides some simple api like putting pixel of given color at x,y

We can go even further...
Canvas can accept Commands sent by current state.
Each command can have method called getAntiCommand, so when running a
command we put anti-commant on the stack.
ctrl+z uses anticommands from the stack.

Now it's simple... isn't it?
Jut to switch context form business models to something more funny:)

Reply all
Reply to author
Forward
0 new messages