sentenz / convention

General articles, conventions, and guides.
https://sentenz.github.io/convention/
Apache License 2.0
4 stars 2 forks source link

Create an article about `Software Architectural Patterns` #209

Open sentenz opened 1 year ago

sentenz commented 1 year ago

Software Architectural Patterns

Software architectural patterns are high-level design templates or solutions that provide a structured approach for organizing and designing software systems. Architectural patterns offer proven solutions to recurring design problems and help architects and developers build scalable, maintainable, and robust software applications.

1. Category

NOTE Architectural patterns are not rigid templates but guidelines to be tailored to the specific requirements and context of each project. Adapt the patterns as needed, considering the unique characteristics and constraints of the system being developed.

Distribution Patterns

1.1. MVC

MVC (Model-View-Controller) is a widely used architectural pattern for designing and developing software applications. It separates the concerns of data management, user interface, and application logic by dividing the application into three interconnected components: the Model, the View, and the Controller.

The MVC pattern has been adopted in various application frameworks and platforms, including web development frameworks (e.g., Ruby on Rails, ASP.NET MVC), desktop application frameworks (e.g., JavaFX), and mobile application frameworks (e.g., iOS, Android). It provides a structured and maintainable way to design and organize software applications.

Elements of MVC:

  1. Model: The Model represents the data and the business logic of the application. It encapsulates the data structure, access methods, and rules for manipulating and managing the data. The Model component is responsible for maintaining the consistency and integrity of the data.

  2. View: The View is responsible for presenting the user interface to the users. It displays the data from the Model in a format that is understandable and visually appealing to the users. The View component is passive and does not contain any business logic; it simply renders the data provided by the Model.

  3. Controller: The Controller acts as an intermediary between the Model and the View. It receives input from the users through the View and initiates appropriate actions in the Model. It also listens for changes in the Model and updates the View accordingly. The Controller contains the application logic and coordinates the interaction between the Model and the View.

Benefits of MVC:

1.2. MVP

1.3. MVVM

Vertical Slice Architecture

N-Tier Architecture

Two-Tier Architecture
Three-Tier Architecture
Four-Tier Architecture
Five-Tier Architecture
Multi-Tier Architecture

Multi-Tier Architecture (N > 5)

1.4. Layered Architecture

1.5. Microservices

1.6. Clean Architecture

project_root/
├── src/
│   ├── core/        # Domain layer (independent of frameworks)
│   │   ├── entities/   # Domain entities (models)
│   │   ├── valueobjects/ # Domain value objects
│   │   ├── usecases/     # Application business logic
│   │   ├── repositories/  # Interfaces for data access
│   │   └── ...          # Other domain-related subfolders
│   ├── infra/        # Infrastructure layer (specific implementations)
│   │   ├── databases/    # Database access (SQL, NoSQL, etc.)
│   │   ├── networks/     # Network communication (APIs, etc.)
│   │   ├── ui/           # UI frameworks (Android, iOS, web, etc.)
│   │   └── ...          # Other infrastructure-related subfolders
│   └── presentation/  # Presentation layer (view models, controllers)
│       ├── android/     # Android specific UI implementation
│       ├── ios/          # iOS specific UI implementation
│       ├── web/           # Web specific UI implementation
│       └── ...          # Other UI implementations
├── test/            # Unit and integration tests
│   └── ...
└── ...              # Other project files (build scripts, configuration)

Notes:

├── app
│   ├── controllers
│   │   ├── auth_controller.py
│   │   ├── product_controller.py
│   │   └── user_controller.py
│   ├── models
│   │   ├── auth.py
│   │   ├── product.py
│   │   └── user.py
│   ├── schemas
│   │   ├── auth_schema.py
│   │   ├── product_schema.py
│   │   └── user_schema.py
│   ├── services
│   │   ├── auth_service.py
│   │   ├── product_service.py
│   │   └── user_service.py
│   └── utils
│       ├── config.py
│       ├── database.py
│       ├── exceptions.py
│       └── validators.py
├── domain
│   ├── entities
│   │   ├── auth_entity.py
│   │   ├── product_entity.py
│   │   └── user_entity.py
│   ├── interfaces
│   │   ├── auth_repository.py
│   │   ├── product_repository.py
│   │   └── user_repository.py
│   └── use_cases
│       ├── auth_use_case.py
│       ├── product_use_case.py
│       └── user_use_case.py
├── infrastructure
│   ├── adapters
│   │   ├── auth_adapter.py
│   │   ├── product_adapter.py
│   │   └── user_adapter.py
│   ├── drivers
│   │   ├── email_driver.py
│   │   ├── logger_driver.py
│   │   └── storage_driver.py
│   └── repositories
│       ├── auth_repository_impl.py
│       ├── product_repository_impl.py
│       └── user_repository_impl.py
├── tests
│   ├── conftest.py
│   ├── test_auth.py
│   ├── test_product.py
│   └── test_user.py
├── .gitignore
├── README.md
├── requirements.txt
└── run.py

