In my DDD project I'm trying to implement the state pattern with java enum.
I have a problem when validating entity methods that have behaviour depending on the state.
For validating I use the notification pattern.
I follow the "always valid entity" approach, so that in every operation I first call a "isValidForOperation" validation method.
Here's the code, just the relevant for simplicity:
The entity:
public class Task extends AggregateRoot<TaskId> {
...
private State state;
...
// Operation with behaviour depending on the state
// It's a transition from "ASSIGNED" state to "IN_PROGRESS" state
// I apply the state pattern here
public void start () {
State next = this.state.start ( this );
this.setState ( next );
}
...
}
The java enum modeling the state:
public enum State {
ASSIGNED {
public State start ( Task task ) {
// Validation method to ensure the operation can be done
assertTaskIsValidForStart ( task );
// Business logic
...
// Return the next state
return ( State.IN_PROGRESS );
}
}
...
// more enum values for other states
...
// Default implementation of "start" operation
// It will be executed when the current state is not "ASSIGNED"
// So an error would be generated
public State start ( Task task ) {
// I can't apply notification pattern here !!!
// I would have to throw an exception
}
}
The validation method follows the notification pattern.
It collects all possible errors in a notification object.
This notification object is passed to an exception.
The exception is thrown and then the application layer catches it and return all the error messages to the client.
public void assertTaskIsValidForStart ( Task task ) {
Notification notification = new Notification();
if ( errorCondition (task) ) {
notification.addError(...);
}
...
// more errors
...
if ( notification.hasErrors() ) {
throw new TaskNotValidForStartException ( notification.errors() );
}
}
How could be the notification pattern applied (in conjuntion with the state pattern) when the error condition is about the invalid transitions between states?
Any ideas?
UPDATE:
I found a solution. I put the whole operation that depends on the state in the entity, and apply the state pattern more fine-grained, just to the code needed. This way I apply the pattern to calculate just the next state, so that I can check if the transition is allowed and apply the notification pattern too.
Code:
public class Task extends AggregateRoot<TaskId> {
...
private State state;
...
// Operation with behaviour depending on the state
// It's a transition from "ASSIGNED" state to "IN_PROGRESS" state
// I apply fine-grained state pattern here
public void start () {
// Validation method to ensure the operation can be done
// One of the validations will be if the transition is allowed
assertTaskIsValidForStart ( this );
// Business logic
// If it depends on the state, I would apply state pattern delegating to another method
...
// Set the next state
State next = this.nextStateForStart();
this.setState ( next );
}
...
public State currentState() {
return this.state;
}
...
public State nextStateForStart() {
return this.currentState().nextStateForStart();
}
...
}
public enum State {
ASSIGNED {
public State nextStateForstart() {
return ( State.IN_PROGRESS );
}
}
...
// more enum values for other states
...
// Default implementation of "start" transition
// It will be executed when the current state is not "ASSIGNED"
public State nextStateForstart() {
return null;
}
}
public void assertTaskIsValidForStart ( Task task ) {
Notification notification = new Notification();
// Validate the transition is allowed
if ( task.nextStateForStart() == null ) {
notification.addError(...);
}
...
// more errors
...
if ( notification.hasErrors() ) {
throw new TaskNotValidForStartException ( notification.errors() );
}
}
I think your enum does too much.
Besides having a fixed set of states which hardly can be extended, you make it hard to introduce any form of contract for each concrete state, which would also solve your notification problem.
Introduce an abstract state class which is the base class for all concrete states. A context is passed which allows setting a successor state for each state. This context can be implemented by your aggregate root.
Your notification can be managed by each state in a way you enforce using the AbstracftState, e.g. by forcing the state execution to return a notification object:
interface StateContext {
setState(AbstractState state);
}
class AbstractState {
abstract Notification execute(StateContext context);
}
class Task extends AggregateRoot implements StateContext {
AbstractState currentState;
....
public void start() {
Notification n = currentState.execute(this);
if (n.hasErrors()) {
throw new Exception(n.toErrorReport());
}
}
}
Now you can collect errors of each state before or after execution (you may want to introduce a validateStart() within each AbstractState which is called before execution) and report the collected errors to the caller.
I would model the TaskWorkflow as a VO inside the Task aggregate.
class Task {
private Workflow workflow;
public void start() {
workflow = workflow.followWith(Action.START, this);
}
public State currentState() {
return workflow.state();
}
public List availableActions() {
return workflow.nextActions();
}
}
The workflow is a FSM being composed of transitions between states joined by actions. Any call to a workflow method creates a new workflow representation pointing to the new state. Transitions can be modeled as direct or more complex custom involving business logic like you say.
If you use a functional language you can return a Monad to treat errors but in this case you can reify and create one or you can just throw an exception representing aggregated messages.
Hope it helps.
Related
I read about state and strategy design patterns in refactoring.guru web site in pages State and Strategy. The author says
This structure may look similar to the Strategy pattern, but there’s one key difference. In the State pattern, the particular states may be aware of each other and initiate transitions from one state to another, whereas strategies almost never know about each other.
The author also says, the ConcereteState classes, store a variable context which is an object to Context class and by this variable, states may aware of each other.
There are two things I can't understand:
How a state is aware of its predecessor?
Where should I implement the logic of transition between states? For example state1 by input a moves to state2 and by b moves to state4, where exactly this logic must be implemented?
This is a simple implementation of strategy I implemented in php language
<?php
class Algorithms{
public $algorithm;
function __construct(AlgorithmsInterface $algorithm){
$this->algorithm = $algorithm;
}
public function run(){
$this->algorithm->run();
}
}
interface AlgorithmsInterface{
public function run();
}
class Algorithm1 implements AlgorithmsInterface{
public function run(){
print "Algorithm1";
}
}
class Algorithm2 implements AlgorithmsInterface{
public function run(){
print "Algorithm2";
}
}
$payment = new Algorithms(new Algorithm2());
$payment->run();
and this is a simple implementation of State design pattern I implemented
<?php
interface State{
public function execute();
}
class Context{
public $state;
public function __construct(State $initialState){
$this->state = $initialState;
}
public function changeState(State $state){
$this->state = $state;
}
public function execute(){
$this->state->execute();
}
}
class State1 implements State{
public function execute(){
print "This is State1";
}
}
class State2 implements State{
public function execute(){
print "This is State2";
}
}
$initialState = new State1();
$state2 = new State2();
$context = new Context($initialState);
$context->execute();
$context->changeState($state2);
$context->execute();
?>
I can't see much difference between state and strategy while I know exactly what the intents of these strategies are. Besides that, the logic of movement between states and the way a state should be aware of its parent are missed from the code.
From your examples the two patterns look very similar. But your example of State design pattern is not really state design pattern, because you are setting the state from outside.
Typical state design pattern changes state internally and very often delegates the change to the state itself.
Let's look at simple toggle button. It has a state, and method to press it, and method to describe current state (toString()):
class ToggleButton {
enum State {
ON {
public State press() {
return OFF;
}
},
OFF {
public State press() {
return ON;
}
};
abstract public State press();
}
State state = State.OFF;
public void press() {
state = state.press();
}
public String toString() {
return "Device is " + state;
}
}
So from outside you're not setting the state, so you don't know in which state it is and how it will react. You use:
button.press();
System.out.println(button);
So the key difference is, that for strategy, you pass the strategy from outside, and let your object perform some operation (which doesn't change the strategy), so it's sticky delegation.
But purpose of State design pattern is, that the state is supposed to change, very often intrrnally, and with change of the state also the behavior changes. So even if we set some state before computation of some task, it may change (typically does) internally during the task to complete it.
It's a way to achieve state polymorphism. Also notice, that it's often related to state automata.
We have a bot that will be collecting information and we would like to utilize FormFlow. Using the custom prompter we can customize the outgoing messages, but is there any similar facility to let us intercept incoming messages before they hit the recognizers? The specific use case is based on the user input, we may want to immediately exist out of a flow and redirect to a different dialog.
You can use business logic to process user input when using FormFlow, where you can immediately exit out of a form flow and redirect to a different dialog.
Since the validate function cannot pass context, you can store the context in a form variable that is populated when constructed.
public MyFormClass(IDialogContext context)
{
Context = context;
}
public IDialogContext Context { get; set; }
public int IntegerField { get; set; }
Later, call the validate function for a specific field. Here, you can use the stored context to start a new dialog.
return new FormBuilder<MyFormClass>()
.Field(nameof(IntegerField),
validate: async (state, value) =>
{
var result = new ValidateResult { IsValid = true };
if (state.IntegerField > 10)
{
await state.Context.Call(new Dialog(), Dialog.ResumeMethod);
return result;
}
else
{
return result;
}
}
)
.Build();
Note:
Even though the first return statement will never be reached, it is required to avoid throwing an error.
You may need to implement additional steps to properly manage the bot's dialog stack.
Even though the first return statement will never be reached, it is required
I have an MVC application in which I have to update the view with the current value of a stream.
In the model I have this method:
public Observable<Integer> getStreamInstance(){
if(stream == null){
this.stream = Observable.create((Subscriber<? super Integer> subscriber) -> {
new HeartbeatStream(frequence,subscriber).start();
});
}
return stream;
}
which I use in the controller to get the stream. Then, in the controller I have these two methods:
public void start(){
this.sb = stream.subscribe((Integer v) -> {
view.updateCurrValue(v);
});
}
public void stop(){
this.sb.unsubscribe();
}
With the start method I simply update a label in the view with the current value.
This works fine until I try to stop the updating with the unsubscribing; infact, when I press the button "stop" in the view, the label keeps updating with the current value and, if I press "start" again, the label shows the values from two different streams, the one that I first created with the first "start" and the second that seems has been created with the second pressing of "start".
Where am I wrong?
EDIT:
public class HeartbeatStream extends Thread{
private Subscriber<? super Integer> subscriber;
private int frequence;
private HeartbeatSensor sensor;
public HeartbeatStream(int freq, Subscriber<? super Integer> subscriber){
this.frequence = freq;
this.subscriber = subscriber;
sensor = new HeartbeatSensor();
}
public void run(){
while(true){
try {
subscriber.onNext(sensor.getCurrentValue());
Thread.sleep(frequence);
} catch (Exception e) {
subscriber.onError(e);
}
}
}
This is the HeartbeatStream class. HeartbeatSensor is a class that periodically generates a value that simulates the heartbeat frequence.
I'm guessing you tried to periodically signal some event that triggers the screen update. There is an operator for that:
Observable<Long> timer = Observable.interval(period, TimeUnit.MILLISECONDS,
AndroidSchedulers.mainThread());
SerialSubscription serial = new SerialSubscription();
public void start() {
serial.set(timer.subscribe(v -> view.updateCurrValue(v)));
}
public void stop() {
serial.set(Subscriptions.unsubscribed());
}
public void onDestroy() {
serial.unsubscribe();
}
Observable by design unsubscribe your observer once that all items are emitted and onComplete callback is invoked.
Look this example https://github.com/politrons/reactive/blob/master/src/test/java/rx/observables/creating/ObservableSubscription.java
I guess you're not handling the unsubscribe - although I can't see what's going on in your HeartbeatStream class.
If you're creating an Observable with Observable.create then you need to handle unsubscribing explicitly with subscriber.isUnsubscribed().
Where possible use some of the utility methods to create an Observable - they handle this all for you eg Observable.just() or Observable.from().
If this doesn't help, please post your HeartbeatStream class.
See the the docs for more details:
https://github.com/ReactiveX/RxJava/wiki/Creating-Observables
https://github.com/ReactiveX/RxJava/wiki/Async-Operators
While questions of this sort have been frequently asked, I think I have a more specific constraint that makes the problem a little more interesting. I am writing a client-side application in Dart using an MVC pattern. My goal is simple: listen for clicks on a button, trigger an async request to a back-end API, and present that data to the user.
Minimally, I have one each of a model, view, and controller class. The model class implements methods to make requests and bundle up the data it receives. The view class has the DOM subtree of interest as a field and implements methods to manipulate the elements therein. The controller has a single instance each of the model and view classes as its fields and registers event handlers on the elements of the view. The controller's event handlers fire off calls to the model to make requests and return data, which will then be passed to the view for rendering.
The issue arises when I attempt to capture the incoming data from the async request into an instance variable of the model. I'd like to keep everything nicely encapsulated (that's why I'm using Dart in the first place), and I'd like to avoid using a global variable to hold the data that comes from the async request. A minimal example of my current layout looks something like below. I've made all of the fields and methods public here for clarity's sake.
// view.dart
class FooView {
// The root element of the view with which we're concerned.
static final Element root = querySelector('#thisView');
FooView() { init(); }
void init() { root.hidden = false; }
// Appends the new data into an unordered list.
void update(List<Map<String,String>> list) {
UListElement container = root.querySelector('ul#dataContainer');
container
..hidden = true
..children.clear();
for ( Map<String,String> item in list ) {
container.append(new LIElement()
..id = item['id']
..text = item['text']
);
container.hidden = false;
}
// model.dart
class FooModel {
// Instance variable to hold processed data from the async request.
List<Map<String,String>> dataList;
// Makes async request, returning data to caller.
List<Map<String,String>> getData() {
HttpRequest
.getString('example.com/api/endpoint')
.then( (String data) {
dataList = JSON.decode(data);
});
return dataList;
}
}
// controller.dart
class FooController {
FooModel model;
FooView view;
FooController() {
model = new FooModel;
view = new FooView;
}
void registerHandlers() {
// When this button is clicked, the view is updated with data from the model.
ButtonElement myButton = view.root.querySelector('#myButton');
myButton.onClick.listen( (Event e) {
view.update(model.getData());
});
}
}
The errors I'm seeing involve the model.dataList field coming up null at the end of all of this. My first blush is that I do not understand scoping of callback functions. The way I first understood it, the callback would handle the request's data when it arrived and just set the instance variable when it was ready. Perhaps the instance variable is aliased and modified within the scope of the callback, but the variable I want to return is never touched.
I have thought about passing a Future object to a method of the view, which will then just do the processing itself and add the elements to the DOM as a side effect. That technique would break my MVC design (even more than it's broken now in this minimal working example).
It is also very possible that I am using asynchronous programming completely incorrectly. Thinking more on this, my async call is useless because I basically make a blocking call to view.update() in the controller when the event fires. Maybe I should pass a request Future to the controller, and fire the request's then() method from there when the event handler is triggered.
In Dart, in what scope do callback functions reside, and how can I get data out of them with minimal side effects and maximal encapsulation?
N.B. I hate to belabor this oft-discussed question, but I have read previous answers to similar questions to no avail.
The getData method initiates the asynchronous HTTP request then immediately returns before having received/parsed the response. That is why model.datalist is null.
To make this work with minimal effort, you can make getData synchronous:
(note: I changed the dataList type, just to make it work with the sample JSON service http://ip.jsontest.com/)
// model.dart
class FooModel {
// Instance variable to hold processed data from the async request.
Map<String, String> dataList;
// Makes async request, returning data to caller.
Map<String, String> getData() {
var request = new HttpRequest()
..open('GET', 'http://ip.jsontest.com/', async: false)
..send();
dataList = JSON.decode(request.responseText);
return dataList;
}
}
Though this may violate your objective, I agree with your concerns re: blocking call and would personally consider keeping the HTTP request asynchronous and making getData return a new future that references your model class or parsed data. Something like:
// model.dart
class FooModel {
// Instance variable to hold processed data from the async request.
Map<String,String> dataList;
// Makes async request, returning data to caller.
Future<Map<String, String>> getData() {
return HttpRequest
.getString('http://ip.jsontest.com/')
.then( (String data) {
dataList = JSON.decode(data);
return dataList;
});
}
}
and in the controller:
void registerHandlers() {
// When this button is clicked, the view is updated with data from the model.
ButtonElement myButton = FooView.root.querySelector('#myButton');
myButton.onClick.listen( (Event e) {
model.getData().then((Map<String, String> dataList) {
view.update(dataList);
});
});
}
You return datalist in getData before the HttpRequest has returned.
// Makes async request, returning data to caller.
List<Map<String,String>> getData() {
return HttpRequest // <== modified
.getString('example.com/api/endpoint')
.then( (String data) {
return JSON.decode(data); // <== modified
});
// return dataList; // <== modified
void registerHandlers() {
// When this button is clicked, the view is updated with data from the model.
ButtonElement myButton = view.root.querySelector('#myButton');
myButton.onClick.listen( (Event e) {
model.getData().then((data) => view.update(data)); // <== modified
});
}
You can use Stream to make your design loosely coupled and asynchronous:
class ModelChange {...}
class ViewChange {...}
abstract class Bindable<EventType> {
Stream<EventType> get updateNotification;
Stream<EventType> controllerEvents;
}
class Model implements Bindable<ModelChange> {
Stream<ModelChange> controllerEvents;
Stream<ModelChange> get updateNotification => ...
}
class View implements Bindable<ViewChange> {
Stream<ViewChange> controllerEvents;
Stream<ViewChange> get updateNotification => ...
}
class Controller {
final StreamController<ViewChange> viewChange = new StreamController();
final StreamController<ModelChange> modelChange = new StreamController();
Controller.bind(Bindable model, Bindable view) {
view.controllerEvents = viewChange.stream;
model.controllerEvents = modelChange.stream;
view.updateNotification.forEach((ViewChange vs) {
modelChange.add(onViewChange(vs));
});
model.updateNotification.forEach((ModelChange mc) {
viewChange.add(onModelChange(mc));
});
}
ModelChange onViewChange(ViewChange vc) => ...
ViewChange onModelChange(ModelChange mc) => ...
}
I want to re-write a method that has way too many nested if statements.
I came up with this approach and wanted your opinions:
public void MyMethod()
{
bool hasFailed = false;
try
{
GetNewOrders(out hasFailed);
if(!hasFailed)
CheckInventory(out hasFailed);
if(!hasFailed)
PreOrder(out hasFailed);
// etc
}
catch(Exception ex)
{
}
finally
{
if(hasFailed)
{
// do something
}
}
}
I've done stuff similar to that, but without the exception handling:
BOOL ok = CallSomeFunction();
if( ok ) ok = CallSomeOtherFunction();
if( ok ) ok = CallYetAnotherFunction();
if( ok ) ok = WowThatsALotOfFunctions();
if( !ok ) {
// handle failure
}
Or if you want to be clever:
BOOL ok = CallSomeFunction();
ok &= CallSomeOtherFunction();
ok &= CallYetAnotherFunction();
...
If you are using exceptions anyway, why do you need the hasFailed variable?
Not really. Your methods should raise an exception in case of an error to be caught by your "catch" block.
As far as I can see this is an example of cascade steps where second and third one will be executed if first and first and second are valid, i.e. return hasFailed==false.
This code can be made much more elegant using Template Method and Decorator design pattern.
You need one interface, concrete implementation, abstract class and several subclasses of the abstract class.
public interface Validator {
public boolean isValid();
}
public class GetNewOrders implements Validator {
public boolean isValid() {
// same code as your GetNewOrders method
}
}
public abstract class AbstractValidator implements Validator {
private final Validator validator;
public AbstractValidator(Validator validator) {
this.validator = validator;
}
protected boolean predicate();
protected boolean isInvalid();
public final boolean isValid() {
if (!this.validator.isValid() && predicate() && isInvalid())
return false;
return true;
}
}
public class CheckInventory extends AbstractValidator {
public CheckInventory(Validator validator) {
super(validator);
}
#Override
public boolean predicate() {
return true;
}
#Override
public boolean isInvalid() {
// same code as your CheckInventory method
}
}
public class PreOrder extends AbstractValidator {
public CheckInventory(Validator validator) {
super(validator);
}
#Override
public boolean predicate() {
return true;
}
#Override
public boolean isInvalid() {
// same code as your PreOrder method
}
}
Now your method can look much more elegant:
public void MyMethod() {
bool success = false;
try {
Validator validator = new GetNewOrders();
validator = new CheckInventory(validator);
validator = new PreOrder(validator);
success = validator.isValid();
} finally {
if (!success) {
// do something
}
}
}
Validator object can be created in one line, but I prefer this style since it makes obvious the order of validation. Creating new validation link in the chain is matter of subclassing AbstractValidator class and implementation of predicate and isInvalid methods.
Without commenting on the try/catch stuff since I really don't know what is going on there, I would change it so the called methods return true/false for success and then just check them depending on the boolean short-circuiting to avoid calling later methods if the preceding method failed.
public void MyMethod()
{
bool success = false;
try
{
success = GetNewOrders()
&& CheckInventory()
&& PreOrder();
// etc
}
catch(Exception ex) { }
finally
{
if(!success)
{
}
}
}
This doesn't really look good to me. The use of the hasFailed variable is really not nice. if GetNewOrders fails with an exception, you for instance end up inside the catch block with hasFailed = false !
Opposed to other answers here I believe there MAY be legitimate uses for boolean "hasFailed" that are not exceptional. But I really don't think you should mix such a condition into your exception handler.
I know I'll probably duplicate a few posts: What's wrong with else? You could also use lazy evaluation (a() && b()) to link methods - but that relies on status being given as return value, which is more readable anyhow IMHO.
I don't agree with posters that you should raise an exception, because exceptions should be raised if program faults occur or the program enters an exceptional state because of operations. Exceptions are not business logic.
I would do it like this:
public void MyMethod()
{
bool success = false;
try
{
GetNewOrders(); // throw GetNewOrdersFailedException
CheckInventory(); // throw CheckInventoryFailedException
PreOrder(); // throw PreOrderFailedException
success = true;
}
catch( GetNewOrdersFailedException e)
{
// Fix it or rollback
}
catch( CheckInventoryFailedException e)
{
// Fix it or rollback
}
catch( PreOrderFailedException e)
{
// Fix it or rollback
}
finally
{
//release resources;
}
}
Extending an exception is rather trivial,
public NewExecption : BaseExceptionType {}
Well, I don't like code that appears to get a list of orders and then process them, and then stop processing them when an error occurs, when surely it should skip that order and move to the next? The only thing to completely fail on is when the database (source of orders, destination of preorders) dies. I think that the entire logic is a bit funky really, but maybe that's because I don't have experience in the language you are using.
try {
// Get all of the orders here
// Either in bulk, or just a list of the new order ids that you'll call the DB
// each time for, i'll use the former for clarity.
List<Order> orders = getNewOrders();
// If no new orders, we will cry a little and look for a new job
if (orders != null && orders.size() > 0) {
for (Order o : orders) {
try {
for (OrderItem i : o.getOrderItems()) {
if (checkInventory(i)) {
// Reserve that item for this order
preOrder(o, i);
} else {
// Out of stock, call the magic out of stock function
failOrderItem(o, i);
}
}
} catch (OrderProcessingException ope) {
// log error and flag this order as requiring attention and
// other things relating to order processing errors that aren't database related
}
}
} else {
shedTears();
}
} catch (SQLException e) {
// Database Error, log and flag to developers for investigation
}
Your new approach is not that bad for a simple set of instructions, but what happens when additional steps are added? Do you / would you ever require transactional behavior? (What if PreOrder fails? or If the next step after PreOrder fails?)
Looking forward, I would use the command pattern:
http://en.wikipedia.org/wiki/Command_pattern
...and encapsulate each action as a concrete command implementing Execute() and Undo().
Then it's just a matter of creating a queue of commands and looping until failure or an empty queue. If any step fails, then simply stop and execute Undo() in order on the previous commands. Easy.
Chris solution is the most correct. But I think you should not do more than you need. Solution should be extandable and that's enough.
Change value of a parameter is a bad practice.
Never use empty generic catch statement, at least add a comment why you do so.
Make the methods throw exception and handle them where it is appropriate to do so.
So now it is much more elegant :)
public void MyMethod()
{
try
{
GetNewOrders();
CheckInventory();
PreOrder();
// etc
}
finally
{
// do something
}
}