Pattern for sequence of steps with no common interface - java

In my java app I got a method that runs a long sequence of steps (synchronously) where one step result is the input for the next.
for example:
// Step 1
Map<String, SomeObject> objectsMap = someService.createObjectsMap();
if (!objectsMap.isEmpty()) {
// Step 2
AnotherObject anotherObject = anotherService.createAnotherObject(objectsMap);
if (null != anotherObject) {
// Step 3 that gets anotherObject as input and returns something else
} else { // Step 2 failed
// log and handle
}
} else { // Step 1 failed
// log and handle
}
And so I got this series of steps written in a series of if-else blocks.
There is no common interface for the steps since each one has different signature. I've been loking on some different and tried to customize patterns such as chain-of-responsibility and command but could not get to a satisfied result.
I wonder if this ugly long if-else section is the way to go or is there a pattern out there that can help make this series of steps more clean and scalable.

One question you must answer yourself is Why do I want to refactor my code?
Do you want it to be
more clean code?
more modularized?
Must the steps be configurable (replaceable) at runtime?
Refactor in order to make the code clean
If the steps do not need to be configured at runtime and you want to make your code more clean than you should take a look at the comments you made. Each comment is a hint.
Break the code block into methods and name them after the steps
/**
* Explain what step1 does.
*/
private void step1() {
// Step 1
Map<String, SomeObject> objectsMap = someService.createObjectsMap();
if (!objectsMap.isEmpty()) {
step2(objectsMap);
} else { // Step 1 failed
// log and handle
}
}
/**
* Explain what step2 does.
*/
private void step2(Map<String, SomeObject> objectsMap) {
// Step 2
final AnotherObject anotherObject = anotherService
.createAnotherObject(objectsMap);
if (null != anotherObject) {
step3(anotherObject);
} else { // Step 2 failed
// log and handle
}
}
/**
* Explain what step3 does.
*/
private void step3(AnotherObject anotherObject) {
// Step 3 that gets anotherObject as input and returns something
// else
}
This approach just breaks the method down to smaller methods. The advantage is that each smaller method is only responsible for one thing. And because it is a method you can add javadoc to it. So there is no need for inline comments anymore. Eventually you can give the method better names and omit the javadoc at all.
Refactor in order to make the steps replaceable at runtime
If you want to configure the steps that are executed at runtime (e.g. because of some user input) than you must encapsulate them in objects, because your application has references to objects that can be replaced.
Since you want all steps to have a common api you must make it more general.
Start thinking from the clients perspective. How should the steps be executed. E.g.
for (Step step : steps) {
boolean executeNext = step.execute();
if (!executeNext) {
break;
}
}
Design a Step interface
public interface Step {
boolean execute();
}
How to pass the output of one step as the input to another?
Make an interface
public static interface StepInput<T> {
public T getInput();
}
Implement your Steps. An abstract class will help you.
public abstract class InputOutputStep<T> implements Step,
StepInput<T> {
private T returnValue;
protected void setReturnValue(T returnValue) {
this.returnValue = returnValue;
}
public T getInput() {
return returnValue;
}
}
public class Step1 extends InputOutputStep<Map<String, SomeObject>> {
private StepInput<Map<String, SomeObject>> stepInput;
public Step1(StepInput<Map<String, SomeObject>> stepInput) {
this.stepInput = stepInput;
}
public boolean execute() {
boolean executeNext = false;
Map<String, SomeObject> objectsMap = stepInput.getInput();
if (!objectsMap.isEmpty()) {
// Step 2
setReturnValue(objectsMap);
executeNext = true;
} else { // Step 1 failed
// log and handle
}
return executeNext;
}
}
public class Step2 extends InputOutputStep<AnotherObject> {
private StepInput<Map<String, SomeObject>> stepInput;
private AnotherService anotherService;
public Step2(AnotherService anotherService,
StepInput<Map<String, SomeObject>> stepInput) {
this.anotherService = anotherService;
this.stepInput = stepInput;
}
public boolean execute() {
boolean executeNext = false;
Map<String, SomeObject> objectsMap = stepInput.getInput();
AnotherObject anotherObject = anotherService
.createAnotherObject(objectsMap);
if (null != anotherObject) {
setReturnValue(anotherObject);
executeNext = true;
} else { // Step 2 failed
// log and handle
}
return executeNext;
}
}
public class Step3 extends InputOutputStep<Void> {
private StepInput<AnotherObject> stepInput;
public Step3(StepInput<AnotherObject> stepInput) {
this.stepInput = stepInput;
}
public boolean execute() {
AnotherObject anotherObject = stepInput.getInput();
setReturnValue(null);
return false;
}
}
Configure the steps at runtime and execute
Step1 step1 = new Step1(stepInput);
Step2 step2 = new Step2(anotherService, step1);
Step step3 = new Step3(step2);
Step[] steps = new Step[]{step1, step2, step3};
for (Step step : steps) {
boolean executeNext = step.execute();
if (!executeNext) {
break;
}
}

