101 DDD

Mitigating the "Ball of mud" in your products/services with Domain Driven Design.

@juanantoniobm & @LeXavTwit

101 DDD

Follow the talk from with your smartphone:

101 DDD

Example repository:

https://github.com/jabrena/101-ddd

I can't teach anything. I can only make you think.
- Socrates
Can't see the forest for the trees
- John Heywood
Production is the happiest place in the world.
- Josh Long
it’s not the domain expert's knowledge that goes into production, it’s the developer's assumption of that knowledge.
- Alberto Brandolini

Agenda

  1. Who I am
  2. Expectations
  3. Context
  4. DDD: "what when why where how"
  5. Strategic DDD
  6. Implementing Strategic DDD
  7. Tactical DDD
  8. Implementing Tactical DDD
  9. Who to follow about DDD
  10. References

Disclaimer

Note: DDD is not the unique way to develop software for production.

Who I am

Juan Antonio Breña Moral

Engineering in Industrial Organization (M.S.) @ ICAI
Technical Architect & Innovation Estratego @ VASS
Associate Professor @ ICAI
STEAM Teacher @ Space Math
@juanantoniobm | Github

Who I am

Xavier Levaux

Bachelor degree in Management Information Systems @ HE VINCI
Freelance Senior Software Engineer
@LeXavTwit | Github

Expectations

The talk will try explain some ideas from:

Expectations


Source: https://www.dddcommunity.org/book/evans_2003/

Expectations


Source: https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf

Expectations


Source: https://kalele.io/books/ddd-destilado/

Expectations


Source: https://contextmapper.org/media/978-3-030-67445-8_11_AuthorsCopy.pdf

Expectations


Source: https://leanpub.com/introducing_eventstorming

Expectations

ISO 25010


Source: https://iso25000.com/index.php/en/iso-25000-standards/iso-25010

Expectations

The talk doesn´t cover the following topics ATM:

  • Wardley maps
  • User Story Mapping
  • Impact Mapping
  • Example Mapping
  • Event Modelling
  • Team topologies
  • Cognitive Load

Context

What is a Software architecture?

Architecture is about the important stuff. Whatever that is.


Source: https://martinfowler.com/architecture/

Context

Timeline


Source: https://eventmodeling.org/about/

Context

Or maybe your design suffer with: Anemic Domain Model

Context

Microservices with Spring Cloud Kubernetes


Source: https://tanzu.vmware.com/developer/guides/kubernetes/app-enhancements-spring-k8s/

Context

Microservices running in a multi cloud environments


Source: https://www.vmware.com/products/tanzu-service-mesh.html

Context

Have that designs an enough detail to create a backlog to start the implementation phase?

Timeline

Timeline

2003 - Domain Driven Design

Timeline

2003 - Domain Driven Design

Timeline

2003 - Domain Driven Design

Context

Did you read a book about DDD previously?

DDD: "what when why where how"

What is DDD?

Domain-driven design (DDD) is a software design that focuses on understanding domain experts and building the software as a model of its domain.

One concept is that the structure and language of software code (class names, class methods, class variables) should match the business domain.

Source: https://en.wikipedia.org/wiki/Domain-driven_design

DDD: "what when why where how"

When use DDD?



In any moment :)

DDD: "what when why where how"

Why use DDD?

  • Improve the design of your project
  • Reduce the complexity to maintain software in Production stage

DDD: "what when why where how"

Where use DDD?

Depends of the DDD Skills 🤷‍

DDD: "what when why where how"

How use DDD?

You could use DDD:

  • Strategically
  • Tactically

DDD: "what when why where how"

How use DDD? Strategic DDD

Strategic Design is a set of principles and patterns for maintaining model integrity, distilling the Business Domain Model, and working with multiple models. Strategic design is very useful to divide a large and complex business problem into multiple chunks with clear boundaries and specific responsibilities and build a high-level software design topology.

DDD: "what when why where how"

How use DDD? Tactical DDD

Tactical Design is a set of design patterns and building blocks that you can use to abstract low and mid-level components of the software. Tactical patterns are very hands-on addressing programming code and deal with classes and modules. The purpose of tactical design is to refine the result of Strategic patterns applied to a stage where it can be converted into a working code.

DDD: "what when why where how"

DDD Vocabulary

Strategic DDD