1.7. Event-Driven Architecture

1.8. Hexagonal Architecture (Ports and Adapters)

project
├── core
│   ├── domain
│   │   ├── entities
│   │   │   └── ... (domain specific entities)
│   │   ├── events
│   │   │   └── ... (domain events)
│   │   ├── exceptions
│   │   │   └── ... (domain exceptions)
│   │   ├── usecases
│   │   │   └── ... (domain use cases)
│   │   └── valueobjects
│   │       └── ... (domain value objects)
│   ├── ports
│   │   ├── inbound
│   │   │   └── ... (inbound ports - interfaces for application logic)
│   │   └── outbound
│   │       └── ... (outbound ports - interfaces for external interactions)
│   └── services
│       └── ... (domain specific services)
├── adapters
│   ├── inbound
│   │   ├── api         (REST API adapter)
│   │   │   └── ... (other inbound adapters - console, message queue, etc.)
│   └── outbound
│       ├── database    (database adapter)
│       └── ... (other outbound adapters - cache, external services)
└── tests
    ├── core
    │   ├── ... (unit tests for domain logic)
    └── adapters
        ├── ... (integration tests for adapters)

Key Components:

/project
├── README.md
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   ├── com.example.hexagonal
│   │   │   │   ├── application
│   │   │   │   │   ├── ports
│   │   │   │   │   │   ├── in
│   │   │   │   │   │   │   ├── BookService.java
│   │   │   │   │   │   │   └── UserService.java
│   │   │   │   │   │   └── out
│   │   │   │   │   │       ├── BookRepository.java
│   │   │   │   │   │       └── UserRepository.java
│   │   │   │   │   └── services
│   │   │   │   │       ├── BookServiceImpl.java
│   │   │   │   │       └── UserServiceImpl.java
│   │   │   │   ├── domain
│   │   │   │   │   ├── model
│   │   │   │   │   │   ├── Book.java
│   │   │   │   │   │   └── User.java
│   │   │   │   │   └── validation
│   │   │   │   │       ├── BookValidator.java
│   │   │   │   │       └── UserValidator.java
│   │   │   │   └── infrastructure
│   │   │   │       ├── adapters
│   │   │   │       │   ├── in
│   │   │   │       │   │   ├── web
│   │   │   │       │   │   │   ├── BookController.java
│   │   │   │       │   │   │   └── UserController.java
│   │   │   │       │   │   └── persistence
│   │   │   │       │   │       ├── BookEntity.java
│   │   │   │       │   │       ├── BookMapper.java
│   │   │   │       │   │       ├── UserEntity.java
│   │   │   │       │   │       └── UserMapper.java
│   │   │   │       │   └── out
│   │   │   │       │       ├── BookRepositoryImpl.java
│   │   │   │       │       └── UserRepositoryImpl.java
│   │   │   │       └── config
│   │   │   │           ├── DatabaseConfig.java
│   │   │   │           └── WebConfig.java
│   │   │   └── com.example.hexagonal.infrastructure.config
│   │   │       └── ApplicationConfig.java
│   │   └── resources
│   │       ├── application.properties
│   │       └── logback.xml
│   └── test
│       ├── java
│       │   └── com.example.hexagonal
│       │       ├── application
│       │       │   ├── ports
│       │       │   │   ├── in
│       │       │   │   │   ├── BookServiceTest.java
│       │       │   │   │   └── UserServiceTest.java
│       │       │   │   └── out
│       │       │   │       ├── BookRepositoryTest.java
│       │       │   │       └── UserRepositoryTest.java
│       │       │   └── services
│       │       │       ├── BookServiceImplTest.java
│       │       │       └── UserServiceImplTest.java
│       │       ├── domain
│       │       │   ├── model
│       │       │   │   ├── BookTest.java
│       │       │   │   └── UserTest.java
│       │       │   └── validation
│       │       │       ├── BookValidatorTest.java
│       │       │       └── UserValidatorTest.java
│       │       └── infrastructure
│       │           ├── adapters
│       │           │   ├── in
│       │           │   │   ├── web
│       │           │   │   │   ├── BookControllerTest.java
│       │           │   │   │   └── UserControllerTest.java
│       │           │   │   └── persistence
│       │           │   │       ├── BookEntityTest.java
│       │           │   │       ├── BookMapperTest.java
│       │           │   │       ├── UserEntityTest.java
│       │           │   │       └── UserMapperTest.java
│       │           │   └── out
│       │           │       ├── BookRepositoryImplTest.java
│       │           │       └── UserRepositoryImplTest.java
│       │           └── config
│       │               ├── DatabaseConfigTest.java
│       │               └── WebConfigTest.java
│       └── resources
│           └── test.properties
└── target
    ├── classes
    ├── generated-sources
    ├── generated-test-sources
    ├── maven-archiver
    ├── maven-status
    ├── surefire-reports
    └── test-classes

