HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

I command thee: do SOMETHING

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
commandtheesomething

Problem

I am currenly contributing to a Chat-Bot to be used across the whole SE-Network's chat which is implemented in Java 8.

This bot is supposed to have commands. These commands again are supposed to be as flexible as possible, and based on chat messages. To allow easy and extensible implementation of arbitrary commands I have created the following two classes:

  • CommandHandle: This class defines when a command is "triggered", and specifies the code executed. It's supposed to be as "generic" as possible while allowing clean and specialized code.



  • CommandHandleBuilder: This class is responsible for building instances of CommandHandles and defines a chainable API that's supposed to be easy to use for anybody willing to create their own commands.



Currently the bot itself is a work in progress, but a working one can be found on github.

Anyways let's get into code:

/**
 * Simple handle for a Command. Consists of a {@link Predicate} to match
 * messages (aka. invocations) against, a helpText,
 * an infoText and a {@link Consumer Consumer} for {@link ChatMessage ChatMessages}
 * 
 * @author vogel612vogel612@gmx.de>
 */

public class CommandHandle {

    private final Predicate     matchesSyntax;

    private final String                helpText;

    private final String                infoText;

    private final Consumer executor;

    public CommandHandle(
        Predicate matchesSyntax, Consumer executor,
        String helpText, String infoText) {
        this.matchesSyntax = matchesSyntax;
        this.helpText = helpText;
        this.infoText = infoText;
        this.executor = executor;
    }

    public void execute(ChatMessage message) {
        executor.accept(message);
    }

    public boolean matchesSyntax(String commandCall) {
        return matchesSyntax.test(commandCall);
    }

    public String getHelpText() {
        return helpText;
    }

    public String getInfoText() {
        return infoText;
    }
}


```
/**
* Command Builder for ass

Solution

If you are intent on using a builder, then I'd suggest either making it an inner static class to the main class or a different class in the same package. If the first solution, then the constructor for the built class can be made private; if the second, it can be made package local. First scenario:

public final class Foo
{
    // instance variables...

    public static Builder newBuilder()
    {
        return new Builder();
    }

    private Foo(args, here) { /* whatever */ }

    public static final class Builder
    {
        // etc etc

        public Foo build()
        {
            return new Foo(args, here);
        }
    }
}


Easy to adapt in the second scenario.

Second remark: I fail to see why FALSE is an illegal value at all for your predicate; as your code reads right now, I can very well input s -> false as an argument to the predicate and it will work. Why not just "let it be"? After all, it is the user's fault if a correct predicate is not provided, isn't it?

Third remark: calling a Consumer an executor? Uh... Why not just Consumer? Also, remind that any interface obeying the prototype of a @FunctionalInterface can be used, so you can define public interface MessageConsumer extends Consumer and use instances of this interface. By default, you could supply an empty one, or one that System.out.println()s, for instance

Code Snippets

public final class Foo
{
    // instance variables...

    public static Builder newBuilder()
    {
        return new Builder();
    }

    private Foo(args, here) { /* whatever */ }

    public static final class Builder
    {
        // etc etc

        public Foo build()
        {
            return new Foo(args, here);
        }
    }
}

Context

StackExchange Code Review Q#70178, answer score: 3

Revisions (0)

No revisions yet.