Define the Ubiquitous Language, the Bounded contexts and the Context maps

Strategic DDD

Concepts:

  • The Ubiquitous Language
  • The Bounded contexts
  • The Context maps

  • Structural Refactorings

Strategic DDD

The Ubiquitous Language

A language structured around the domain model and used by all team members within a bounded context to connect all the activities of the team with the software.

Strategic DDD

The Ubiquitous Language


Source: https://blog.tekaris.com/blog/introduction-ubiquitous-language/

Strategic DDD

The Ubiquitous Language


Source: https://medium.com/nick-tune-tech-strategy-blog/domains-subdomain-problem-solution-space-in-ddd-clearly-defined-e0b49c7b586c

Strategic DDD

The Ubiquitous Language

Strategic DDD

The Ubiquitous Language

What happened with meters & miles?

Source: https://www.simscale.com/blog/2017/12/nasa-mars-climate-orbiter-metric/

Strategic DDD

The Bounded contexts

A description of a boundary (typically a subsystem, or the work of a particular team) within which a particular model is defined and applicable.

Strategic DDD

The Bounded contexts


Source: https://martinfowler.com/bliki/BoundedContext.html

Strategic DDD

The Bounded contexts

Domains & Subdomains


Source: https://speakerdeck.com/mploed/aligning-organization-and-architecture-with-strategic-ddd

Strategic DDD

The Bounded contexts

Domains & Subdomains


Source: https://speakerdeck.com/mploed/aligning-organization-and-architecture-with-strategic-ddd

Strategic DDD

The Bounded contexts

Domains & Subdomains


Source: https://speakerdeck.com/mploed/aligning-organization-and-architecture-with-strategic-ddd

Strategic DDD

The Bounded contexts

Domains & Subdomains


Source: https://speakerdeck.com/mploed/aligning-organization-and-architecture-with-strategic-ddd

Strategic DDD

The Context maps

Context Maps describe the contact between bounded contexts and teams with a collection of patterns. There are nine context map patterns and three different team relationships.

Strategic DDD

The Context maps patterns:


Source: https://github.com/ddd-crew/context-mapping

Strategic DDD

The Context maps patterns:

Technical integration patterns between Bounded Contexts:

  • Open Host Service [OHS]
  • Published Language [PL]
  • Anticorruption Layer [ACL]

Strategic DDD

The Context maps patterns:

Organizational patterns and integration that describe the types of relationship between Bonded Contexts:

  • Shared Kernel [SK]
  • Conformist [CF]
  • Customer / Supplier [C,S]
  • Partnership [P]
  • Separate ways *
  • Big ball of Mud *

Strategic DDD

The Context maps patterns: Open Host Service

This pattern addresses the case where the power is skewed toward the consumers. The supplier is interested in protecting its consumers and providing the best service possible.

To protect the consumers from changes in its implementation, the upstream supplier decouples its implementation model from the public interface.

Strategic DDD

The Context maps patterns: Open Host Service

  • One API for several consumers
  • Has a common, general purpose model and functionality
  • The team providing the Open-Host Service is an upstream team

Strategic DDD

The Context maps patterns: Open Host Service

Source: https://contextmapper.org/docs/open-host-service/

Strategic DDD

The Context maps patterns: Published Language

Common language for the translation between the models that are going to interact. For example JSON or XML. Usually associated with OHS. The advantage of using REST services is that in each request the PL can be specified by configuring the desired content type.

Strategic DDD

The Context maps patterns: Published Language

A well documented language shared between bounded contexts

  • Every bounded context can translate in and out from that language
  • Sometimes defined by a consortium of the most important stakeholders / teams
  • Often combined with Open-Host teams

Strategic DDD

The Context maps patterns: Published Language

Source: https://contextmapper.org/docs/published-language/

Strategic DDD

The Context maps patterns: Anticorruption Layer

This is another upstream/downstream relationship at a lower level, where the downstream bounded context implements a layer between itself and the upstream.

This layer is responsible for translating the objects given by the upstream into its own models. This approach will guarantee the integrity of the downstream bounded context and keeps it completely ignorant of any foreign concepts.

Strategic DDD

The Context maps patterns: Anticorruption Layer

This approach is generally useful for integrating new features to some existing legacy software, where you can treat the existing legacy software as a black box bounded context and create an ACL for the new feature.

