I use lambda expression + Function to implement a strategy pattern, do I use it correctly and appropriately ?
public void deploy(WatcherConfig config) {
performOnWatch(config, a -> {
deployWatch(a);
return null;
});
}
public void delete(final WatcherConfig config) {
performOnWatch(config, a -> {
deleteWatch(a);
return null;
});
}
public void performOnWatch(WatcherConfig config, Function<WatchConfig, Void> function) {
for (WatchConfig watchConfig : config.getWatchConfigs()) {
List<WatchConfig> realConfigs = WatchUtils.parseWatchParameter(watchConfig);
for(WatchConfig realWatchConfig : realConfigs) {
function.apply(realWatchConfig);
}
}
}
You could simplify the performOnWatch method using streams if you implement a streamWatchConfigs to replace getWatchConfigs (which presumably returns a collection):
public void performOnWatch(WatcherConfig config, Consumer<WatchConfig> consumer) {
config.streamWatchConfigs()
.flatMap(WatchUtils::parseWatchParameters)
.forEach(consumer::accept);
}
performOnWatch(config, this::deployWatch);
performOnWatch(config, this::deleteWatch);
Every time you are using the word "pattern" you are digging yourself into a terrible mental hole. That's why I wish that pattern book was never written. Stop thinking about patterns. Forget their names. Think in terms of what you need to get done and what tools the language gives you to solve the problem in a way that combines flexibility, readability of the code and performance. Patterns are mental crutches. If you are smart enough to use patterns correctly, you don't need patterns. IF you are not, patterns will hurt you more than help you.
Seems legit. The only thing I would change is using Consumer<WatchConfig> instead of Function<WatchConfig, Void>. It will simplify method signatures as well as strategy implementations (there will be no need to return null from strategy).
Also if deleteWatch() and deployWatch() returns null and if you will use Consumer code can be rewritten as:
performOnWatch(config, this::deployWatch);
performOnWatch(config, this::deleteWatch);
Related
I have the following POJO:
public class Shipment() {
private LocalDate dateShipped; // Sometimes we know the date of shipment, sometimes we don't
private boolean wasItemShipped; // If we know the date of shipment, this value is true. If we don't know the date, it can be either true or false
}
I'm trying to design the best pattern for managing these two fields. The boolean should be true whenever the Date is not null. However when the Date is null, the boolean can be true or false. Here's a couple of approaches:
Standard getter/setters
public void setDateShipped(LocalDate dateShipped) {
this.dateShipped = dateShipped;
}
public LocalDate getDateShipped() {
return dateShipped;
}
public void setWasItemShipped(boolean wasItemShipped) {
this.wasItemShipped = wasItemShipped
}
public boolean getWasItemShipped() {
return wasItemShipped;
}
This is a pretty normal approach. One downside to this approach is that when developers call setDateShipped() they need to also know to call setWasItemShipped(). This could become problematic if this code is found in multiple spots, or if we need to deserialize some incomplete JSON or something.
Add logic into the setter of dateShipped
public void setDateShipped(LocalDate dateShipped) {
this.dateShipped = dateShipped;
if (dateShipped != null) {
setWasItemShipped(true);
}
}
Add logic into the getter of wasItemShipped
public boolean getWasItemShipped() {
return dateShipped != null || wasItemShipped
}
Both of these approaches have the downside of adding logic to a POJO to mutate it in perhaps surprising ways. I feel like this could lead to frustration/bugs down the road.
Are there any other patterns for this type of operation?
You may checkout Observer and Observable, but that's too complicated. On the other hand there is no formal documentation that strictly says 'no logic inside setters'. So you can go ahead and implement your second approach, and retrofit if needed in future.
I prever Logic in the setter. Ist also helps debugging,as your variables represent the State Office your object and you don‘t Need the getter for getting your Objekts State.
And you can use wasItemShipped in other methods too without mich thinking and making your class More complicated.
To ne it Feels More Natural and intuitive to have Logic in the setter Rather the getter
when implementing an Akka Typed actor by extending createReceive, we will see something like this:
#Override
public Receive<Command> createReceive()
{
return newReceiveBuilder()
.onMessage(SomeCommand.class, s -> something())
.build();
}
..with something() returning a Behavior, for example:
public Behavior<Command> something()
{
return Behaviors.receive(Command.class)
.onMessage(SomeCommand.class, m -> something())
.build();
}
But now we can see that createReceive() and something() being pretty much duplicates. In other words, whenever I return to the "initial" state, I will get this code duplication. So, the question is:
Can I somehow implement createReceive() by re-using the something() method? For example, is something like this possible...
#Override
public Receive<Command> createReceive()
{
return Behaviors.behave( this::something);
}
(Of course, Behaviors.behave does not exist like this, the question is, does something like this exists, "converting" a Behavior to a receive?)
Akka 2.7.0 will introduce an alternative API for defining a behavior which is basically a port of the Scala API.
public class MyActor extends AbstractOnMessageBehavior<MyActor.Command>
public static interface Command {}
public static class SomeCommand extends Command {
public static SomeCommand INSTANCE = new SomeCommand();
private SomeCommand() {}
}
public MyActor(ActorContext<Command> context) {
super(context);
}
#Override
public Behavior<Command> onMessage(Command msg) {
if (msg instanceof SomeCommand) { return something((SomeCommand)msg); }
else return Behaviors.unhandled();
}
private Behavior<Command> something(SomeCommand sc) {
// FIXME: actually do something useful
return Behaviors.same()
}
}
(Apologies if the Java is atrocious)
This API is likely slightly lower overhead than the current Java AbstractBehavior API: the ReceiveBuilder and BehaviorBuilder APIs are effectively compiling a domain-specific language like:
newReceiveBuilder()
.onMessage(SomeMessage.class, this::something)
.build()
into
if (msg instanceof SomeMessage) { return something((SomeMessage)msg); }
else return Behaviors.unhandled();
whenever an instance of this behavior handles its first message (i.e. when an actor handles its first message after transitioning to this behavior). When staying in this behavior, there's also some overhead of checking if the Receive has been built already (though JIT may largely eliminate that).
The benefit of the ReceiveBuilder/BehaviorBuilder APIs is that the instanceof checks and casts are hidden: the developer ergonomic improvement is worth some small overhead. The AbstractOnMessageBehavior lets you opt out of the builder APIs:
You can, effectively, manually compile the builder into instanceof and cast like I did above (this will work on any Java version); if you're on Java 8/11 and want max performance, this might be worth trying (but always, always, benchmark!)
You can use language features ("pattern matching") to have the Java compiler build the instanceof-and-cast logic... this should also make it easier to define a behavior in Kotlin or other JVM language which supports pattern matching. This might even be more ergonomic than the builders.
You can also use a different approach entirely (e.g. one leveraging virtual method dispatch)
I want to refactor an existing class of almost 5000 lines but I'm having difficulty with the constructor. Right now it's something like the following(methods here are in reality 10-30 blocks of code )
public MyClass( MyObject o ) {
if ( o.name.equalsIgnoreCase("a") ) {
doSomething()
} else {
doSomethingElse()
}
commonCode()
if (o.name.equalsIgnoreCase("a") ) {
doSecondThing()
} else {
doOtherSecondThing() //almost identical to doSecondThing but with some extra steps that absolutely have to be done in this sequence
}
// more of the same
}
I considered using inheritance and breaking things up into functions that would be overridden where necessary but that feels messy to me. Is there a pattern that fits this use case? Incidentally any advice on refactoring legacy code would be more than welcome.
You are exactly right. Refactoring like you described is called
Replace Conditional with Polymorphism.
Also you can look through on Chain-of-responsibility, Command or Strategy design patterns.
If every object follows the following pattern:
if(conditionA)
DoA();
else
DoElse();
Common();
if(conditionA2)
DoA2();
else if(conditionB2)
DoB2();
else
DoElse2();
Common2();
I'd advice you to have a common class that gathers handlers with conditions. This is roughly what I mean (Pseudo-code not java):
public interface IConditionalHandler
{
bool Condition();
void Action();
}
public class ActionHandler
{
private List<IConditionalHandler> m_FirstHandlers;
private List<IConditionalHandler> m_SecondHandlers; //Or possibly use a list of lists
public ActionHandler()
{
m_FirstHandlers = new ArrayList<>();
m_FirstHandlers.add(new HandlerA1());
m_FirstHandlers.add(new HandlerB1());
m_SecondHandlers = new ArrayList<>();
m_SecondHandlers.add(new HandlerA1());
m_SecondHandlers.add(new HandlerB1());
}
void DoStuff()
{
for(IConditionHandler handler : m_FirstHandlers)
{
if(handler.Condition())
{
handler.Action();
break;
}
}
CommonA();
for(IConditionHandler handler : m_SecondHandlers)
{
if(handler.Condition())
{
handler.Action();
break;
}
}
}
}
If you have lots of segment, a list of lists can include your common code as an exit-handler and contain all of the logic. You delegate the logic out to implementing classes, and shorten the actual code in your class.
However, as far as efficiency goes you are going to kill both the instruction and data cache. If this isn't what you're looking for, then more than likely this is: Chain-of-Responsibility Pattern - Wikipedia
I have a "legacy" code that I want to refactor.
The code basically does a remote call to a server and gets back a reply. Then according to the reply executes accordingly.
Example of skeleton of the code:
public Object processResponse(String responseType, Object response) {
if(responseType.equals(CLIENT_REGISTERED)) {
//code
//code ...
}
else if (responseType.equals(CLIENT_ABORTED)) {
//code
//code....
}
else if (responseType.equals(DATA_SPLIT)) {
//code
//code...
}
etc
The problem is that there are many-many if/else branches and the code inside each if is not trivial.
So it becomes hard to maintain.
I was wondering what is that best pattern for this?
One thought I had was to create a single object with method names the same as the responseType and then inside processResponse just using reflection call the method with the same name as the responseType.
This would clean up processResponse but it moves the code to a single object with many/many methods and I think reflection would cause performance issues.
Is there a nice design approach/pattern to clean this up?
Two approaches:
Strategy pattern http://www.dofactory.com/javascript/strategy-design-pattern
Create dictionary, where key is metadata (in your case metadata is responseType) and value is a function.
For example:
Put this in constructor
responses = new HashMap<string, SomeAbstraction>();
responses.Put(CLIENT_REGISTERED, new ImplementationForRegisteredClient());
responses.Put(CLIENT_ABORTED, new ImplementationForAbortedClient());
where ImplementationForRegisteredClient and ImplementationForAbortedClient implement SomeAbstraction
and call this dictionary via
responses.get(responseType).MethodOfYourAbstraction(SomeParams);
If you want to follow the principle of DI, you can inject this Dictionary in your client class.
My first cut would be to replace the if/else if structures with switch/case:
public Object processResponse(String responseType, Object response) {
switch(responseType) {
case CLIENT_REGISTERED: {
//code ...
}
case CLIENT_ABORTED: {
//code....
}
case DATA_SPLIT: {
//code...
}
From there I'd probably extract each block as a method, and from there apply the Strategy pattern. Stop at whatever point feels right.
The case you've describe seems to fit perfectly to the application of Strategy pattern. In particular, you've many variants of an algorithm, i.e. the code executed accordingly to the response of the remote server call.
Implementing the Stategy pattern means that you have to define a class hierachy, such the following:
public interface ResponseProcessor {
public void execute(Context ctx);
}
class ClientRegistered implements ResponseProcessor {
public void execute(Context ctx) {
// Actions corresponding to a client that is registered
// ...
}
}
class ClientAborted implements ResponseProcessor {
public void execute(Context ctx) {
// Actions corresponding to a client aborted
// ...
}
}
// and so on...
The Context type should contain all the information that are needed to execute each 'strategy'. Note that if different strategies share some algorithm pieces, you could also use Templeate Method pattern among them.
You need a factory to create a particular Strategy at runtime. The factory will build a strategy starting from the response received. A possibile implementation should be the one suggested by #Sattar Imamov. The factory will contain the if .. else code.
If strategy classes are not to heavy to build and they don't need any external information at build time, you can also map each strategy to an Enumeration's value.
public enum ResponseType {
CLIENT_REGISTERED(new ClientRegistered()),
CLIENT_ABORTED(new ClientAborted()),
DATA_SPLIT(new DataSplit());
// Processor associated to a response
private ResponseProcessor processor;
private ResponseType(ResponseProcessor processor) {
this.processor = processor;
}
public ResponseProcessor getProcessor() {
return this.processor;
}
}
I am building a HTTP server for my android device.
I am using a lot of IF-ELSE statements to handle differnt requests.
As I will be sharing my code with other people for later use, I will have to make it as legible as possible. Right now, I can't even read my code with ease.
I think the problem comes from using a lot of IF-ELSE statements in one class.
For example.
if(purpose.equals("readProfile"){
.....
}
else if(purpose.equals("writeProfile"){
.....
}
....
I tried classifying them in category and ordered the conditions according to their category. But not a lot of legebility was improved.
Then I tried writing short comments infront of each conditions. But this made even more mess.
What can be done to increase legibility for conditional statements?
As Luiggi Mendoza stated, this is a follow up of a previous question...
If you are using Java 7, you can use a switch-case statement for strings
//month is a String
switch (month.toLowerCase()) {
case "january":
monthNumber = 1;
break;
//partsleft out for sake of brevity ..
default:
monthNumber = 0;
break;
}
(excerpt from the Oracle Java Tutorials, referenced above.)
Refactoring
However, this huge if-else is just part of the problem. As this seems to be a structure growing over time, I'd recommend a thorough refactoring, and using what seems to me is a Strategy pattern. You should:
Formulate an interface which covers the boundaries for all the use cases:
interface MyStrategy {
void execute(MyInputContext input, MyOutputContext output);
}
(using a void method with MyInputContext and MyOutputContext are just one approach, this is just an example, but to handle requests that have responses, this makes sense, just like how Servlets work)
Refactor the content of the big IF-ELSE statement into instances of this interface (these will be the strategies):
//VERY simplified...
class ReadProfileStrategy implements MyStrategy {
void execute(MyInputContext input, MyOutputContext output) {
//do the stuff that was in the if-else block in the "readProfile" part
}
}
//... at the branching part:
MyInputContext input; //build this here
MyOutputContext output; //build this here
switch (purpose) {
case "readProfile":
// no need to always instantiate this, it should be stateless...
new ReadProfileStrategy().execute();
break;
//... left out for sake of brevity
}
Refactoring step 2
If this is done, you can add the string IDs to the interface, and the instances themselves, and get rid of the if-else or switch statement altogether, you could create a Map populated even through an IOC container (like), to be up to date, and completely flexible.
class ReadProfileStrategy implements MyStrategy {
String getID() {
return "readProfile";
}
void execute(MyInputContext input, MyOutputContext output) {
//do the stuff that was in the if-else block in the "readProfile" part
}
}
In the class when requests are processed
private final Map<String, MyStrategy> strategyMap; //fill the map using your favorite approach, like using Spring application context, using the getCode() to provide the key of the map
In the processing logic:
MyStrategy strategy = strategyMap.get(purpose);
if(strategy!=null) {
strategy.execute();
}
else {
//handle error here
}
This may be out of scope, but just an observation
try using
if("readProfile".equals(purpose){} instead of
if(purpose.equals("readProfile"){}.
It will help to avoid null pinter exception
Enums can help - you can also add functionality to them.
public void test(String purpose) {
if (purpose.equals("readProfile")) {
// Read.
} else if (purpose.equals("writeProfile")) {
// Write.
}
}
enum Purpose {
readProfile {
#Override
void doIt() {
// Read.
}
},
writeProfile {
#Override
void doIt() {
// Write.
}
};
abstract void doIt();
}
public void test2(String purpose) {
Purpose.valueOf(purpose).doIt();
}
You can try using some kind of Action-Interface with implementations for each block and preload a map with concrete Implementations of this action.
interface Action {
void execute();
}
Map<String, Action> actions = new HashMap<>();
actions.put("readProfile", new Action() { ... });
actions.put("writeProfile", new Action() { ... });
actionMap.get(purpose).execute();
That will lower your cyclomatic complexity as well. Of course you should preload the map only once.
Well, If it makes sense to separate code inside if-else condition to another class, perhaps use Factory pattern. Also make all separated classes implement common interface (eg: MyActivity.class) with a method such as execute().
Factory decides what object (ReadProfile.class, WriteProfile.class etc.) has to be created based on the string you pass and then call execute() method.
MyActivity obj = MyFactory.createMyActivity(String)
obj.execute(...);