1.9. Service-Oriented Architecture (SOA)

1.10. Saga

Representation and Diagrams:

├── README.md
├── LICENSE
├── .gitignore
├── package.json
├── src
│   ├── index.js
│   ├── components
│   │   ├── App.js
│   │   ├── Header.js
│   │   └── Footer.js
│   ├── reducers
│   │   ├── index.js
│   │   ├── userReducer.js
│   │   └── postReducer.js
│   ├── actions
│   │   ├── index.js
│   │   ├── userActions.js
│   │   └── postActions.js
│   ├── sagas
│   │   ├── index.js
│   │   ├── userSagas.js
│   │   └── postSagas.js
│   ├── utils
│   │   ├── api.js
│   │   ├── constants.js
│   │   ├── helpers.js
│   │   └── ...
│   └── styles
│       ├── index.css
│       ├── app.css
│       ├── header.css
│       ├── footer.css
│       └── ...
└── public
    ├── index.html
    ├── favicon.ico
    ├── logo.png
    └── 
...

Examples and Explanations:

- `README.md`: This is a file that contains the documentation and instructions for the project. It is written in markdown and usually displayed on the project's GitHub page.
- `LICENSE`: This is a file that specifies the terms and conditions for using, modifying, and distributing the project. It is usually a standard open source license such as MIT, GPL, or Apache.
- `.gitignore`: This is a file that tells Git which files or folders to ignore when committing or pushing changes to the repository. It usually contains patterns or names of files that are generated by the project or the system, such as `node_modules`, `.env`, or `.DS_Store`.
- `package.json`: This is a file that contains the metadata and dependencies of the project. It is used by npm or yarn to install and manage the packages that the project requires. It also contains scripts and configurations for running and building the project.
- `src`: This is a folder that contains the source code of the project. It is usually organized into subfolders according to the type or functionality of the code, such as components, reducers, actions, sagas, utils, and styles.
- `index.js`: This is the entry point of the project. It is the file that is executed when the project is run or built. It usually imports and renders the main component, such as `App.js`, and applies the redux store and the saga middleware to the application.
- `components`: This is a folder that contains the React components of the project. A component is a reusable piece of UI that can accept props and render elements. Each component is usually defined in a separate file with the same name, such as `App.js`, `Header.js`, or `Footer.js`.
- `reducers`: This is a folder that contains the redux reducers of the project. A reducer is a function that takes the previous state and an action, and returns the next state. Each reducer is usually defined in a separate file according to the slice of state it manages, such as `userReducer.js`, `postReducer.js`, or `index.js` (which combines all the reducers using `combineReducers`).
- `actions`: This is a folder that contains the redux actions of the project. An action is an object that describes what happened in the application, such as `{ type: 'LOGIN', payload: { username: 'Alice' } }`. Each action is usually defined in a separate file according to the domain or feature it belongs to, such as `userActions.js`, `postActions.js`, or `index.js` (which exports all the actions).
- `sagas`: This is a folder that contains the saga functions of the project. A saga is a function that uses the `yield` keyword and the `effects` from the saga library to perform asynchronous or complex tasks, such as calling an API, dispatching actions, or handling errors. Each saga is usually defined in a separate file according to the domain or feature it belongs to, such as `userSagas.js`, `postSagas.js`, or `index.js` (which runs all the sagas using `all` and `fork`).
- `utils`: This is a folder that contains the utility functions or constants of the project. A utility function is a function that performs a common or generic task, such as formatting a date, validating an input, or generating a random number. A constant is a variable that holds a fixed or immutable value, such as a URL, a color, or a message. Each utility function or constant is usually defined in a separate file according to its purpose or category, such as `api.js`, `constants.js`, or `helpers.js`.
- `styles`: This is a folder that contains the CSS files of the project. CSS is a language that defines the style and layout of the HTML elements. Each CSS file is usually named after the component or feature it styles, such as `index.css`, `app.css`, `header.css`, or `footer.css`.
- `public`: This is a folder that contains the static assets of the project, such as HTML, images, icons, or fonts. These files are usually copied or served as they are, without any processing or bundling. The most important file in this folder is `index.html`, which is the HTML file that loads the JavaScript bundle and renders the application.