Strategic DDD

The Context maps patterns: Anticorruption Layer

The Anticorruption Layer translate one model to another one

  • Transforms an external model from another team / bounded context / system to another internal one
  • Reduces the amount of coupling to a single layer
  • The team implementing an Anticorruption Layer is always downstream

Strategic DDD

The Context maps patterns: Shared Kernel

2 or more bounded contexts can share a common model. In design terms, the Ubiquitous Language of this shared part is common both all relevent teams. In code terms, you may have a shared library, or a service. This is generally a small codebase but difficult to maintain as its related bounded contexts develop, as the teams will tend to go on separate ways as their own bounded contexts evolve.

Strategic DDD

The Context maps patterns: Shared Kernel

Shared kernel is a subset of a domain model that two or more teams share:

  • Physically shared artefact between two or more teams
  • High degree of coupling requires a high amount of coordination between the involved teams
  • Shared kernel is no anti-pattern but use with caution

Strategic DDD

The Context maps patterns: Conformist

This relationship describes the relationship of 2 bounded context, where the upstream has no interest in supporting the downstream for whatever reason. Instead, the downstream must conform to whatever the upstream provides. This can happen when integrating a new feature with a large, existing solution that is well established; or using a set of APIs, where the downstream is not the sole customer.

Strategic DDD

The Context maps patterns: Conformist

The conformist slavishly adhreres to the upstream model:

  • Motivation: Simplicity, contracts, force or delight (for the upstream model)
  • The team implementing a Conformist is always downstream

Strategic DDD

The Context maps patterns: Customer/Supplier

This approach puts 2 bounded contexts into an upstream and downstream, where the upstream is the supplier, and has to try and meet the expectations of the customer (downstream). But the final decision of what the customer gets comes from the supplier. This typically works in an autonomous environment within the same organisation, or if the customer is the sole client of the supplier.

Strategic DDD

The Context maps patterns: Customer/Supplier

A customer-supplier development gives the downstream team some influence:

  • Downstream requirements factor into upstream planning. Therefore, the downstream team gains some influence over the priorities and tasks of the upstream team
  • Customer-Supplier is organisational
  • Mind vetoing customer and customer agains an ohs as anti-patterns

Strategic DDD

The Context maps patterns: Partnership

Partnership is about cooperative relationships between teams:

  • Establishes a process for coordinated planning of development and joint management of integration
  • Not technical at all, Partnership is plain organisational
  • Recommend for teams with depend on a Shared kernel

Strategic DDD

Strategic Refactoring

Structural Refactorings:

  • AR-2: Split Bounded Context by Features
  • AR-3: Split Bounded Context by Owner
  • AR-7: Merge Bounded Contexts
  • AR-8: Extract Shared Kernel
  • AR-9: Suspend Partnership


Source: https://contextmapper.org/docs/architectural-refactorings/

Strategic DDD

Strategic Refactoring

AR-2: Split Bounded Context by Features

Description Input Output
Splits a bounded context by grouping those aggregates together into one bounded context which are used by the same use case(s) and/or user stories (features). 1 BC n BC

Strategic DDD

Strategic Refactoring

AR-3: Split Bounded Context by Owner

Description Input Output
Splits a bounded context by grouping those aggregates together into one bounded context which belong to the same team. 1 BC n BC

Strategic DDD

Strategic Refactoring

AR-7: Merge Bounded Contexts

Description Input Output
Merges two bounded contexts together. The result is one bounded context containing all the aggregates of the two input bounded contexts. 2 BC 1 BC

Strategic DDD

Strategic Refactoring

AR-8: Extract Shared Kernel

Description Input Output
Extracts a new bounded context for the common model parts of the Shared Kernel and establishes two upstream-downstream relationship between the new and the existing Bounded Contexts. 1 Shared Kernel relationship 1 New Bounded Context and 2 new upstream-downstream relationships

Strategic DDD

Strategic Refactoring

AR-9: Suspend Partnership

Description Input Output
Suspends a Partnership relationship and replaces it with another structure how the two Bounded Context can depend on each other. The AR provides three strategies to suspend the partnership. 1 Partnership relationship Depends on the selected mode

Strategic DDD

Strategic Refactoring