This scenario -where you do lots of things and want to abort and log if any of them fails - is what exception handling is designed for. For example:
try {
// Step 1
Map<String, SomeObject> objectsMap = someService.createObjectsMap();
if (objectsMap.isEmpty())
throw new SomethingWentWrongException("Failed to get object map from service");
// Step 2
AnotherObject anotherObject = anotherService.createAnotherObject(objectsMap);
if(anotherObject == null)
throw new SomethingWentWrongException("Failed to create another object");
// Step 3 that gets anotherObject as input and returns something else
} catch(SomethingWentWrongException e) {
// log and handle
e.printStackTrace();
}
Ideally, someService.createObjectsMap and anotherService.createAnotherObject would throw their own exceptions instead of making you check the return value. Then you would only need to write:
try {
Map<String, SomeObject> objectsMap = someService.createObjectsMap();
AnotherObject anotherObject = anotherService.createAnotherObject(objectsMap);
// Step 3 that gets anotherObject as input and returns something else
} catch(Exception e) {
// log and handle
e.printStackTrace();
}
(although note that you should only catch Exception if you really want to catch all failures)

Options:
Memento Pattern:
With memento, you can store the state of the object. Like when you want to redo and undo things.
This way, when you have similar methods in step 1 and step 3, you can simply use 1 general method.
Then, with undo and redo, you know that you have to save your state.
Think of possibility to save your step number.
Strategy pattern:
With strategy pattern, you are saving the IF-ELSE statement.
You just have to go to one function, strategy object will determine the rest.
Think of a router as the strategy class.
The router will determine the best way, best route, or best process (from several process options).
Observer pattern:
This is something like MVC.
I always think that observer is a CCTV.
When something changes, something weird happened, the CCTV admin will know.
So you have a controller class, which monitors everything, and configures where you have to go next.
Thank you,

Related

If/else representation with stream and Java 8

