DEV Community

Cover image for Behavior driven service development
Bertil Muth
Bertil Muth

Posted on

Behavior driven service development

I just released version v2.0 of the requirements as code library.

Using it, you can create a single behavior that receives messages from the calling code. The behavior then dispatches the messages to an appropriate message handler. Which handler is appropriate is defined in a behavior model.

In the following example, a user sends a request with the user name (“Joe”). The system greets the user with “Hello, Joe.”

package helloworld;

import java.util.function.Consumer;

import org.requirementsascode.Behavior;
import org.requirementsascode.BehaviorModel;
import org.requirementsascode.Model;
import org.requirementsascode.StatelessBehavior;

public class HelloUser {
  public static void main(String[] args) {
    GreeterModel greeterModel = new GreeterModel(HelloUser::sayHello);
    Behavior greeter = StatelessBehavior.of(greeterModel);
    greeter.reactTo(new SayHelloRequest("Joe"));
  }

  private static void sayHello(SayHelloRequest requestsHello) {
    System.out.println("Hello, " + requestsHello.getUserName() + ".");
  }
}

class GreeterModel implements BehaviorModel {
  private final Consumer<SayHelloRequest> sayHello;

  public GreeterModel(Consumer<SayHelloRequest> sayHello) {
    this.sayHello = sayHello;
  }

  @Override
  public Model model() {
    Model model = Model.builder()
      .user(SayHelloRequest.class).system(sayHello)
    .build();
    return model;
  }
}

class SayHelloRequest {
  private final String userName;

  public SayHelloRequest(String userName) {
    this.userName = userName;
  }

  public String getUserName() {
    return userName;
  }
}
Enter fullscreen mode Exit fullscreen mode

Since the behavior is the central point of control for all functions, you can inject and configure the dependencies of all functions through it. That makes it easy to implement a hexagonal architecture or clean architecture.

The following example shows how to implement a clean architecure with requirements as code, in principle:

public class CleanArchitectureOutline {
  public static void main(String[] args) {
    ConsolePrinter consolePrinter = new ConsolePrinter(); 
    GreetingServiceModel greetingServiceModel = new GreetingServiceModel(consolePrinter);
    Behavior greetingService = StatelessBehavior.of(greetingServiceModel);

    greetingService.reactTo(new SayHelloRequest("Joe"));
  }
}

/**
 * The behavior model defines that a consumer reacts to SayHelloRequest.
 * 
 * @author b_muth
 *
 */
class GreetingServiceModel implements BehaviorModel {
  private final Consumer<String> outputPort;

  public GreetingServiceModel(Consumer<String> outputPort) {
    this.outputPort = outputPort;
  }

  @Override
  public Model model() {
    Model model = Model.builder()
      .user(SayHelloRequest.class).system(sayHello())
    .build();
    return model;
  }

  private SayHello sayHello() {
    return new SayHello(outputPort);
  }
}

/**
 * Command class
 */
class SayHelloRequest {
  private final String userName;

  public SayHelloRequest(String userName) {
    this.userName = userName;
  }

  public String getUserName() {
    return userName;
  }
}

/**
 * Message handler
 */
class SayHello implements Consumer<SayHelloRequest> {
  private final Consumer<String> outputPort;

  public SayHello(Consumer<String> outputPort) {
    this.outputPort = outputPort;
  }

  public void accept(SayHelloRequest requestHello) {
    String greeting = Greeting.forUser(requestHello.getUserName());
    outputPort.accept(greeting);
  }
}

/**
 * Infrastructure class
 */
class ConsolePrinter implements Consumer<String>{
  public void accept(String message) {
    System.out.println(message);
  }
}

/**
 * Domain class
 */
class Greeting {
  public static String forUser(String userName) {
    return "Hello, " + userName + ".";
  }
}
Enter fullscreen mode Exit fullscreen mode

I think about writing an article about a new, modern approach to clean architecture soon. My goal is to further simplify the development of a service with a clean architecture in a Spring environment.

Are you interested? Tell me what you think in the comments.

Top comments (0)