Relationship Refactorings:

  • AR-10: Change Shared Kernel to Partnership
  • AR-11: Change Partnership to Shared Kernel


Source: https://contextmapper.org/docs/architectural-refactorings/

Strategic DDD

Strategic Refactoring

AR-10: Change Shared Kernel to Partnership

Description Input Output
Changes the type of a Shared Kernel relationship to a Partnership relationship. Shared Kernel relationship Partnership relationship

Strategic DDD

Strategic Refactoring

AR-11: Change Partnership to Shared Kernel

Description Input Output
Changes the type of a Partnership relationship to a Shared Kernel relationship. Partnership relationship Shared Kernel relationship

Implementing Strategic DDD

Techniques:

  • Event Storming
  • Bounded Context Canvas

Tool:

  • Context Mapper

Process:

  • Domain-Driven Design Starter Modelling Process
  • ISO-25010

Implementing Strategic DDD

Event-Storming

Implementing Strategic DDD

Event-Storming

Event storming is a workshop-based method to quickly find out what is happening in the domain. The result is expressed in sticky notes on a wide wall. The business process is "stormed out" as a series of domain events which are denoted as orange stickies.

Implementing Strategic DDD

Event-Storming

Event storming can be used as a means for business process modeling and requirements engineering. The basic idea is to bring together software developers and domain experts and learn from each other.

Implementing Strategic DDD

Example: Discovering Domain Events


Source: https://spring.io/blog/2018/04/11/event-storming-and-spring-with-a-splash-of-ddd

Implementing Strategic DDD

Example: Discovering Commands & Queries


Source: https://spring.io/blog/2018/04/11/event-storming-and-spring-with-a-splash-of-ddd

Implementing Strategic DDD

Example: Discovering Invariants


Source: https://spring.io/blog/2018/04/11/event-storming-and-spring-with-a-splash-of-ddd

Implementing Strategic DDD

Example: Discovering the bounded contexts


Source: https://spring.io/blog/2018/04/11/event-storming-and-spring-with-a-splash-of-ddd

Implementing Strategic DDD

Bounded Context Canvas

The Bounded Context Canvas is a collaborative tool for designing and documenting the design of a single bounded context.

A bounded context is a sub-system in a software architecture aligned to a part of your domain.

Source: https://github.com/ddd-crew/bounded-context-canvas

Implementing Strategic DDD

Bounded Context Canvas


Source: https://github.com/ddd-crew/bounded-context-canvas

Implementing Strategic DDD

Context mapper

Context Mapper is a modular and extensible modeling framework for Domain-driven Design (DDD) and its strategic patterns. The core component provides a DSL to create context maps featuring these DDD patterns.


Source: https://contextmapper.org/

Implementing Strategic DDD

Context mapper


Source: https://contextmapper.org/

Implementing Strategic DDD

Context mapper

  • Step 1: Capture User Requirements as Use Cases and/or User Stories
  • Step 2: Derive DDD Subdomains from the functional requirements
  • Step 3: Derive DDD Bounded Contexts (type FEATURE) from the Subdomains
  • Step 4: Derive SYSTEMs from the FEATUREs

Implementing Strategic DDD

Context mapper


Source: Source: https://github.com/ContextMapper/context-mapper-examples/tree/master/src/main/cml/insurance-example

Implementing Strategic DDD

Context mapper


Implementing Strategic DDD

Context mapper

Implementing Strategic DDD

Domain-Driven Design Starter Modelling Process


Source: https://github.com/ddd-crew/ddd-starter-modelling-process

Implementing Strategic DDD

ISO 25010


Source: https://iso25000.com/index.php/en/iso-25000-standards/iso-25010

Tactical DDD

Tactical DDD is when you define your domain models with more precision.

Tactical DDD

Concepts:

  • Value Objects
  • Entities
  • Agreggate Root
  • Repositories
  • Domain Events

Tactical DDD

Value Object

A value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.

Examples: Objects representing an amount of money or a date range

Tactical DDD

Entity

In a data model context, describes the structure of data regardless of the stored form.

Tactical DDD

Agreggate Root

An Agreggate is a cluster of associated objects that we treat as a unit.

Source: Domain-Driven Design, Eric Evans

Tactical DDD

Agreggate Root

Aggregates are the basic element of transfer of data storage - you request to load or save whole aggregates.