I have the following interface with two implementations:
public interface Parser {
void parse();
boolean canParse(String message);
}
class StackParser implements Parser {
public void parse(){
System.out.println("Parsing stackoverflow");
}
public boolean canParse(String message){
return message.equals("stackoverflow");
}
}
class YoutubeParser implements Parser {
public void parse() {
System.out.println("Parsing youtube");
}
public boolean canParse(String message) {
return message.equals("youtube");
}
}
I go to check incoming message and parse "stackoverflow" or "youtube":
public class Main {
private List<Parser> parsers;
public static void main(String[] args) {
new Main().doSomething("youtube");
}
void doSomething(String message){
parsers.stream()
.filter(p -> p.canParse(message))
.forEach(p -> p.parse());
}
}
Okay, pretty good. But what if message is not "stackoverflow" or "youtube"? App will be silent, but I want to send another default message if no matches were found, like "I can't parse this web!".
I know that will not works (even compile), but it's also should print "I can't parse this web" only one time, not for every false condition.
parsers.stream()
.filter(p -> {
if (p.canParse(message) == false) {
System.out.println("I can't parse it!");
}
})
.forEach(p -> p.parse());
How can I do it?
This is a perfect example of when to use the Optional#orElse or the Optional#orElseThrow method(s). You want to check if some condition is met so you filter, trying to return a single result. If one does not exist, some other condition is true and should be returned.
try {
Parser parser = parsers.stream()
.filter(p -> p.canParse(message))
.findAny()
.orElseThrow(NoParserFoundException::new);
// parser found, never null
parser.parse();
} catch (NoParserFoundException exception) {
// cannot find parser, tell end-user
}
In case only one parser can parse the message at a time you could add a default parser:
class DefaultParser implements Parser {
public void parse() {
System.out.println("Could not parse");
}
public boolean canParse(String message) {
return true;
}
}
And then use it via
// make sure the `DefaultParser` is the last parser in the `parsers`
parsers.stream().filter(p -> p.canParse(message)).findFirst().get().parse();
or alternatively drop the DefaultParser and just do
Optional<Parser> parser = parsers.stream().filter(p -> p.canParse(message)).findFirst();
if (parser.isPresent()) {
parser.get().parse();
} else {
// handle it
}
You can use simply a forEach if-else inside
parsers.forEach(p -> {
if (!p.canParse(message)) {
System.out.println("I can't parse it!");
} else {
p.parse();
}
});
That's a pretty interesting question, which fortunately I had to face some time ago.
Mi approach consisted on declaring a list of Supplier<T> which would be iterated only if there's and exception thrown (the intention of this approach was to retrieve data from DB based on the parameters given, so I would be able to search by id or by an instance).
import java.util.function.Supplier;
public class AbstractFacadeUtil {
public <R> R tryOr(Supplier<R>...fns) {
R result = null;
boolean success = false;
int i = 0;
while (!success && i < fns.length) {
Supplier<R> fn = fns[i++];
try {
result = fn.get();
success = true;
} catch (Exception e) {
}
}
if (!success) {
throw new RuntimeException(new Exception(String.format("[%s] Couldn't find a successful method to apply\"", this.getClass())));
}
return result;
}
}
Some notes:
I'd used Supplier<T> because it's body didn't contain anything that would throw an undeclared exception which, otherwise, would be needed to use Callable<T> instead.
Yeah, could have given it a better name though.
Maybe an Iterator<T> would make that piece of code more understandable and clean.
In your specific case, I'd use Jason's approach by adding a Supplier<T> at the end of the list that would throw an NoParserFoundException
[EDIT]
Also, you should iterate the List<Supplier<T>> or List<Callable<T>> wheter the Parser can't parse and it throws an CantParseException.
So, as you see, exceptions can help a lot even I'm not sure this would be the most efficient or expert approach.
Hope it helps you.
[EDIT2]
This is an example of how I implemented the solution given above.
Ok, I'm gonna say it. Look at every solution posted - what do you think? Are they neat, clean code that you would expect from functional approach?
Nope, why? Because the design is wrong, it doesn't fit functional approach.
Fix the design:
get rid of void return type (brr)
don't overuse methods like canDoSomething (treat them like isPresent in Optional - it's there for extreme cases, mostly technical, not business code)
look into VAVR (or similar library) - classes like Try, Either etc.
Solution will come naturally then and in every case - not only this specific one you posted here.

Method overloading vs factory

Lets say we need some logic change in multiple methods of multiple classes on basis of a flag, while keeping backwards compatibility.
There are two ways..
1.overload every method in every class. then end up with an if-else ladder in caller code to call correct method.
2.Make a common interface and a Factory. Return objects of either on basis of flag passed to factory. Callers don't need any change. only a little change is needed while object creation. Is it logical to create factory for two types only ?
Based on your experience which will you choose ? How to decide between these two ways ? Any better approach you can suggest ?
Logic change suggests behavior which suggests the Strategy Pattern. This avoids a change to the existing method signature.
But you can still use a factory to centralize the creation of the concrete strategy object which handles the logic.
import java.util.Random;
public class App {
public static void main(String[] args) {
App app = new App();
app.calculateSomething(new Random().nextBoolean());
}
private void calculateSomething(boolean isUsingLegacyLogic) {
CalculationStrategyFactory factory = new CalculationStrategyFactory();
CalculationStrategy strategy = factory.getCalculationStrategy(isUsingLegacyLogic);
Calculator calculator = new Calculator(strategy);
calculator.calculate();
}
class Calculator {
CalculationStrategy calculationStrategy;
Calculator(CalculationStrategy calculationStrategy) {
this.calculationStrategy = calculationStrategy;
}
// ...
public double calculate() {
// original code
// ...
// System.out.println("Calculation steps were done in sequential order.");
// return 0;
return calculationStrategy.calculate(this);
}
}
private interface CalculationStrategy {
double calculate(Calculator c);
}
private class SequentialCalculationHandler implements CalculationStrategy {
public double calculate(Calculator c) {
// ...
System.out.println("Calculation steps were done in sequential order.");
return 0;
}
}
private class ParallelCalculationHandler implements CalculationStrategy {
public double calculate(Calculator c) {
// ...
System.out.println("Calculation steps were done in parralel.");
return 0;
}
}
private class CalculationStrategyFactory {
public CalculationStrategy getCalculationStrategy(boolean isUsingLegacyLogic) {
if (isUsingLegacyLogic || Runtime.getRuntime().availableProcessors() == 1) {
return new SequentialCalculationHandler();
}
return new ParallelCalculationHandler();
}
}
}