#### 1.11. Data Mesh

Project ├── README.md ├── data │ ├── domain1 │ │ ├── data1.csv │ │ ├── data2.json │ │ └── metadata.yaml │ ├── domain2 │ │ ├── data3.parquet │ │ ├── data4.hdf5 │ │ └── metadata.yaml │ └── domain3 │ ├── data5.sql │ ├── data6.xml │ └── metadata.yaml ├── docs │ ├── domain1.md │ ├── domain2.md │ └── domain3.md ├── src │ ├── domain1.py │ ├── domain2.py │ └── domain3.py └── tests ├── domain1_test.py ├── domain2_test.py └── domain3_test.py

project_root/ ├── domains/ │ ├── domain_1/ │ │ ├── data/ # Raw and curated data for domain_1 │ │ ├── pipelines/ # Scripts for data ingestion, transformation, validation │ │ ├── ownership/ # Documentation on data ownership, access control │ │ └── tests/ # Unit and integration tests for data pipelines │ ├── domain_2/ # Similar structure for other domains │ └── ... ├── infrastructure/ │ ├── orchestration/ # Tools for scheduling and managing data pipelines │ ├── storage/ # Configuration for data storage (e.g., data lake) │ └── monitoring/ # Tools for monitoring pipeline health and data quality ├── platform/ # Optional: Shared codebase for common data processing tasks │ └── ... ├── readme.md # Project overview, setup instructions ├── data_products/ # Optional: Location for curated data products │ └── ... └── tests/ # Integration tests for overall data mesh functionality


This layout emphasizes domain-driven ownership of data. Each domain has its own directory containing:

* **data/**: Raw and curated data relevant to the domain
* **pipelines/**: Scripts to ingest, transform, and validate data
* **ownership/**: Documentation on data ownership, access control
* **tests/**: Unit and integration tests for data pipelines

* **domains/**: The core directory containing subdirectories for each domain.
* **infrastructure/**: Configuration and tools for managing the data mesh infrastructure.
* **platform/** (Optional): Shared codebase for common data processing tasks across domains.
* **readme.md**: Project overview, setup instructions, and documentation.
* **data_products/** (Optional): Location for curated data products consumed by applications.
* **tests/**: Integration tests for overall data mesh functionality.

#### 1.12. Domain-Driven Design (DDD)

- Project Layout

```plaintext
project/
├── src/
│   ├── domain/
│   │   ├── <domain_context_1>/  // Folder per domain context
│   │   │   ├── entities/        // Entities representing domain concepts
│   │   │   ├── value_objects/    // Immutable objects with data
│   │   │   ├── repositories/     // Interfaces for persistence access
│   │   │   └── services/         // Domain logic operations
│   │   ├── ... (other domain contexts)
│   │   └── shared/              // Shared domain concepts across contexts
│   ├── application/
│   │   ├── commands/            // Data for initiating actions
│   │   ├── queries/             // Data for retrieving information
│   │   └── services/            // Application-level services
│   ├── infrastructure/
│   │   ├── persistence/        // Persistence mechanisms (databases, etc.)
│   │   └── ... (other infrastructure concerns)
│   └── presentation/            // User Interface (web, console, etc.)
├── tests/
│   └── ... (unit and integration tests)
└── ... (other project configurations)
DDD-project
├── README.md
├── config
│   ├── application.yml
│   └── database.yml
├── domain
│   ├── entities
│   │   ├── customer.rb
│   │   ├── order.rb
│   │   └── product.rb
│   ├── repositories
│   │   ├── customer_repository.rb
│   │   ├── order_repository.rb
│   │   └── product_repository.rb
│   └── services
│       ├── customer_service.rb
│       ├── order_service.rb
│       └── product_service.rb
├── infrastructure
│   ├── adapters
│   │   ├── email_adapter.rb
│   │   ├── payment_adapter.rb
│   │   └── shipping_adapter.rb
│   ├── database
│   │   ├── migrations
│   │   │   ├── 202103071234_create_customers.rb
│   │   │   ├── 202103071235_create_orders.rb
│   │   │   └── 202103071236_create_products.rb
│   │   └── schema.rb
│   └── web
│       ├── controllers
│       │   ├── customers_controller.rb
│       │   ├── orders_controller.rb
│       │   └── products_controller.rb
│       ├── routes.rb
│       └── views
│           ├── customers
│           │   ├── edit.html.erb
│           │   ├── index.html.erb
│           │   ├── new.html.erb
│           │   └── show.html.erb
│           ├── orders
│           │   ├── edit.html.erb
│           │   ├── index.html.erb
│           │   ├── new.html.erb
│           │   └── show.html.erb
│           └── products
│               ├── edit.html.erb
│               ├── index.html.erb
│               ├── new.html.erb
│               └── show.html.erb
└── test
    ├── domain
    │   ├── entities
    │   │   ├── customer_test.rb
    │   │   ├── order_test.rb
    │   │   └── product_test.rb
    │   ├── repositories
    │   │   ├── customer_repository_test.rb
    │   │   ├── order_repository_test.rb
    │   │   └── product_repository_test.rb
    │   └── services
    │       ├── customer_service_test.rb
    │       ├── order_service_test.rb
    │       └── product_service_test.rb
    └── infrastructure
        ├── adapters
        │   ├── email_adapter_test.rb
        │   ├── payment_adapter_test.rb
        │   └── shipping_adapter_test.rb
        └── web
            ├── controllers
            │   ├── customers_controller_test.rb
            │   ├── orders_controller_test.rb
            │   └── products_controller_test.rb
            └── views
                ├── customers
                │   ├── edit_test.rb
                │   ├── index_test.rb
                │   ├── new_test.rb
                │   └── show_test.rb
                ├── orders
                │   ├── edit_test.rb
                │   ├── index_test.rb
                │   ├── new_test.rb
                │   └── show_test.rb
                └── products
                    ├── edit_test.rb
                    ├── index_test.rb
                    ├── new_test.rb
                    └── show_test.rb

1.13. Component-Driven Development (CDD)

Component-Driven Development (CDD) is an approach to software development that emphasizes the construction of applications by composing modular, reusable components. It focuses on building and integrating self-contained, loosely coupled components as the primary building blocks of an application.

In CDD, the application is divided into smaller, independent components, each representing a distinct functionality or user interface element. These components can be developed, tested, and maintained independently, promoting code reusability and modular design. The components are typically designed to have well-defined interfaces, allowing them to be easily integrated into larger systems or used across multiple projects.

CDD encompasses the entire development lifecycle, from designing and implementing components to integrating them into larger systems. It promotes modularity, reusability, and scalability in software development, enabling teams to build applications more efficiently and maintainable by focusing on building and integrating reusable components.

NOTE CDD aligns well with modern frontend development frameworks like React, Vue.js, and Angular, which provide component-centric development approaches.

Concepts of CDD:

  1. Component-Based Architecture: CDD emphasizes the use of a component-based architecture, where components are the fundamental units of development, deployment, and composition. Components are self-contained entities that encapsulate specific functionality or user interface elements.

  2. Reusability: Components in CDD are designed to be reusable across different parts of the application or even in different projects. This reusability reduces duplication of code and accelerates development by leveraging existing components.

  3. Isolation and Independence: Components in CDD are developed in isolation, allowing them to be tested, maintained, and evolved independently. Each component has its own well-defined boundaries and dependencies, minimizing coupling with other components.

  4. Component Libraries: Component libraries are collections of reusable components that adhere to a specific set of guidelines and standards. These libraries provide a repository of components that developers can leverage to build applications more efficiently.

  5. Component Testing: Testing plays a crucial role in CDD. Components are tested in isolation to ensure their individual functionality and behavior. Additionally, integration tests are performed to verify the correct composition and interaction of components within the application.

  6. Designing with Composability in Mind: Components in CDD are designed to be easily composed together to form larger applications. They provide well-defined interfaces and expose properties, events, and methods for interaction and customization.

  7. Collaboration and Documentation: CDD encourages collaboration between designers, developers, and stakeholders. It emphasizes the use of documentation, style guides, and design systems to facilitate effective communication and ensure consistency in component development.

1.14. Serverless Architecture

Backend for Frontend (BFF)

Backend for Frontend (BFF) is a design pattern where a dedicated backend service is created for each frontend application. This approach allows tailoring the backend logic and APIs to the specific needs of a particular frontend, optimizing communication and data exchange between the frontend and backend.

BFF-project
├── README.md
├── package.json
├── src
│   ├── app.js
│   ├── config
│   │   ├── index.js
│   │   └── logger.js
│   ├── controllers
│   │   ├── auth.js
│   │   ├── cart.js
│   │   ├── product.js
│   │   └── user.js
│   ├── middleware
│   │   ├── auth.js
│   │   ├── error.js
│   │   └── validation.js
│   ├── models
│   │   ├── cart.js
│   │   ├── product.js
│   │   └── user.js
│   ├── routes
│   │   ├── auth.js
│   │   ├── cart.js
│   │   ├── index.js
│   │   ├── product.js
│   │   └── user.js
│   ├── services
│   │   ├── auth.js
│   │   ├── cart.js
│   │   ├── product.js
│   │   └── user.js
│   └── utils
│       ├── constants.js
│       ├── errors.js
│       └── helpers.js
└── tests
    ├── controllers
    │   ├── auth.test.js
    │   ├── cart.test.js
    │   ├── product.test.js
    │   └── user.test.js
    ├── middleware
    │   ├── auth.test.js
    │   ├── error.test.js
    │   └── validation.test.js
    ├── services
    │   ├── auth.test.js
    │   ├── cart.test.js
    │   ├── product.test.js
    │   └── user.test.js
    └── utils
        ├── constants.test.js
        ├── errors.test.js
        └── helpers.test.js

Frontend for Backend (FFB)

Frontend for Backend (FFB) integrates admin panels into web applications, enabling frontend developers to manage and configure backend functionalities more efficiently. This approach adds a layer of frontend interfaces, essentially admin panels that directly interact with the backend.

FFB
├── README.md
├── package.json
├── src
│   ├── app.js
│   ├── config
│   │   ├── index.js
│   │   └── routes.js
│   ├── controllers
│   │   ├── auth.js
│   │   ├── index.js
│   │   └── user.js
│   ├── models
│   │   ├── index.js
│   │   └── user.js
│   ├── services
│   │   ├── auth.js
│   │   ├── index.js
│   │   └── user.js
│   └── utils
│       ├── constants.js
│       ├── errors.js
│       └── helpers.js
└── tests
    ├── integration
    │   ├── auth.test.js
    │   └── user.test.js
    └── unit
        ├── config.test.js
        ├── controllers.test.js
        ├── models.test.js
        ├── services.test.js
        └── utils.test.js

2. Principles

Principles guide architects and developers in making design decisions when applying architectural patterns.

3. Best Practice

When applying architectural patterns, it is important to follow best practices to ensure successful implementation and achieve the desired outcomes.

4. Terminology

5. References

sentenz commented 1 year ago

Related #111, #109, #108

sentenz commented 3 months ago

Prompts

  1. Create a tree view in markdown of Frontend for Backend (FFB) project layout, directory structure respectively.