Source: https://martinfowler.com/bliki/DDD_Aggregate.html

Tactical DDD

Agreggate Root

An aggregate will have one of its component objects be the aggregate root. Any references from outside the aggregate should only go to the aggregate root. The root can thus ensure the integrity of the aggregate as a whole.

Source: https://martinfowler.com/bliki/DDD_Aggregate.html

Tactical DDD

Repositories

Query access to aggregates expressed in the ubiquitous language

For each type of aggregate that needs global access, create a service that can provide the collection of all objects of that aggregate’s root type. Provide methods to add and remove objects, which will encapsulate the actual insertion or removal of data in the data store. Provide methods that select objects based on criteria meaningful to domain experts.

Tactical DDD

Example:

Source: https://khalilstemmler.com/articles/typescript-domain-driven-design/aggregate-design-persistence/

Tactical DDD

Example:

Source: https://kalele.io/modeling-aggregates-with-ddd-and-entity-framework/

Tactical DDD

Domain Events

A domain event is a full-fledged part of the domain model, a representation of something that happened in the domain. Ignore irrelevant domain activity while making explicit the events that the domain experts want to track or be notified of, or which are associated with state change in the other model objects.

Implementing Tactical DDD

Patterns:

  • Onion architecture

Libraries:

  • ArchUnit
  • Spring Data JDBC

Implementing Tactical DDD

Onion Architecture

The Hexagonal-like Architectures:

  • The first Hexagonal Architecture, originally called Ports and Adapters, was published in 2005 by Alistair Cockburn;
  • An alternative to it called Onion Architecture was published in 2008 by Jeffrey Palermo;
  • An alternative to it called The Clean Architecture was published in 2012 by Robert C. Martin.

Implementing Tactical DDD

Onion Architecture

The Onion Architecture is an Architectural Pattern that enables maintainable and evolutionary enterprise systems.

Source: https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/

Implementing Tactical DDD

Onion Architecture

Implementing Tactical DDD

Onion Architecture

Domain layer:

  • The domain package is the core of the application. It consists of two parts. The domainModels packages contain the domain entities. The packages in domainServices contains services that use the entities in the domainModel packages.

Implementing Tactical DDD

Onion Architecture

Application layer:

  • The applicationServices packages contain services and configuration to run the application and use cases. It can use the items of the domain package but there must not be any dependency from the domain to the application packages.

Implementing Tactical DDD

Onion Architecture

Infrastructure layer:

  • The adapter package contains logic to connect to external systems and/or infrastructure. No adapter may depend on another adapter. Adapters can use both the items of the domain as well as the application packages. Vice versa, neither the domain nor the application packages must contain dependencies on any adapter package.

Implementing Tactical DDD

Onion Architecture

jmolecules-onion-architecture: Layers:

Source: https://speakerdeck.com/kiyotakeshi69/spring-fest-2020-express-ddd-using-jpa-x-jmolecules

Implementing Tactical DDD

Onion Architecture

Advantages:

  • It provides better maintainability as all the codes depend on layers or the center.
  • It provides better testability as the unit test can be created for separate layers.
  • It develops a loosely coupled application as the outer layer of the application always communicates with the inner layer via interfaces.

Implementing Tactical DDD

Onion Architecture

Advantages:

  • Domain entities are core and center part.
  • The internal layers never depend on the external layer.

Implementing Tactical DDD

Onion Architecture

How to ensure that your team apply Onion architecture in an effective way?

🤔

Implementing Tactical DDD

ArchUnit

ArchUnit is a free, simple and extensible library for checking the architecture of your Java code using any plain Java unit test framework.

Website: https://www.archunit.org/

Implementing Tactical DDD

ArchUnit



< dependency>
    < groupId>com.tngtech.archunit< /groupId>
    < artifactId>archunit< /artifactId>
    < version>${archunit.version}< /version>
    < scope>test< /scope>
< /dependency>
< dependency>
    < groupId>com.tngtech.archunit< /groupId>
    < artifactId>archunit-junit5-engine< /artifactId>
    < version>${archunit.version}< /version>
< /dependency>
< dependency>
    < groupId>com.tngtech.archunit< /groupId>
    < artifactId>archunit-junit5< /artifactId>
    < version>${archunit.version}< /version>
< /dependency>

                    
Maven: https://mvnrepository.com/artifact/com.tngtech.archunit

