diff --git a/.gitignore b/.gitignore index 67f6890827..8260299e3f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,4 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk -/rust-lib/flowy-ast -/rust-lib/flowy-derive \ No newline at end of file +/rust-lib \ No newline at end of file diff --git a/README.md b/README.md index b0514bbabc..b425ab0c8f 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,22 @@ -# AppFlowy client - -* The Big Picture - * Introduce - * Goals - * Cross-platform - -* Getting started - * Build - * Running - -* Contributing - * First steps - * Opening issues - * Participating in discussions - * Finding something to work on - * Open your PR - * Review Process - * Getting more involved - * Organization membership - * Contributor - * Maintainer - -## The Big Picture - -### Introduce - -### Goals - -### Cross-platform +[![Version](https://img.shields.io/badge/rustc-1.46+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html) +![Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -## Getting Started -Read the [architecture doc](doc/architecture.md) before you started. +# what is AppFlowy? + +## Features + +## Documentation + +* [**Getting Started**](doc/getting_started.md) +* [**Roadmap**](doc/roadmap.md) +* [**Deep Dive AppFlowy**](doc/architecture.md) ## Contributing -Read the [architecture doc](doc/architecture.md) before you started. +Read the [Contributing Doc](doc/contribute.md) before you want to contribute. +## Social Media +* Slack + +## License +AppFlowy is under the Apache 2.0 license. See the [LICENSE](/LICENSE) file for details. diff --git a/doc/about app flowy.md b/doc/about app flowy.md new file mode 100644 index 0000000000..0e3d959cf3 --- /dev/null +++ b/doc/about app flowy.md @@ -0,0 +1 @@ +[WIP] \ No newline at end of file diff --git a/doc/architecture.md b/doc/architecture.md index 1575f42a54..eb294c9de1 100644 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -1,231 +1,19 @@ -# AppFlowy Architecture -This documentation introduces the Domain-Driven Design and the design of AppFlowy. Feel free to skip the first part -if you know what Domain-Driven Design is. -* Basic Concepts - * Layered architecture - * Domain Driven Design +# πŸ₯³ AppFlowy System Design + +* Goals of the System +* Some Design Considerations +* High Level Design +* Component Design + +## 🎯 Goals of the System + +## πŸ€” Some Design Considerations +## πŸ“œ High Level Design +## πŸ“š Component Design -* AppFlowy Design - * Overview - * Operation Flow - * Create - * Read - * Update - * Delete - -# Basic Concepts - -## 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. - -## 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. - -DDD consists of four layers. - -``` - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” ─────────▢ - β”‚ Presentation Layer │──┐ Dependency - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ β”‚ - β–Ό β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ - β”‚ Application Layer β”‚ β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ β”‚ - β–Ό β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ - β”‚ Domain Layer β”‚β—€β”€β”˜ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β–² - β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Infrastructure Layer β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - - β–² - β”‚ - Level of β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - Abstraction β”‚ Presentation β”‚ - β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Application β”‚ - β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Domain β”‚ - β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Infrastructure β”‚ - └──────────────────────────────────────────────┴─────▢ - Complexity -``` - -**Presentation**: -* Responsible for presenting information to the user and interpreting user commands. -* Consists of Widgets and also the state of the Widgets. - -**Application**: -* 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**: -* 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**: - -This layer acts as a supporting library for all the other layers. It deals with APIs, -databases and network, etc. - -DDD classifies data as referenceable objects, or entities, and non-referenceable objects, or values. - -**Entity** - -user, order, book, table. They are referenceable because they carry an identity which -allows us to reference them. - -**Value** - -email, phone number, name, age, description. They can't be referenced. They can be only included into -entities and serve as attributes. Values could be simple or could be composite. - -**Aggregate** - -entities can be grouped into aggregates. Aggregates can simplify the model by accessing th 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, │◀▢───────│} β”‚ β”‚ - β”‚ β”‚} β”‚ β”‚ β”‚ β”‚ - β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -DDD also introduces `Service` and `Repository`. - -**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, String> value; - - factory EmailAddress(String? input) { - return EmailAddress._( - validateEmailAddress(input), - ); - } - - const EmailAddress._(this.value); -} +### πŸ“• Component 1 +### πŸ“— Component 2 +### πŸ“˜ Component 3 +### πŸ“™ Component 3 -Either, String> validateEmailAddress(String? input) { - ... -} -``` - -**Repository** - -Repository offer an interface to retrieve and persist aggregates. 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. - -## AppFlowy Design - -The AppFlowy Client consists of lots of modules. Each of them follows the DDD design pattern and using [dependency injection](https://levelup.gitconnected.com/dependency-injection-in-swift-bc16d66b038b) -to communication with other module. - -``` - - Client - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ β”‚ - β”‚ Module A Module B Module C β”‚ - β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ - β”‚ β”‚ presentation β”‚ Dependency β”‚ presentation β”‚ β”‚ presentation β”‚ β”‚ - β”‚ β”‚ β”‚ Injection β”‚ β”‚ β”‚ β”‚ β”‚ - β”‚ β”‚ application β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ application β”‚ β”‚ application β”‚ β”‚ - β”‚ β”‚ │◀───────────────│ β”‚ β”‚ β”‚ β—‰ β—‰ β—‰ β”‚ - β”‚ β”‚ domain β”‚ β”‚ domain β”‚ β”‚ domain β”‚ β”‚ - β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ - β”‚ β”‚ Infrastructure β”‚ β”‚ Infrastructure β”‚ β”‚ Infrastructure β”‚ β”‚ - β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ β–² β”‚ β”‚ - β”‚ β”‚ Dependency Injection β”‚ β”‚ - β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -Let's dig it how can I construct each module. I take `User` module for demonstration. - -``` - - presentation Application domain Infrastructure - - β”‚ - β”‚ β”‚ - 7 Data Model - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β–Άβ”‚ Repository implementation β”‚ - β–Ό Bloc β”‚ 2.1 β”‚ β”‚ Aggregate β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β” β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ 4 -β”‚ Widget β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β–Ό -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ Event β”‚ β”‚ State β”‚ │───┬────▢│ β”‚ Entity β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Unit of Work β”‚ - β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Value Object β”‚ β”‚ β”‚ β”‚ β”‚ 5 - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–Ό - 1 β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ β”‚ β—ˆ β”‚ β”‚ Persistence Service β”‚ - β”‚ β”‚ β”‚ contain β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ - β”‚ β”‚ β”‚ Service β”‚ β”‚ β”‚ - β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ 2.2 β”‚ β”‚ - β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ - β”‚ └───▢│ Repository interface β”‚ β”‚ β”‚ - β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ - β”‚ β”‚ β”‚ β”‚ - β”‚ β”‚ 3 β”‚ - β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”˜ -``` - - -1. Send event using the bloc. The bloc does not know about the `Widget`. It should communicate through events. -2. The bloc dispatching the event to the appropriate handler of the `Domain` - 1. Conversion between, DTO (Data Transfer Object) to domain model and Domain Model to DTO. - 2. Handling the business logic using the repository interface -3. Repository are used to store the domain model data and calls respective service to finish the jobs. -# Event-Driven \ No newline at end of file diff --git a/doc/contribute.md b/doc/contribute.md new file mode 100644 index 0000000000..e0f57bdaf8 --- /dev/null +++ b/doc/contribute.md @@ -0,0 +1,12 @@ +[WIP] +* Contributing + * First steps + * Opening issues + * Participating in discussions + * Finding something to work on + * Open your PR + * Review Process + * Getting more involved + * Organization membership + * Contributor + * Maintainer \ No newline at end of file diff --git a/doc/domain driven design.md b/doc/domain driven design.md new file mode 100644 index 0000000000..2bad671c86 --- /dev/null +++ b/doc/domain driven design.md @@ -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, String> value; + + factory EmailAddress(String? input) { + return EmailAddress._( + validateEmailAddress(input), + ); + } + + const EmailAddress._(this.value); +} + + +Either, 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. +![[image from here](http://uniknow.github.io/AgileDev/site/0.1.8-SNAPSHOT/parent/ddd/core/building_blocks_ddd.html)](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. \ No newline at end of file diff --git a/doc/getting_started.md b/doc/getting_started.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/doc/imgs/ddd_big_pic.png b/doc/imgs/ddd_big_pic.png deleted file mode 100644 index 1f05b56df1..0000000000 Binary files a/doc/imgs/ddd_big_pic.png and /dev/null differ diff --git a/doc/imgs/domain_model_relation.png b/doc/imgs/domain_model_relation.png new file mode 100644 index 0000000000..dddf430f27 Binary files /dev/null and b/doc/imgs/domain_model_relation.png differ diff --git a/doc/roadmap.md b/doc/roadmap.md new file mode 100644 index 0000000000..0e3d959cf3 --- /dev/null +++ b/doc/roadmap.md @@ -0,0 +1 @@ +[WIP] \ No newline at end of file diff --git a/doc/why flutter and rust.md b/doc/why flutter and rust.md new file mode 100644 index 0000000000..0e3d959cf3 --- /dev/null +++ b/doc/why flutter and rust.md @@ -0,0 +1 @@ +[WIP] \ No newline at end of file