Software Design

Low coupling between modules and high cohesion within them.

Low coupling and high cohesion are general design principles.

There is a limit to how many things a person can think about at once (low coupling).

Projects have to make pragmatic trade-offs.

The design is the code, and the code is the design. The design is how it works.
Knowing the best code design comes through quick experimental models using an agile discovery process.

Implementing Domain-Driven Design by Vernon Vaughn

Layered achitecture

Ports and adapters architecture

Known as:

ports and adapters

There are adapters for each of the outside types. The outside reaches the inside through the application API.

Abstract ports are resolved into concrete adapters in the infrastructure layer either through dependency injection or by bootstrapping.

Port is the interface between our application and whatever it is we wish to abstract away, and the adapter is the implementation behind that interface or abstraction.

If you're using an abstract base class, that's the port.

Transaction script

Organizes business logic by procedures where each procedure handles a single request from the presentation.

Martin Fowler

Each operation should either succeed or fail but can never result in an invalid state.

Active record

An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data,

Martin Fowler

There is nothing wrong using active records when the business logic is simple.

When the business logic is simple but operates on complicated data structures.

Domain model

Message bus

Outbox pattern for publishing messages after committing changes to another database.

The outbox pattern is a reliable way to publish aggregates' domain events. It ensures that domain events are always going to be published, even in the face of different process failure.

Command-query responsibility segregation (CQRS)

Read side Write side
Behavior Simple read Complex business logic
Cacheability Highly cacheable Uncacheable
Consistency Can be stale Must be transactionally consistent

Follow one simple rule: functions should either modify state or answer questions, but never both.

Query (read) and Command (write) model.

Event sourcing (event sourced domain model)

https://learn.microsoft.com/en-us/azure/architecture/patterns/event-sourcing

The accepted name for the database that is used for persisting events is event store.

Versioning in an Event Sourced System by Greg Young.

Difference between event-driven achitecture and event sourcing
- event sourcing is a method of capturing changes in state as a series of events
- event-drive architecture refers to the communication between services, event sourcing happens inside a service

Event-driven architecture

Pipes and filters, Sagas (long running processes).

Events, commands, and messages.

An event is a message, but a message is not necessary and event.

Types of messages:

Event categories:

Event notification - something important has happened.

Event-carried state transfer - a message-based data replication mechanism.

Domain event - describing an event in the producer's business domain.

Consider these:

Domain events - trigger workflows that cross consistency boundaries.

Message bus - provides a unified way of invoking use cases from any endpoint.

CQRS - Separating reads and writes avoids awkward compromises in an event-driven architecture and enables performance and scalability improvements.

class Event:
    pass


@dataclass
class MyEvent(Event):
    value: str

Events can help with the single responsibility principle.

A message bus routes messages to handlers.

Options:
- Service layer raises events and passes them to message bus.
- Domain model raises events, service later passes them to message bus.
- UoW collects events from aggregates and passes them to message bus

Move from imperative to event-based flow control changes what used to be orchestration into choreography.

Ed Jung

Commands are sent by one actor to another specific actor with the expectation that a particular thing will happen as a result.

Name commands with imperative mood verb phrases like "allocate stock" or "delay shipment".

Commands capture intent.

Events are broadcast by an actor to all interested listeners.

Name events with past-tense verb phrases.

Use events to spread the knowledge about successful commands.
Senders should not care about whether the receiver succeeded or failed.

Events vs commands:

Event Command
Named Past tense Imperative mood
Error handling Fail independently Fail noisily
Sent to All listeners One recipient

Treating commands and events differently helps us understand which things have to succeed and which things we can tidy up later.

Consistency

Only the data within an aggregate's boundaries can be considered strongly consistent. Everything outside is eventually consistent.

Big ball of mud

A big ball of mud is a haphazardly structured, sloppy, duct-tape-and-baling-wire, spaghetti-code jungle. These systems show unmistakable signs of unregulated growth, and repeated, expedient repair.

Brian Foote and Joseph Yoder

The unregulated growth that leads to big balls of mud results from extending a software system's functionality without re-evaluating its design decisions.

The guiding principle for dealing with growth-driven complexity is to identify and eliminate accidental complexity caused by outdated design decisions.

Other patterns

Forgetable payload

Sensetive information is encrypted, when has to be deleted - only the encryption ckey is being deleted.

Polyglot modeling

OLTP (online transaction processing) and OLAP (online analytical processing) may require different representation of system data.

All databases are flawed, each in its own way.

Greg Young

An alternative to finding a perfect database is the polyglot persistence model: using multiple databases to implement different data-related requirements.

Saga

If one of the execution steps fails, the saga is in charge of issuing relevant compensating actions to ensure the system state remains consistent.

The saga pattern if often confused with process amanger pattern.
The saga patern manages simple, linear flow.
A saga is instantiated implicitly when a particular event is observed.
A process manager can not be bound to a single source event.

The saga pattern can be used to implement simple cross-component business process. More complex business process can be implemented using the process manager pattern.

Tests

Transaction script -> reversed testing pyramid (ice-creame cone).
Active record -> testing diamond.
Domain model -> testing pyramid.
Event-sourced domain model -> testing pyramid.

Testing pyramid (top to bottom): ene-to-end, integration, unit.

Microservices

Notes on microservices.

OLTP

Online transactional processing.

Models have to be optimized to support real-time business transactions.

ALAP

Online analytical processing.

Fact table - business activities that already happened.

Dimention table - represents business process or action (verb), a dimention describes the fact (adjective).

Analytical data us append-only data.

Schemas:

Analytical data architectures:

Data wirehouse - based primarily on the extract-transform-load (ETL) scripts.
The transformation steps may include operations such as removing sensitive data, deduplicating records, reordering events, etc.

Data lake - instead of being transformed right away into an analytical model, the data is persisted in its raw form.

Data mesh - domain-driven design for analytical data. Principles: decompose data around domains, data is aproduct, enable autonomy, build an ecosystem. Analytical data should be treated the same as any public API.

Functional Core and Imperative Shell

Responsibility-driven design

Think about code in terms of behavior, rather than in terms of data or algorithms.

Dependency injection frameworks

Dependency Injector

Punq

Dependencies

API

Pastel's law or robustness principle: be liberal in what you accept, and conservative in what you emit.

Validate as little as possible. Read only the fields you need, and don't overspecify their contents.

Tolerant Reader by Martin Fowler.

Vocabulary

Automation policy - scnario in which an event triggers the execution of a command.

Brownfield projects - already proved their business viability and need a shake up to fight accumulated technical debt and design entropy.

REST - Representational State Transfer (Roy T. Fielding coined the term). Is a means of exchanging and modifying resources that are uniquely identified using a distinct URI.

Licensed under CC BY-SA 3.0