Implementing Tactical DDD

ArchUnit

Example:


@AnalyzeClasses(
    packages = "com.ddd.balance",
    importOptions = {ImportOption.DoNotIncludeTests.class})
public class BalanceArchitectureOnionTest {

    @ArchTest
    static final ArchRule follow_onion_architecture_structure =
            onionArchitecture()
                    .domainModels("..domain.model..")
                    .domainServices("..domain.service..")
                    .applicationServices("..application..")
                    .adapter("rest", "..infrastructure.rest..");

}
                    

Implementing Tactical DDD

ArchUnit

Implementing Tactical DDD

ArchUnit

You can apply TDD at architectural level with ArchUnit

Implementing Tactical DDD

Spring Data JDBC

Spring Data JDBC, part of the larger Spring Data family, makes it easy to implement JDBC based repositories.

Library: https://spring.io/projects/spring-data-jdbc

Implementing Tactical DDD

Spring Data JDBC

Spring Data repositories are inspired by the repository as described in the book Domain Driven Design by Eric Evans. One consequence of this is that you should have a repository per Aggregate Root. Aggregate Root is another concept from the same book and describes an entity which controls the lifecycle of other entities which together are an Aggregate. An Aggregate is a subset of your model which is consistent between method calls to your Aggregate Root.

Implementing Tactical DDD

Spring Data JDBC

  • Aggregates are Boundaries of integrity
  • Transactional consistency inside
  • Eventual consistency between aggregates

Implementing Tactical DDD

Spring Data JDBC

Implementing Tactical DDD

Spring Data JDBC

Jmolecules

Architectural abstractions for Java.

Jmolecules

Maven dependencies:



< dependency>
    < groupId>org.jmolecules< /groupId>
    < artifactId>jmolecules-ddd< /artifactId>
    < version>${jmolecules.version}< /version>
< /dependency>
< dependency>
    < groupId>org.jmolecules< /groupId>
    < artifactId>jmolecules-onion-architecture< /artifactId>
    < version>${jmolecules.version}< /version>
< /dependency>


                    
Maven: https://mvnrepository.com/artifact/org.jmolecules

Jmolecules

Goals:

  • Express that a piece of code (a package, class, or method) implements an architectural concept.
  • Make it easy for the human reader to determine what kind of architectural concepts a given piece of code is.
  • Allow tool integration (to do interesting stuff like generating persistence or static architecture analysis to check for validations of the architectural rules.)

Jmolecules

The library is organized in the following modules:

  • jmolecules-ddd
  • jmolecules-architecture
  • jmolecules-events

Maven: https://mvnrepository.com/artifact/org.jmolecules

Jmolecules

jmolecules-ddd:

Github: https://github.com/xmolecules/jmolecules/tree/main/jmolecules-ddd

Jmolecules

jmolecules-ddd: Annotations to define Domain-Driven Design building blocks.

Github: https://github.com/xmolecules/jmolecules/tree/main/jmolecules-ddd

Jmolecules

jmolecules-ddd:

Jmolecules

jmolecules-architecture:

  • jmolecules-cqrs-architecture
  • jmolecules-layered-architecture
  • jmolecules-onion-architecture

Github: https://github.com/xmolecules/jmolecules/tree/main/jmolecules-architecture

Jmolecules

jmolecules-onion-architecture:

Jmolecules

jmolecules-onion-architecture:

Jmolecules

jmolecules-onion-architecture:

Source: https://speakerdeck.com/kiyotakeshi69/spring-fest-2020-express-ddd-using-jpa-x-jmolecules

Jmolecules

jmolecules-onion-architecture: Layers:

Source: https://speakerdeck.com/kiyotakeshi69/spring-fest-2020-express-ddd-using-jpa-x-jmolecules

Who to follow about DDD

  • @ericevans0
  • @VaughnVernon
  • @ziobrando
  • @adymitruk
  • @EventModeling
  • @Context_Mapper
  • @stefankapferer
  • @hschwentner
  • @ntcoding

Who to follow about DDD

  • @archtests
  • @xmolecules
  • @odrotbohm
  • @jensschauder
  • @bitboss
  • @spirnbaum
  • @jqassistant

References

Books

References

Articles

References

Articles

References

Talks

🙏 🙏 🙏

Thanks