-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from DouglasbDev/feat/arch
Feat/arch
- Loading branch information
Showing
3 changed files
with
89 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,253 +1,132 @@ | ||
# YuNO Architecture | ||
# Arquitetura - MiniCore | ||
|
||
This architecture aims to clearly separate responsibilities into layers, making code maintenance, testability, and scalability easier. Each layer has a specific purpose, and dependencies are organized so that business logic is not tightly coupled to technical implementation, allowing flexibility and ease of system evolution. | ||
**Objective**: Propose a simplified and easily understandable architecture, focusing on the FrontEnd. The proposed structure is based on three distinct layers: User Interactor, Adaptation, and External. | ||
|
||
<img src="assets/YuNO-Arch.png" width="512" alt="Achitecture diagram"/> | ||
### Layers | ||
|
||
## 1. Layers | ||
**User Interactor**: Should be responsible for declaring the inputs, outputs, and interactions of the application. | ||
|
||
### 1.1 Public | ||
**Adaptation**: Should be responsible for translating and facilitating communication between the User Interactor and External layers. | ||
|
||
Encompasses all pages and subpages of the application. | ||
**External**: Should be responsible for handling information external to your application. | ||
<br> | ||
<br> | ||
|
||
- **Pages:** | ||
- Represents the user interface layer. | ||
- Should be decoupled as much as possible from non-essential UI packages. | ||
- **Widgets:** | ||
- Contains specific visual components for a single page. | ||
<p align="center"> | ||
<img src="assets/vai.png" width="512" alt="Achitecture diagram"/> | ||
</p> | ||
|
||
### 1.2 Interactor | ||
<br> | ||
<br> | ||
|
||
Encompasses business rules and yours interfacer. | ||
<p align="center"> | ||
<img src="assets/volta.png" width="512" alt="Achitecture diagram"/> | ||
</p> | ||
|
||
- **Atoms:** | ||
- Small building blocks representing atomic units of functionality. | ||
- **Actions:** | ||
- Represents actions that can be performed in the system. | ||
- **Interfaces of Repositories and Services:** | ||
- Defines contracts for interactions with data layers. | ||
### Limits | ||
|
||
### 1.3 Data | ||
Within the established architectural boundaries, it is highlighted that the User Interactor layer should not have direct access to the External layer. To overcome this restriction, the Adaptation layer acts as an intermediary, facilitating communication between the User Interactor and External layers. | ||
|
||
Encompasses the execution of business rules. | ||
With the aim of enhancing development efficiency and flexibility, the architecture ensures low coupling through a clear separation of responsibilities in each layer. | ||
|
||
- **Implementations:** | ||
- **Repositories and Services:** | ||
- Contains concrete implementations of contracts defined in the Interactor layer. | ||
- Responsible for interacting with external data sources such as databases or APIs. | ||
|
||
### 1.4 Core | ||
## Architecture Structure | ||
|
||
Encompasses global data for the application. | ||
### UI (User Interface) | ||
This layer must contain the visual elements of the application. | ||
|
||
- **Themes:** | ||
- Defines visual styles and themes for the application. | ||
- **Assets:** | ||
- Stores static resources such as images, icons, etc. | ||
- Every type of asset requires a specific file, with its names listed and pre-cached in a function. | ||
- **Widgets:** | ||
- Reusable components that can be used in different parts of the application. | ||
- **Other Global Data:** | ||
- Includes other elements essential for the global operation of the application. | ||
### Interactor | ||
This layer should encompass the states or reactivities of the application, the representation of business rules, abstractions for communication between the other layers, and the operations executed by its UI. | ||
|
||
## 2. Nomenclatures | ||
- #### Atoms: | ||
They must store an application state. | ||
|
||
This section outlines the naming conventions for different components of our application including widgets, actions, atoms, repositories, and services. | ||
- #### Actions: | ||
They must have the purpose of changing the application states. | ||
|
||
### 2.1 Widgets | ||
- #### DTO: | ||
Data Transfer Object is a design pattern used to transfer data between layers. | ||
|
||
### Guidelines for Widget Naming | ||
- #### Models: | ||
They represent business rules. | ||
|
||
- **Suffix "Widget":** All widget classes should consistently use the "Widget" suffix. This makes it easier to identify them in the codebase. | ||
- **Clarity and Consistency:** The name should clearly reflect the widget's functionality. | ||
- **Example:** `login_button_widget.dart` | ||
- #### Interfaces: | ||
They must contain interfaces to achieve loose coupling, reducing direct dependency and providing easy replacement of implementations. | ||
|
||
## Data | ||
They must interact with external sources. | ||
|
||
```dart | ||
class LoginButtonWidget extends StatelessWidget { } | ||
``` | ||
|
||
### 2.2 Actions | ||
|
||
### Guidelines for Action Naming | ||
|
||
- **Verb-Noun Format:** Names of actions should typically follow a verb-noun format, indicating what the action does. | ||
- **Descriptive:** Ensure the name gives a clear indication of its purpose. | ||
- **Example:** `config_action.dart` | ||
|
||
```dart | ||
Future<T> fetchConfig() {} | ||
Future<T> saveConfig() {} | ||
``` | ||
|
||
### 2.3 Atoms | ||
|
||
### Guidelines for Atom Naming | ||
|
||
- **Descriptive and Concise:** Atom names should be concise yet descriptive enough to indicate their role and usage. | ||
- **Component Specific:** Name atoms based on their functionality or the data they handle. | ||
- **Example:** | ||
`config_atom.dart` | ||
|
||
```dart | ||
final configState = Atom<T>(); | ||
``` | ||
|
||
### 2.4 Repositories | ||
|
||
### Guidelines for Repository Naming | ||
|
||
- **Noun Format:** Repository names should be clear, concise nouns. | ||
- **Reflect Data Model:** They should closely reflect the data model or resource they are associated with. | ||
- **Example:** | ||
`game_repository.dart` | ||
|
||
```dart | ||
class GameRepository { } | ||
``` | ||
|
||
### 2.5 Services | ||
|
||
### Guidelines for Service Naming | ||
|
||
- **Noun or Verb-Noun Format:** Service names can be nouns or verb-noun combinations, indicating the service provided. | ||
- **Purpose-Clear:** The name should clearly reflect the functionality or the domain of the service. | ||
- **Example:** | ||
`authentication_service.dart` | ||
|
||
```dart | ||
class AuthenticationService { } | ||
``` | ||
|
||
This structured approach provides a clear and organized set of naming conventions across different elements of the application, ensuring consistency and clarity in the codebase. | ||
|
||
## 3. Tests | ||
|
||
Testing is a crucial part of software development. It ensures code quality and functionality, and helps in maintaining the software over time. Our testing approach adheres to the triple-A pattern (Arrange, Act, Assert) for its clarity and structure. | ||
|
||
For an in-depth understanding, refer to this article on the [Triple-A Pattern](https://medium.com/@pjbgf/title-testing-code-ocd-and-the-aaa-pattern-df453975ab80). | ||
|
||
### Example | ||
- #### Adapter: | ||
There must be adaptations to ensure that external data follows the standards defined by the application. | ||
|
||
```dart | ||
test('should execute a sum correctly', () { | ||
- #### Tratamento de erros: | ||
As a good practice, we must handle errors in our application, ensuring stability and reducing the occurrence of failures. | ||
|
||
- #### Repository: | ||
It must contain the concrete class, coming from the abstraction, for communication between layers. | ||
|
||
- #### Service: | ||
It must contain the concrete class, coming from the abstraction, for communication between layers. | ||
|
||
// arrange | ||
int number1 = 2; | ||
int number2 = 1; | ||
## Core | ||
It must contain global and reusable information for all layers of the application. | ||
|
||
// act | ||
final result = sumFunction(number1, number2); | ||
## Benefits of Using MiniCore Architecture: | ||
|
||
// assert | ||
expect(result, 3); | ||
- #### Ease of Understanding: | ||
It provides a clear and intuitive structure, making the code easier for developers to understand. | ||
|
||
}); | ||
``` | ||
- #### Maintainability: | ||
Layering and clarifying responsibilities makes the code easier to maintain and update. | ||
|
||
### 3.1 Test Description | ||
- #### Code Scalability: | ||
The architecture is designed to handle application growth, ensuring it can scale effectively. | ||
|
||
The description of each test should clearly articulate the expected outcome based on the specific action or condition being tested. Avoid generic or obvious descriptions. Instead, focus on what is being verified in each test case. | ||
- #### Easy Access to Global Variables and Methods: | ||
Facilitates access to global variables and methods, promoting efficient communication between different parts of the system. | ||
|
||
### Guidelines for Test Descriptions | ||
- #### Facilitates Testing (Without the Need to Mock the Atoms): | ||
Simplify testing by eliminating the need to simulate or mock Atoms, making the testing process more efficient and less complex. | ||
|
||
- Clearly state the purpose of the test. | ||
- Describe the specific condition or scenario. | ||
- Indicate the expected result or behavior. | ||
Another important point will be the global state, and with this, we gain: | ||
|
||
### Examples of Good Descriptions | ||
Universal Accessibility: The global state allows data to be accessed from anywhere in the application. This can be useful when you need to share information between different parts of the user interface or across multiple pages. | ||
|
||
- Correct: "should return the sum of two numbers when both inputs are positive". | ||
- Avoid: "Should return a result". | ||
Reduced Complexity: Instead of passing data through various components as parameters, the use of a global state can simplify the code, making it more readable and easier to understand. | ||
|
||
### 3.2 Test Grouping | ||
Ease of Maintenance: By centralizing the state in a global location, it becomes easier to maintain and modify the application state. This can facilitate bug resolution and the implementation of new features. | ||
|
||
Grouping tests is essential for organization and readability, especially in large codebases. Group names should correspond to the class or functionality they are testing, with an optional method name if applicable. Use " | " (space, pipe, space) at the end of each group name for clarity. | ||
Improved Performance: Depending on the implementation, a well-managed global state can lead to better performance, especially compared to approaches where data needs to be passed through many components. | ||
|
||
### Guidelines for Test Grouping | ||
|
||
- Group tests by functionality or class. | ||
- Use descriptive names that reflect the group's purpose. | ||
- Optionally include the specific method being tested. | ||
<br> | ||
|
||
### Example of Action Test Group | ||
By adopting the MiniCore architecture, developers gain a more robust, efficient, and easily maintainable system development, promoting a more positive and sustainable development experience. | ||
|
||
```dart | ||
group('SaveGameAction | ', () { | ||
// Tests for SaveGameAction | ||
}); | ||
``` | ||
## Examples | ||
|
||
### Example of Repository Test Group | ||
According to the proposed architecture, the folder structure is defined. | ||
|
||
```dart | ||
group('AndroidAppsRepository.openAppSettings | ', () { | ||
// Tests for AndroidAppsRepository.openAppSettings | ||
}); | ||
``` | ||
|
||
## 3.3 Additional Best Practices | ||
|
||
- **Test Isolation:** Ensure each test is independent and can run alone. | ||
- **Code Coverage:** Aim for high test coverage, but prioritize meaningful tests over merely inflating coverage metrics. | ||
- **Mocking and Stubbing:** Use mocks and stubs where necessary to isolate the unit of test. | ||
|
||
Remember, good tests not only check for correct outcomes but also contribute to the overall quality and maintainability of the software. | ||
|
||
## 4. Localizations | ||
|
||
Localization is key to making an application accessible and user-friendly to a global audience. This section provides guidelines and best practices for implementing localizations. | ||
|
||
### 4.1 Implementing Localizations | ||
|
||
### Steps for Implementation | ||
|
||
#### 4.1.1 Defining localization files | ||
|
||
Create a JSON file in the i18n folder, this file should be named `xx.json` where xx should be replaced with the locale, for example: en_US.json. These files must contain key-value pairs for strings in different languages. | ||
|
||
**Example of content to pt_BR.json file:** | ||
|
||
```json | ||
{ | ||
"home": "Início", | ||
"apps": "Apps", | ||
"settings": "Configurações", | ||
"favorite": "Favoritar", | ||
"play": "Jogar", | ||
"syncing": "Sincronizando", | ||
"search_a_game": "Pesquise um jogo", | ||
"platforms": "Plataformas", | ||
"preferences": "Preferencias", | ||
"feedback": "Feedback", | ||
"about": "Sobre", | ||
"add_platorm": "Adicionar Plataforma" | ||
} | ||
. | ||
└── app/ | ||
├── public/ | ||
│ └── pages/ | ||
├── core/ | ||
│ ├── assets/ | ||
│ ├── themes/ | ||
│ └── widgets/ | ||
├── data/ | ||
│ ├── adapters/ | ||
│ ├── repositories/ | ||
│ └── services/ | ||
└── interactor/ | ||
├── atoms/ | ||
├── actions/ | ||
├── dtos/ | ||
├── models/ | ||
├── repositories/ | ||
└── services/ | ||
``` | ||
|
||
#### 4.1.2 Locale Configuration | ||
|
||
Configure the list of supported locales in the app_widget.dart file. | ||
|
||
#### 4.1.3 Loading Localized Data | ||
|
||
We use the `localization` package to load and retrieve localized data based on the current locale. | ||
|
||
#### 4.1.4 Dynamic Text Replacement | ||
|
||
Implement dynamic text replacement in the UI using localized strings. | ||
|
||
#### 4.1.5 Fallback Locale | ||
|
||
Set up a fallback locale for scenarios where the user's locale doesn't match any supported locales. | ||
|
||
### 4.2 Best Practices for Localizations | ||
|
||
- **Key Consistency:** Ensure consistency in the naming of keys across different localization files. | ||
|
||
- **Regular Updates:** Regularly update localization files whenever there are changes in the text of the application. | ||
|
||
- **Testing for Different Locales:** Test the application in different languages to ensure that the translations fit well in the UI and are contextually accurate. | ||
|
||
- **Cultural Considerations:** Pay attention to cultural nuances in translations to avoid misunderstandings or offense. | ||
|
||
- **Automated Tools and Human Review:** Consider using automated translation tools for efficiency, but always have translations reviewed by native speakers for accuracy and context. | ||
See some [examples](https://github.com/FelCarv01/mini-core-examples). |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.