Class level design for validation engine with 2 independent entities

I have a use case where there will be 3 kind of data
Business_Enrollment_Program (lets denote them with BEP_1, BEP_2 ...)
Validation_Rule (lets denote them with R1, R2 ...)
Transaction_Type (lets denote them TT_1, TT_2 ...). This is an entity class having some attributes. On these entities Validation_Rule need to be executed.
Transaction_Type entities will look something like
public TT_1 {
private Business_Enrollment_Program;
private COMMON_FIELD_1;
private COMMON_FIELD_2;
private TT_1_SPECIFIC_FIELD;
}
public TT_2 {
private Business_Enrollment_Program;
private COMMON_FIELD_1;
private COMMON_FIELD_2;
private TT_2_SPECIFIC_FIELD;
}
Now i have 2 requirement while executing Validation rules:
Set of Validation_Rule that need to be executed depends on the Transaction_Type and it's Business_Enrollment_Program.
That means for TT_1 enrolled under BEP_1 we might need to execute (R1,R2) rules but for TT_1 enrolled under BEP_2 we might need to execute (R1,R3) rules.
Behavior of rule will depend on Transaction_Type and it's Business_Enrollment_Program. That means for TT_1 enrolled under BEP_1 behavior of rule R1 might be different compared to TT_1 enrolled under BEP_2
For rules i can create a structure like below:
public interface Rule <T> {
public boolean execute(T transactionType);
}
public class R1_For_TT_1 implements Rule<TT_1> {
public boolean execute(TT_1 transactionType) {
//Do something here
}
}
public class R1_For_TT_2 implements Rule<TT_2> {
public boolean execute(TT_2 transactionType) {
//Do something here
}
}
And i can execute the rules like below
public processTransaction(T transactioType) {
private boolean result = true;
if(t instanceof TT_1) {
result = result && R1_For_TT_1.execute(t);
}
else if (t instanceof TT_2) {
result = result && R1_For_TT_1.execute(t);
result = result && R2_For_TT_1.execute(t);
}
if(result) {
// Do something
}
else {
// Do something else
}
}
Issue with this approach is i am not meeting my 2nd requirement where i wanted behavior of rule to depend on Transaction_Type and it's Business_Enrollment_Program.
Any idea how can i arrange my classes and entities so that both of my requirements are fulfilled elegantly?
I would give every BusinessEnrollmentProgram a Map<TransactionType, List<Rule>> as a field, so that you can organize what Rule objects go with each TransactionType. It will make it easy to lookup which Rules need to be executed.
So it would look something like this:
BusinessEnrollmentProgram.java
public class BusinessEnrollmentProgram {
private Map<TransactionType, List<Rule>> transactions = new HashMap<>();
public void processTransaction(TransactionType t) {
List<Rule> rules = transactions.get(t);
boolean result = true;
for (Rule rule : rules) {
if (!rule.execute(t)) {
result = false;
break;
}
}
if (result) {
// do something
} else {
// do something else
}
}
}
TransactionType.java
public class TransactionType {
private COMMON_FIELD_1;
private COMMON_FIELD_2;
// override hashCode() & equals() here so it can be used as a HashMap key
}
Then make all of your transaction types extend TransactionType, and allow your Map to store all of the relationships for which Rule is aloud with which TransactionType. Each BusinessEnrollmentProgram should have a separate set of rules to draw from.
If you're finding that there are too many classes extending Rule, use anonymous classes or lambda expressions instead.

Which method should change the field, when calling a hierarcy of private methods?

