Background Shape
Hero Shape
Written by Armakuni
Sep 17, 2024

Demystifying Event-Driven Architectures and Event Sourcing: Key Differences and Synergies

Table of Content

Demystifying Event-Driven Architectures and Event Sourcing: Key Differences and Synergies

If you’re transitioning to a programming language like Python or TypeScript that supports multiple paradigms but come from an object-oriented programming (OOP) background, you might prefer sticking with OOP practices. While using classes is entirely valid, you may end up creating unnecessary boilerplate code. Here’s how you can simplify common single-method class patterns by using functions, reducing boilerplate and enhancing code clarity.

Simplifying Single-Method Classes

Single-method classes are designed to represent a specific action, often wrapping state or dependencies needed for the method’s execution. Here’s how you can simplify these classes.

Refactoring Simple Actions

The simplest case involves a class that only wraps a function without any dependencies. For instance, a class that performs addition can be simplified:

Class-Based Approach:

python

Copy code

class Adder: def calculate(self, a: int, b: int) -> int: return a + b

Function-Based Approach:

python

Copy code

def add(a: int, b: int) -> int: return a + b

While you lose the interface implementation with a function, you can use type aliases to define callable types for abstraction:

python

Copy code

Calculator = Callable[[int, int], int]

Simplifying Dependency Injection

Another example is a class that uses constructor injection to manage dependencies:

Class-Based Approach:

python

Copy code

class OrderCreator: def __init__(self, order_repository: OrderRepository, email_sender: EmailSender): self._order_repository = order_repository self._email_sender = email_sender def create_order(self, customer: Customer, items: list[Items]) -> None: order_id = OrderID.generate() order = Order(order_id, items) self._order_repository.save(order) confirmation_email = Email(to=customer, subject=f"Thank you for your order {order_id}") self._email_sender.send(confirmation_email)

Function-Based Approach:

python

Copy code

CreateOrder = Callable[[Customer, list[Items]], None] def new_order_creator(order_repository: OrderRepository, email_sender: EmailSender) -> CreateOrder: def create_order(customer: Customer, items: list[Items]) -> None: order_id = OrderID.generate() order = Order(order_id, items) order_repository.save(order) confirmation_email = Email(to=customer, subject=f"We have received your order {order_id}") email_sender.send(confirmation_email) return create_order

Handling Deferred Dependencies

A similar simplification applies when using deferred dependencies:

Class-Based Approach:

python

Copy code

class Email: def __init__(self, to: str, subject: str, body: str): self._to = to self._subject = subject self._body = body def send(self, sender: EmailSender) -> None: sender.send(self._to, self._subject, self._body)

Function-Based Approach:

python

Copy code

SendEmail = Callable[[EmailSender], None] def create_email(to: str, subject: str, body: str) -> SendEmail: def send(sender: EmailSender) -> None: sender.send(to, subject, body) return send

Summary

For classes with a single method, consider using functions to streamline your code. While this approach may seem to move away from OOP, it retains the concept of encapsulating behavior while reducing boilerplate. Type aliases can offer named abstractions for these functions, maintaining clarity and improving communication. In object-oriented languages, command classes might still be necessary, but in multi-paradigm languages, functions often provide a more concise and readable alternative.

Got Questions?

Reach out, and we’ll have answers for you pronto.

Send message
Success Icon
Request Received

Thank you for reaching out to Armakuni. We have received your message and will get back to you as soon as possible.

Oops! Something went wrong while submitting the form.

Got Questions?

Reach out, and we’ll have answers for you pronto.

Send message

Meet the speakers

No items found.