|
@@ -0,0 +1,243 @@
|
|
|
+
|
|
|
+# ๐ Domain Driven Design
|
|
|
+
|
|
|
+For many architects, the process of data modeling is driven by intuition. However, there are well-formulated methodologies
|
|
|
+for approaching it more formally. I recommend the [Domain-Driven Design](https://en.wikipedia.org/wiki/Domain-driven_design)
|
|
|
+and choose it as AppFlowy architecture.
|
|
|
+
|
|
|
+## ๐ฅ Layered architecture
|
|
|
+The most common architecture pattern is the layered architecture pattern, known as the n-tier architecture pattern.
|
|
|
+Partition the software into `layers` to reduce the complexity. Each layer of the layered architecture pattern has a
|
|
|
+specific role and responsibility.`DDD` consists of four layers.
|
|
|
+
|
|
|
+```
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโถ
|
|
|
+ โ Presentation Layer โโโโ Dependency
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
|
+ โ โ
|
|
|
+ โผ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
|
+ โ Application Layer โ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
|
+ โ โ
|
|
|
+ โผ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
|
+ โ Domain Layer โโโโ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โฒ
|
|
|
+ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ Infrastructure Layer โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+```
|
|
|
+
|
|
|
+**Presentation Layer**:
|
|
|
+* Responsible for presenting information to the user and interpreting user commands.
|
|
|
+* Consists of Widgets and also the state of the Widgets.
|
|
|
+
|
|
|
+**Application Layer**:
|
|
|
+* Defines the jobs the software is supposed to do. (Shouldn't find any UI code or network code)
|
|
|
+* Coordinates the application activity and delegates work to the next layer down.
|
|
|
+* It doesn't contain any complex business logic but the basic validation on the user input before
|
|
|
+ passing to the other layer.
|
|
|
+
|
|
|
+**Domain Layer**:
|
|
|
+* Responsible for representing concepts of the business.
|
|
|
+* Manages the business state or delegated to the infrastructure layer.
|
|
|
+* Self contained and it doesn't depend on any other layers. Domain should be well isolated from the
|
|
|
+ other layers.
|
|
|
+
|
|
|
+**Infrastructure Layer**:
|
|
|
+
|
|
|
+* Provides generic technical capabilities that support the higher layers. It deals with APIs, persistence and network, etc.
|
|
|
+* Implements the repository interface and hiding the complexity of the Domain layer.
|
|
|
+
|
|
|
+As you see, the `Complexity` and `Abstraction` of these layers are depicted in this diagram. Software system are composed in layers,
|
|
|
+where higher layers use the facilities provided by lower layers. Each layer provides a different abstraction from the layer above
|
|
|
+and below it. As a developer, we should pull the complexity downwards. Simple interface and powerful implementation(Think about the
|
|
|
+[open](https://man7.org/linux/man-pages/man2/open.2.html) function). Another way of expressing this idea is that it is more important
|
|
|
+for a module to have a simple interface than a simple implementation.
|
|
|
+
|
|
|
+
|
|
|
+```
|
|
|
+ โฒ
|
|
|
+ โ
|
|
|
+ Level of โโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ Abstraction โ Presentation โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโดโโโโโโโโ
|
|
|
+ โ Application โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโ
|
|
|
+ โ Domain โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโ
|
|
|
+ โ Infrastructure โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโถ
|
|
|
+ Complexity
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
+### Data Model
|
|
|
+DDD classifies data as referenceable objects, or entities, and non-referenceable objects, or value objects. Let's introduces
|
|
|
+some terminologies from DDD.
|
|
|
+
|
|
|
+**Entity**
|
|
|
+
|
|
|
+`Entities` are referenceable because they carry an identity which allows us to reference them. e.g. user, order, book, etc.
|
|
|
+You can use `entities` to express your business model and encapsulate them into Factory that provides simple API interface
|
|
|
+to create Entities.
|
|
|
+
|
|
|
+
|
|
|
+**Value Object**
|
|
|
+
|
|
|
+`Value Object` can't be referenced. They can be only included into entities and serve as attributes. Value objects could be
|
|
|
+simple and treat as immutable. e.g. email, phone number, name, etc.
|
|
|
+
|
|
|
+**Aggregate**
|
|
|
+
|
|
|
+`Entity` or `Value object` can be grouped into aggregates. Aggregates can simplify the model by accessing the entire aggregate.
|
|
|
+For instance, Table has lots of row. Each row using the table_id to reference to the
|
|
|
+table. TableAggregate includes two entities: Table and the Row.
|
|
|
+
|
|
|
+```
|
|
|
+ TableAggregate
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ
|
|
|
+ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
|
+ โ โstruct Table { โ โstruct Row { โ โ
|
|
|
+ โ โ id: String, โ โ table_id: String, โ โ
|
|
|
+ โ โ desc: String, โโโถโโโโโโโโ} โ โ
|
|
|
+ โ โ} โ โ โ โ
|
|
|
+ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
|
|
|
+ โ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+```
|
|
|
+
|
|
|
+**Service**
|
|
|
+
|
|
|
+When a significant process of transformation in the domain is not a natural responsibility of an `Entity` or `Value object`, add
|
|
|
+an operation to the model as standalone interface declared as a Service. For instance: The `Value object`, EmailAddress,
|
|
|
+uses the function `validateEmailAddress` to verify the email address is valid or not. `Service` exists in Application, Domain and
|
|
|
+Infrastructure.
|
|
|
+
|
|
|
+```
|
|
|
+class EmailAddress {
|
|
|
+ final Either<Failure<String>, String> value;
|
|
|
+
|
|
|
+ factory EmailAddress(String? input) {
|
|
|
+ return EmailAddress._(
|
|
|
+ validateEmailAddress(input),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ const EmailAddress._(this.value);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+Either<Failure<String>, String> validateEmailAddress(String? input) {
|
|
|
+ ...
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**Repository**
|
|
|
+
|
|
|
+Repository offer an interface to retrieve and persist aggregates and entities. They hide the database or network details from the domain.
|
|
|
+The Repository interfaces are declared in the Domain Layer, but the repositories themselves are implemented in the Infrastructure Layer.
|
|
|
+You can replace the interface implementation without impacting the domain layer. For instance:
|
|
|
+
|
|
|
+```
|
|
|
+// Interface:
|
|
|
+abstract class AuthInterface {
|
|
|
+ ...
|
|
|
+}
|
|
|
+
|
|
|
+// Implementation
|
|
|
+class AuthRepository implements AuthInterface {
|
|
|
+ ...
|
|
|
+}
|
|
|
+```
|
|
|
+> More often than not, the repository interface can be divided into sub-repository in order to reduce the complexity.
|
|
|
+
|
|
|
+### Relation
|
|
|
+The diagram below is a navigational map. It shows the patterns that form the building blocks of Domain Driven Design and how they relate to each other.
|
|
|
+](imgs/domain_model_relation.png)
|
|
|
+
|
|
|
+
|
|
|
+## ๐ฅ Operation Flow
|
|
|
+
|
|
|
+```
|
|
|
+
|
|
|
+ presentation โ Application domain Infrastructure
|
|
|
+ โ โ
|
|
|
+ 7 Data Model
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โ โ โโโโโโโโโโโโโโโ โ โ Network Service โ
|
|
|
+ โผ Bloc โ โ โ โ Aggregate โ โ โ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโดโโโโโโ โ โโโโโโโโโโโโโโโ โ โฒ
|
|
|
+โโโโโโโโโถ Widget โ โ โโโโโโโโโโ โโโโโโโโโโ โ 2 โ โโโโโโโโโโ โ โ โ 6
|
|
|
+ โโโโโโโโโโโโโโโ โ โ โ Event โ โ State โ โโโโโโฌโโโโถโ โ Entity โ โ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+User โ โ โโโโโโโโโโ โโโโโโโโโโ โ โ โ โ โโโโโโโโโโ โ โ โ Persistence Service โ
|
|
|
+interaction โ โ โโโโโโโโฒโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โ โ โ โ Value Object โ โ โ โฒ
|
|
|
+ โโโโโโโโโโโโผโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโโ โ โ 5
|
|
|
+ 1 โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โcontain โ Unit of Work โ
|
|
|
+ โ โ โโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โ Service โ โฒ
|
|
|
+ โ โ โโโโโโโโโโโโโโโโโโโโโโ โ โ
|
|
|
+ โ โ โ 4
|
|
|
+ โ โ Repository โ โ
|
|
|
+ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ 3 โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
|
|
|
+ โ โโโโโค Interface โโโโโถ Implementation โ
|
|
|
+ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
|
|
|
+ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
+1. Widget accepts user interaction and transfers the interactions into specific events. The events will be send to the Application layer,
|
|
|
+ handled by the specific `bloc`. The `bloc` send the states changed by the events back to the widget, and finally the `Widget` update
|
|
|
+ the UI according to the state. The pattern is depicted in this diagram. (More about the flutter [bloc](https://bloclibrary.dev/#/coreconcepts?id=bloc))
|
|
|
+ ```
|
|
|
+ โโโโโโโโโโโโโ State โโโโโโโโโโโโโ
|
|
|
+ โ โ
|
|
|
+ โผ Bloc โ
|
|
|
+ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโผโโโโโโโโโโ
|
|
|
+ โโโโโโโโโถโ Widget โ โ โโโโโโโโโโ โโดโโโโโโโโ โ
|
|
|
+ โโโโโโโโโโโโโโโ โ โ Event โ โ State โ โ
|
|
|
+ User interaction โ โ โโโโโโโโโโ โโโโโโโโโโ โ
|
|
|
+ โ โโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โฒ
|
|
|
+ โ โ
|
|
|
+ โโโโโโโโโโโ Event โโโโโโโโโโโโโ
|
|
|
+
|
|
|
+ ```
|
|
|
+
|
|
|
+2. The `bloc` process the events using the services provided by the `Domain` layer.
|
|
|
+ 1. Convert DTO (Data Transfer Object) to domain model and Domain Model to DTO.
|
|
|
+ 2. Domain model is the place where all your business logics, business validation and business behaviors will be implemented.
|
|
|
+ The Aggregate Roots, Entities and Value Objects will help to achieve the business logic.
|
|
|
+3. Calling repositories to perform additional operations. The repositories interfaces are declared in `Domain`, implemented in `Infrastructure`.
|
|
|
+ You can reimplement the repository interface with different languages, such as `Rust`, `C++` or `Flutter`. etc.
|
|
|
+ ```
|
|
|
+ Domain Infrastructure
|
|
|
+
|
|
|
+ Repository A โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
|
|
|
+ โ Interface โโโผโโถ Implementation โ
|
|
|
+ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ Repository B โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
|
|
|
+ โ Interface โโโผโโถ Implementation โ
|
|
|
+ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
|
|
|
+ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
+ ```
|
|
|
+4. Responsibility of [Unit of Work](https://martinfowler.com/eaaCatalog/unitOfWork.html) is to maintain a list of objects affected by a
|
|
|
+ business transaction and coordinates the writing out of changes and the resolution of concurrency problems((No intermediate state)).
|
|
|
+ If any one persistence service fails, the whole transaction will be failed so, roll back operation will be called to put the object
|
|
|
+ back in initial state.
|
|
|
+
|
|
|
+5. Handling operations (INSERT, UPDATE and DELETE) with SQLite to persis the data.
|
|
|
+6. Saving or querying the data in the cloud to finish the operation.
|