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.
Related
So, this element of code has the potential to get pretty ugly. There is the potential of adding multiple elements to the list in each if statement as well as many more if/else statements. What would be the best pattern or way of going about designing this piece of code. I was thinking about the chain of responsibility but that means be passing the list round everywhere which isn't the best or even the builder pattern? Any thoughts??
List<String> aList = new ArrayList<>();
if (something.contains(Effect.HARD)) {
aList.add("");
}
if (something.contains(Effect.REFLECT)) {
aList.add("");
aList.add("");
} else {
aList.add("no reflect");
}
if (something.contains(Effect.OUTLINE)) {
aList.add("something");
}
if (something.contains(Effect.GRADIENT)) {
aList.add("gradient");
} else {
aList.add("no gradient");
}
Use a visitor (link to wikipedia page).
Here is some lighthearted example code:
public interface Visilator
{
// Process the stuff and, maybe, add an element to the kerplungy list.
void doStuff(Stuff stuff, List<Kerplungy> kerplungyList);
}
public class Kerplungilator
{
// Actually create this however you choose.
#Autowired
private List<Visilator> visilatorList;
public List<Kerplungy> processStuffs(final Stuff stuff)
{
final List<Kerplungy> returnValue = LinkedList<>(); // ArrayList is for chumps.
for (final Visilator current : visilatorList)
{
current.doStuff(Stuff, returnValue);
}
return returnValue;
}
}
public clss HootVisilator
implements Visilator
{
public void doStuff(
#NotNull final Stuff stuff,
#NotNull final List<Kerplungy> kerplungyList)
{
if (stuff.hoot())
{
final Kerplungy hootKerplungy = new Kerplungy("hoot");
kerplungyList.add(hootkerplungy);
}
else
{
System.out.println("not hoot");
}
}
}
Normally you'd look at replacing those ugly conditionals with polymorphic code, but that won't work well here as the conditions (something.contains(...)) are not based on the type of the object. You could turn them into objects, but this would not be an elegant solution either. Builder and Visitor could be used, but I doubt very much you code would more readable at all.
In my opinion, Java 8 and later versions (actually 9 and 10) lack of a piece to efficiently use Stream and other monads. Java does not have any kind of Try monad to handle errors during monad composition.
Why? Initially, I thought that was a lack of only the version 8, but I do not find any JEP to introduce it in the JDK.
Something like the following could be a starting point.
public class Try<T> {
private T value;
private Exception exception;
private Try(Supplier<T> supplier) {
try {
this.value = supplier.get();
} catch (Exception ) {
this.exception = ex;
}
}
Optional<T> toOptional() {
return Optional.ofNullable(value);
}
public static <T> Try<T> of(Supplier<T> supplier) {
return new Try<>(supplier);
}
// Some other interesting methods...
}
Maybe not anyone uses reactive streams, but during a stream transformation, you need some smart way to collect exceptions, without breaking the whole stream execution.
stream
.map(info -> {
// Code that can rise an exception
// Without the Try monad is tedious to handle exceptions!
})
.filter(/* something */)
.to(/* somewhere */)
Can anyone explain me why? Is it related to some other specification lack?
Thanks to all.
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,
I have some small logging system and it can process Strings, which is all working fine.
Now I want to add the ability to signal that I want a new line, and due to my structure I think it is best to use a special flag, some example code:
public class BaseLogger implements Runnable, LogConsumer {
//....
private final BlockingQueue<String> queue;
//....
#Override
public void run() {
while (running) {
try {
if (consumers.isEmpty()) {
synchronized(consumersEmptyLock) {
consumersEmptyLock.wait();
}
}
String message = queue.take();
for (LogConsumer consumer : consumers) {
consumer.consume(message);
}
} catch (InterruptedException ex) {
handleInterrupt();
}
if (requestShutdown && queue.isEmpty()) {
running = false;
}
}
}
public void log(String message) {
if (message == null) {
throw new IllegalArgumentException("customlogger.CustomLogger.log: message == null");
}
queue.offer(message);
}
So now I want to add an enum, let's say LogFlagEnum, which includes a flag called NEW_LINE.
However currently my queue is of type String, and I would like it to include both String (or perhaps T for a more general answer) and LogFlagEnum.
I know I could use Object as type, but that is not the smallest possible type and definatey not safe and what I want.
What would be the best way to implement the specified behaviour?
Solution 1: use Object. It's no big deal since it's just internal implementation.
Solution 2: use CharSequence; have the enum implement CharSequence. Not exactly very helpful. But in general CharSequence is better than String for accepting text arguments.
Solution 3: every problem in Java can be solved by introducing a new type. You queue can be a queue of LogEntry's, and LogEntry can contain String/enum/whatever.
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;
}
}