diff --git a/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/Command.java b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/Command.java new file mode 100644 index 0000000..e3b6157 --- /dev/null +++ b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/Command.java @@ -0,0 +1,12 @@ +package pl.mperor.lab.java.clean.code.ddd; + +interface Command { + + interface CommandHandler { + Status handle(C command); + } + + enum Status { + DONE + } +} diff --git a/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/Event.java b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/Event.java new file mode 100644 index 0000000..201c130 --- /dev/null +++ b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/Event.java @@ -0,0 +1,30 @@ +package pl.mperor.lab.java.clean.code.ddd; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; + +interface Event { + + record Publisher(Collection consumers) { + + public Publisher { + consumers = List.copyOf(consumers); + } + + Publisher onPublish(EventConsumer consumer) { + var newConsumers = new ArrayList<>(consumers); + newConsumers.add(consumer); + return new Publisher(newConsumers); + } + + void publish() { + var event = new Event() {}; + consumers.forEach(consumer -> consumer.accept(event)); + } + + interface EventConsumer extends Consumer { + } + } +} diff --git a/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/CommandVsEventTest.java b/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/CommandVsEventTest.java new file mode 100644 index 0000000..ec88fb7 --- /dev/null +++ b/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/CommandVsEventTest.java @@ -0,0 +1,55 @@ +package pl.mperor.lab.java.clean.code.ddd; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.UUID; + +/** + * ⚑ Command vs Event 🎯 + * + *

Command: An instruction to perform an action, usually leading to a state change. + * - Imperative πŸ—οΈ + * - Synchronous or Asynchronous ⏳ + * - Expect a specific effect πŸ”„ + * + *

Event: A fact that something has happened in the past. + * - Declarative πŸ“’ + * - Asynchronous-friendly ⏩ + * - Captures history πŸ•°οΈ + */ +class CommandVsEventTest { + + private final Command.CommandHandler handler = command -> { + System.out.printf("🫡 Command: %s%n", command); + return Command.Status.DONE; + }; + + private final Event.Publisher publisher = new Event.Publisher(Collections.emptyList()); + + @Test + void commandShouldExecuteImmediately() { + Assertions.assertEquals(Command.Status.DONE, handler.handle(new Command() {})); + } + + @Test + void commandsCanBeHandledByTheSameHandler() { + record CreateOrderCommand(UUID uuid) implements Command {} + record CreatePaymentCommand(UUID uuid) implements Command {} + Assertions.assertEquals(Command.Status.DONE, handler.handle(new CreateOrderCommand(UUID.randomUUID()))); + Assertions.assertEquals(Command.Status.DONE, handler.handle(new CreatePaymentCommand(UUID.randomUUID()))); + } + + @Test + void eventShouldNotBeConsumeWithoutPublishing() { + publisher.onPublish(_ -> Assertions.fail()); + } + + @Test + void eventShouldBeConsumeByManyConsumers() { + publisher.onPublish(event -> System.out.printf("❗Event: %s%n", event)) + .onPublish(Assertions::assertNotNull) + .publish(); + } +}