Youtube resources

CQRS

https://www.youtube.com/watch?v=cqNGAo-9pUE

DDD

Domain Events, Value Objects, Aggregate Roots, Entities, Repositories

Value objects

Equal if same values:

Value objects are immutable:

Concrete example in Python:

class Money:
    def __init__(self, amount, currency):
        self.amount = amount
        self.currency = currency

    def add(self, money):
        if self.currency != money.currency:
            raise Exception("Currency mismatch")
        return Money(self.amount + money.amount, self.currency)

    def __eq__(self, other):
        return self.amount == other.amount and self.currency == other.currency

    def __str__(self):
        return str(self.amount) + " " + self.currency

Entities

Equal if same identity: Concrete example in Python:

class Account:
    def __init__(self, account_id, balance):
        self.account_id = account_id
        self.balance = balance

    def __eq__(self, other):
        return self.account_id == other.account_id

    def __str__(self):
        return str(self.account_id) + " " + str(self.balance)

Aggregate roots

Aggregate roots are entities that are the root of an aggregate. Aggregtes are a cluster of objects that are treated as a unit for the purpose of data changes.

concrete example in Python:

### Example of an Aggregate root
class Car:
    def __init__(self, car_id, engine, wheels):
        self.car_id = car_id
        self.engine = engine
        self.wheels = wheels

    def __eq__(self, other):
        return self.car_id == other.car_id

    def __str__(self):
        return str(self.car_id) + " " + str(self.engine) + " " + str(self.wheels)

We must save the aggregate root as a whole. We cannot save the engine and the wheels separately.

Repositories

Repositories are used to retrieve aggregates from the database. They are used to hide the details of the database from the domain layer.

conceptual example in Python:

class CarRepository:
    def __init__(self):
        self.cars = []

    def save(self, car):
        self.cars.append(car)

    def get(self, car_id):
        for car in self.cars:
            if car.car_id == car_id:
                return car
        return None

Domain Events

Domain events are used to notify other parts of the system that something has happened. They are used to decouple the domain layer from other parts of the system.

concrete example in Python:

class AccountCreated:
    def __init__(self, account_id):
        self.account_id = account_id

Bounded Contexts & subdomains

Bounded contexts are used to divide a large domain into smaller subdomains. Each subdomain has its own bounded context. Each bounded context has its own domain model.

Context map is used to show the relationships between the bounded contexts.

Core domain is the most important part of the domain. It is the part that gives the company its competitive advantage.

Supoorting subdomains are the parts of the domain that are not part of the core domain. They are still important but they do not give the company its competitive advantage.

Generic subdomains are the parts of the domain that are not important for the company. They can be implemented using off-the-shelf software.

Conformist is a bounded context that uses the same model as another bounded context.

Anti-corruption layer is used to translate between two bounded contexts that use different models.

Open host service is a bounded context that exposes its functionality to other bounded contexts.

Published language is a bounded context that exposes its model to other bounded contexts.

Shared kernel is a bounded context that is shared between two or more bounded contexts.

Hexagonal, Onion & Clean Architecture

Interfaces are used to decouple the domain layer from the infrastructure layer. The domain layer defines the interfaces and the infrastructure layer implements them. Interfaces are called ports. The domain layer is the inside of the hexagon and the infrastructure layer is the outside of the hexagon.

Primary ports are used by the outside world to access the domain layer. Secondary ports are used by the domain layer to access the outside world.

Presentation layer is used to interact with the user. Application layer is used to implement the use cases. Domain layer is used to implement the domain model. Infrastructure layer is used to implement the interfaces.

Domain layer is the most important part of the system. It is the part that gives the system its competitive advantage.Domain services are used to implement use cases that do not belong to any entity or value object. Interfaces are used to decouple the domain layer from the infrastructure layer. The domain layer defines the interfaces and the infrastructure layer implements them. Interfaces are called ports. The domain layer is the inside of the hexagon and the infrastructure layer is the outside of the hexagon.

Clean architecture is similar to hexagonal architecture. The main difference is that clean architecture uses a layered architecture instead of a hexagonal architecture. The domain layer is the most important part of the system. It is the part that gives the system its competitive advantage. Domain services are used to implement use cases that do not belong to any entity or value object. Interfaces are used to decouple the domain layer from the infrastructure layer. The domain layer defines the interfaces and the infrastructure layer implements them. Interfaces are called ports. The domain layer is the inside of the hexagon and the infrastructure layer is the outside of the hexagon.

entities, ports and use cases are the most important parts of the system. Entities are used to implement the domain model. Ports are used to decouple the domain layer from the infrastructure layer. Use cases are used to implement the business logic. Frameworks are used to implement the infrastructure layer. The infrastructure layer is the outside of the onion and the domain layer is the inside of the onion. Drivers are used to implement the interfaces. Driven adapters are used to implement the interfaces.

Event Sourcing

Event sourcing is a way to persist the state of an aggregate by storing the events that have happened to the aggregate. The state of the aggregate is restored by replaying the events. Event sourcing is used to implement the event store pattern. Event store is used to persist the events that have happened to an aggregate. Event store is used to implement the event sourcing pattern. Event sourcing is used to persist the state of an aggregate by storing the events that have happened to the aggregate. The state of the aggregate is restored by replaying the events. Event sourcing is used to implement the event store pattern. Event store is used to persist the events that have happened to an aggregate. Event store is used to implement the event sourcing pattern.

Using Kafka as an event store: a concrete example in Python:

from kafka import KafkaProducer
from kafka import KafkaConsumer
from json import dumps

from json import dumps
from json import loads

producer = KafkaProducer(bootstrap_servers=['localhost:9092'],
                         value_serializer=lambda x:
                         dumps(x).encode('utf-8'))

consumer = KafkaConsumer(
    'my-topic',
     bootstrap_servers=['localhost:9092'],
     auto_offset_reset='earliest',
     enable_auto_commit=True,
     group_id='my-group',
     value_deserializer=lambda x: loads(x.decode('utf-8')))

for message in consumer:
    message = message.value
    print('{}'.format(message))

CQRS

CQRS stands for Command Query Responsibility Segregation. CQRS is used to separate the read model from the write model. CQRS is used to implement the command query separation pattern. The write model is used to update the state of the system. The read model is used to query the state of the system. The write model is updated by sending commands to it. The read model is updated by sending events to it. CQRS is used to implement the event sourcing pattern. CQRS is used to implement the event store pattern. CQRS is used to implement the CQRS pattern. CQRS is used to implement the command query separation pattern. The write model is used to update the state of the system. The read model is used to query the state of the system. The write model is updated by sending commands to it. The read model is updated by sending events to it. CQRS is used to implement the event sourcing pattern. CQRS is used to implement the event store pattern. CQRS is used to implement the CQRS pattern.