When a class' public method needs to call a private method that results in a field being changed, which method should change the field? Is there any common convention for this? Is one approach preferable over the other?
Consider these two code snippets:
public class boolHolder {
private boolean theBool = false;
public void doYourThing() {
// Do a lot of other stuff
setBool();
}
private void setBool() {
// Do a lot of other stuff, justifying a private method for this
this.theBool = true;
}
}
VS
public class boolHolder {
private boolean theBool = false;
public void doYourThing() {
// Do a lot of other stuff
theBool = setBool();
}
private boolean setBool() {
// Do a lot of other stuff, justifying a private method for this
return true;
}
}
These two snipped of course being a very simple case, but I'm sure I'm not the only one ending up with public methods calling a huge tree of private methods. Should the field be set at the end of the branch, or should a value be passed back?
I think it makes more sense that only a single place would set the value of the field, and it should be the last method being called. It makes the code easier to understand. Your first snippet looks much more readable to me.
Here's another snippet which, in my opinion, supports this convention :
Lets say we have an int member with two setters - one accepts an int and the other accepts a String representation of that int (which is used, for example, if we de-serialize an instance from an XML String).
int value;
public void setIntField (String value)
throws SomeException
{
if (value == null)
throw new SomeException();
try {
int val = Integer.parseInt (value);
setIntField (val);
}
catch (NumberFormatException ex) {
throw new SomeException();
}
}
public void setIntField (int value)
throws SomeException ()
{
if (value < MIN_ALLOWED || value > MAX_ALLOWED)
throw new SomeException ();
this.value = value;
}
Apart from renaming theBool and setBool to something more understandable (which I'm going to assume you did eitherway in the real application), I'd go with the first one. Methods with the word set are expected to be setters and not many people will expect a return value.
It doesn't change much, but you can try to use a better naming for your methods: i don't like that you name your second method setBool().
If you write "Do a lot of other stuff, justifying a private method for this" you can try to associate a verb to that stuff you do.
Say you update an account status and upon completion want to signal with the boolean the status, well use something like what you did but call it in a meaningful way, e.g. updateAccount() and either return a true if the update went fine or set it inside:
public class boolHolder {
private boolean accountUpdated = false;
public void doYourThing() {
// Do a lot of preliminary stuff
updateAccount();
}
private void updateAccount() {
// try to update account
// if update went fine
this.accountUpdated = true;
}
}
or
public class boolHolder {
private boolean accountUpdated = false;
public void doYourThing() {
// Do a lot of preliminary stuff
this.accountUpdated = updateAccount();
}
private boolean updateAccount() {
// try to update account
// if error happens, rollback change and set
return false;
// else (update went fine)
return true;
}
}
are both perfectly fine, but make your method tell what they do, since updating the bool is not the main action since you "Do a lot of other stuff, justifying a private method for this".
The value setting inside is more compact if you use a default to false as you did, but the other is more explicit in what it does. So I tend to prefer that: returning a result for you operation.

In Java, need to make variables available to Control Break solution

Below is an attempt to create a reusable solution for the control break pattern. It is built on Command Pattern (Action and Test interfaces). However, I realized my old COBOL thinking got in the way, because this solution is predicated on each of the Action and Test objects having access to "global variables." And my immediate thought after that was "the need for variable access like this (wider scope) must be an already invented wheel.
How to give all the Actions and Tests below access to a group of variables -- an indeterminate group because this is supposed to be a reusable solution??
public class ControlBreak {
public static void controlBreak(Action initialize,
Test endOfInput,
Test onChange,
Action breakAction,
Action detailAction,
Action getNext) {
boolean hasProcessed = false;
getNext.execute();
for (initialize.execute();endOfInput.test();detailAction.execute(),getNext.execute()) {
hasProcessed = true;
if (onChange.test()) {
breakAction.execute();
}
detailAction.execute();
}
if (hasProcessed) {
breakAction.execute();
} else {
// throw empty input exception
}
}
}
On a few re-reads, it seems like you're trying to abstract a certain control flow, where the parameters can be coupled. In this case, I'd look into generics. I.e. something like this:
public static void <TParams> controlBreak(Action<TParams> initialize, ..., TParams params) {
// ...
initialize.execute(params)
// ...
}
That way this method will remain reusable, but the various actions / tests can still accept a strongly-typed set of parameters/variables. (The concrete type of TParam.)
Thanks to millimoose, I got where I was going. Here's the fleshed out code, for reference:
public class ControlBreak<TParams> {
public TParams controlBreak(Action<TParams> initialize,
Test<TParams> endOfInput,
Test<TParams> onChange,
Action<TParams> breakAction,
Action<TParams> detailAction,
Action<TParams> getNext,
TParams params) {
boolean hasProcessed = false;
getNext.execute(params);
for (params = initialize.execute(params);endOfInput.test(params);params = detailAction.execute(params),params = getNext.execute(params)) {
hasProcessed = true;
if (onChange.test(params)) {
breakAction.execute(params);
}
detailAction.execute(params);
}
if (hasProcessed) {
breakAction.execute(params);
} else {
// throw empty input exception
}
return params;
}
}

Categories

Resources