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 and choose it as AppFlowy 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:
Application Layer:
Domain Layer:
Infrastructure 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 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
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.
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.
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 โ
โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
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)
โโโโโโโโโโโโโ State โโโโโโโโโโโโโ
โ โ
โผ Bloc โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโผโโโโโโโโโโ
โโโโโโโโโถโ Widget โ โ โโโโโโโโโโ โโดโโโโโโโโ โ
โโโโโโโโโโโโโโโ โ โ Event โ โ State โ โ
User interaction โ โ โโโโโโโโโโ โโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโ
โ โฒ
โ โ
โโโโโโโโโโโ Event โโโโโโโโโโโโโ
The bloc
process the events using the services provided by the Domain
layer.
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 โ
โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Responsibility of Unit of Work 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.
Handling operations (INSERT, UPDATE and DELETE) with SQLite to persis the data.
Saving or querying the data in the cloud to finish the operation.