docs(github, docs): Добавить пример документации (#9)

This commit is contained in:
Yuri Petrov
2025-05-13 18:14:42 +03:00
committed by GitHub
parent 2bce9c1b74
commit f3aee33ada
12 changed files with 426 additions and 20 deletions

18
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,18 @@
## Ссылка на задачу или issue (обязательно)
<!--- https://tracker.yandex.ru/XXX -->
## Описание (обязательно)
<!--- Напишите здесь какую проблему решают изменения в этом запросе. -->
## Чек лист (обязательно)
- [ ] Код соответствует рекомендациям и требованиям проекта.
- [ ] Анализатор проверил на предмет ошибок и предупреждений.
- [ ] Название ПР соответствует [требованиям проекта](../tools/rfc/RFC-documentation.md).
- [ ] В документации отражены внесенные изменения.
- [ ] Добавлены необходимые тесты, если требуется.
## Скриншоты (желательно)
<details>
<summary>Показать</summary>
<!--- Сюда добавить скриншоты -->
</details>

View File

@@ -1,3 +1 @@
.github/* @ns @sna2021
**/.gitlab-ci.yml @ns @sna2021
Friflex LCC

View File

@@ -1,16 +0,0 @@
# friflex_starter
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@@ -1 +1,30 @@
# friflex_starter
#### Приложение [ProjectName]
## Структура проекта
- проект архитектурно делится на три слоя: data, domain и presentation;
- все [features] реализуются в отдельных папках, с внутренним делением на слои;
## Основные пакеты и реализации (обновляется при добавлении или изменении)
- управление роутингом: [go_router](https://pub.dev/packages/go_router);
- основной state manager: [flutter_bloc](https://pub.dev/packages/flutter_bloc);
- di: ручная реализация через InheritedWidget;
- работа с ресурсами: [flutter_gen](https://pub.dev/packages/flutter_gen);
- анализатор: используем [friflex_lint_rules](https://pub.friflex.com/packages/friflex_lint_rules), с правилами написания кода от компании.;
- для хранения защищенных данных - [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage);
- для хранения данных - [shared_preferences](https://pub.dev/packages/shared_preferences);
- для работы с API - [dio](https://pub.dev/packages/dio);
## Инструкция по запуску проекта
- [Инструкция по запуску проекта](./tools/rfc/RFC-build.md)
## Стиль написания кода
- [Стиль написания кода](./tools/rfc/RFC-codestyle.md)
## Внесение изменений в код
- [Внесение изменений в код](./tools/rfc/RFC-gitflow.md)
## Структура проекта
- [Структура проекта](./tools/rfc/RFC-projects_structure.md)
## Ведение документации и комментариев в проекте
- [Ведение документации и комментариев в проекте](./tools/rfc/RFC-documentation.md)

3
tools/.sh Normal file
View File

@@ -0,0 +1,3 @@
format code
dart format --output=none --set-exit-if-changed .

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

2
tools/rfc/RFC-build.md Normal file
View File

@@ -0,0 +1,2 @@
# Инструкция по запуску
<!--- Добавить важную информацию о сборке и запуске проекта -->

124
tools/rfc/RFC-codestyle.md Normal file
View File

@@ -0,0 +1,124 @@
# Стиль кода
Мы придерживаемся рекомендаций, описанных в
[Effective Dart](https://dart.dev/guides/language/effective-dart/design)
Перед каждым PR необходимо отформатировать код и проверить анализатор на отсутствие сообщений.
## Именование
### Интерфейсы
Утверждены два вида объявления интерфейсов:
1. Все интерфейсы в приложении должны начинаться с заглавной буквы "**I**".
Например: **IAuthRepository**, **IProfileRepository**, **IMainRunner** и т.д.
Таким образом, сразу видно, что работаешь с интерфейсом.
Пример:
```dart
/// Интерфейс - **IUserRepository**
abstract interface class IUserRepository {}
/// Основная реализация (prod и stage окружения)
class UserRepository implements IUserRepository {}
/// Иная реализация (мок, локальное хранилище) должна содержать
/// постфикс функциональности:
/// - Network - сетевое взаимодействие.
/// - Local - локальное хранилище.
/// - Mock - мок репозиторий.
class UserRepositoryLocal implements IUserRepository {}
```
### Классы - Репозитории
Репозитории должны содержать в конце название источника данных (если используется мок или локальное хранилище).\
Основная реализация, не должна содержать постфикса.
Например: Интерфейс - **IAuthRepository**\
Основная реализация (prod и stage окружения) - **AuthRepository**
Мок (мок данные) - **AuthRepositoryMock**\
Локальное хранилище (например бд или просто имитация данных) - **AuthRepositoryLocal**
### Файлы
Используется snake_case.
Название файла должно иметь следующую структуру: [раздел]_[тип].dart
Пример: user_details_screen.dart, shop_entity.dart
### Классы
Название классов UpperCamelCase.
Для создание приватных классов используем префикс _ . Название класса в конце должно содержать в себе тип.
Пример: **UserEntity**, **AdultDialog**
## Методы
Название метода в начале должно содержать в себе действие(глагол):
- fetch
- put
- update
- delete и так далее
Пример:
```dart
int fetchFirstElement(){}
```
Пример:
```dart
void updateFirstElement(){};
```
Название метода не должно содержать в себе And/Or
и метод соответственно не должен выполнять подобную логику.
## Переменные и константы
Константы именуются также lowerCamelCase.
Пример:
```dart
const String carItem
```
или
```dart
final userName;
```
## Виджеты
Виджеты именуются UpperCamelCase.
В названии виджетов не должно содержаться слово widget.
### Экраны
Экраны, используемые в роутинге, именуются с постфиксом Screen.
Например, **ShopListScreen**.
### Содержимое экрана
Виджеты, отображающие содержимое экрана, именуются с постфиксом View.
Например, **ShopListView**.
### Глобальные виджеты
Глобальные виджеты именуются с приставкой App.
Например, **AppButton**.
## Структура класса
Объявления элементов класса должны располагаться в следующем порядке:
1. **Constructors**
- constructors
- named-constructors
- factory-constructors
2. **Static**
- public-static-methods
- private-static-methods
- public-static-const-fields
- private-static-const-fields
- public-static-final-fields
- private-static-final-fields
- public-static-fields
- private-static-fields
3. **Fields**
- public-final-fields
- private-final-fields
- public-fields
- private-fields
4. **Getters/Setters**
- public-getters-setters
- private-getters-setters
5. **Methods**
- overridden-methods
- public-methods
- protected-methods
- private-methods

View File

@@ -0,0 +1,113 @@
# Ведение документации и комментариев
## Документация
### Основные правила ведения документации в проекте:
- документация оформляется над описываемым объектом с использованием '///';
- документацией необходимо покрывать все классы, конструкторы, поля, геттеры, сеттеры, методы, фабрики, все кастомные объекты;
- документация должна:
- указывать на назначение объекта;
- содержать исчерпывающее описание объекта;
- быть краткой и емкой;
- быть понятной для любого разработчика.
## Шаблоны и примеры документации объектов
### Документация классов:
```dart
/// {@template new_class}
/// Класс для реализации {описание назначения и реализуемого функционала в классе}.
/// {@endtemplate}
class NewClass {}
```
Пример:
```dart
/// {@template app_button}
/// Класс для реализации кастомизированной кнопки.
/// {@endtemplate}
class AppButton {}
```
### Документация конструкторов и фабрик:
Если конструктор один, то достаточно указать {@macro new_class}.
{@macro new_class} дублирует на конструктор указанную в рамках описания класса документацию, поэтому описание класса должно в таком случае включать все передаваемые в конструктор параметры
Если конструкторов несколько, описания должны отражать их отличия друг от друга. Фабрики описываются по такому же принципу.
```dart
///{@macro new_class}
const NewClass();
/// Создает {описание создаваемого фабрикой объекта}.
/// Принимает:
/// - [json] - {описание параметра}
factory NewClass.fromJson(Map<String, dynamic> json)
```
### Документация полей классов:
В классе необходимо описывать каждое поле по отдельности. Если поле ссылается на другое поле или зависит от него, необходимо это указывать в описании.
```dart
/// Возраст пользователя.
final int age;
/// Индикатор совершеннолетия пользователя. Принимает значение true, когда [age] больше 18 лет.
final bool isAdult;
```
### Документация геттеров/сеттеров:
```dart
/// Получения доступа к {описание данных, которые получает геттер}
int get newGetter => ...
/// Установка значения для {описание работы сеттера}
set newSetter (int setterValue) => ...
```
### Документация методов:
Методы должны описывать их основное назначение. Если метод сложный, требуется указывать дополнительное описание его работы ниже через пропущенную строку. Если метод принимает какие-либо параметры, каждый параметр должен быть описан по отдельности списком с прямой ссылкой. Если метод возвращает какие-либо значения, они должны быть описаны. Желательно указать, что вернет метод в случае возникновения ошибки.
```dart
/// Метод для {описание назначения метода}.
/// {описание особенностей работы метода}.
/// Принимает:
/// - [param] - {описание назначения параметра}.
void newMethod({required String param}) {
...
}
```
Пример:
```dart
/// Метод для расчета температуры.
/// Принимает:
/// - [grad] - параметр необходим для расчета температуры.
/// Возвращает:
/// - температуру в градусах.
/// При ошибке расчета возвращается null.
int? calcTemperature({required int grad}){
// Реализация
}
```
## Комментарии
### Основные правила комментирования кода в проекте:
- комментарии оформляются над описываемым участком кода с использованием '//';
- комментировать необходимо те участки кода, которые действительно нуждаются в дополнительном описании;
- комментарий не должен повторять легко читаемые участки кода
Например:
```dart
if(flag != true) // не нужно описывать как "Если значение не равно true...
```
Например:
```dart
if(isAurora){
// Так как Аврора не может открывать WebView,
// то заменяем на открытие внешнего браузера
}
```
## TODO
### Основные правила создания TODO в проекте:
- TODO оформляются согласно условиям форматирования линтера с указанием имени разработчика, кто находится в контексте проблемы и сможет ее прокомментировать;
- TODO необходимо оставлять на тех участках кода, которые требуют дальнейшей доработки;
- если известно, в рамках какой задачи будет доработан помечаемый участок кода, ссылку на задаче необходимо оставить в скобках.

60
tools/rfc/RFC-gitflow.md Normal file
View File

@@ -0,0 +1,60 @@
# Ведение проекта в git
## Создание commits/pull-request
- язык описания PR - Русский;
- описание должно отражать краткую суть изменений;
- коммит/PR должен содержать:
- исчерпывающую информацию об изменениях;
- ссылку на задачу в таск-трекер;
- Перечисление deprecated-кода (если есть).
### Типы коммитов согласно convention
* **feat**: — новая функция
* **fix**: — исправление ошибок
* **refactor**: — Изменение кода, которое не исправляет ошибку и не добавляет функции (рефакторинг кода).
* **build**: — изменения, влияющие на систему сборки или внешние зависимости (примеры областей (scope): android, ios, linux и так далее).
* **docs**: — изменения только в документации
* **chore** - добавление/обновление/настройка инструментов и библиотек (пример: pubspec.yaml).
* **test**: — добавление недостающих тестов или исправление существующих тестов.
* **ci**: — изменения в файлах конфигурации и скриптах CI (примеры областей: папка CI).
### Правила именования веток
Имена веток должны соответствовать convention, чтобы обеспечить консистентность и читаемость.
- Ветки feature должны начинаться с `feat/`.
- Ветки hotfix должны начинаться с `fix/` и так далее
- Используйте номер задачи из таск-трекера в имени ветки.
- Добавьте краткое описание задачи, используя snake_case или kebab-case.
Пример:
* `feat/PRIME-123_authentication`
* `fix/PRIME-456_typo_in_button`
* `fix/PRIME-456-typo-in-button`
## Схема разработки новой features
![](./tools/res/images/developing.jpg)
## Создание релиза
![](./tools/res/images/release.jpg)
### Добавление новых features
- создаем ветку feat/(уникальный номер задачи) (название feature),
Пример: <b>PRIME-17 Добавить_локальный_репозиторий</b>;
- вносим изменения;
- делаем коммит только на то, что касается изменений связанных с этой задачей;
- по завершению задачи - создаем Pull Request с названием по правилам https://commitlint.io/.
Пример: <b>feat(app,di,auth,scripts,pubspec): PRIME-17 Добавить локальный репозиторий</b>.
Где, PRIME- это обязательный префикс(с помощью него автоматически подтягивается ссылка на задачу), число 17 это уникальный номер задачи из трекера.
В описание к PR добавляем ссылку на задачу и описание внесенных изменений, и пояснения(если требуется);
- после завершения CodeReview создаем squash commit в ветку main (название коммит(а), должно быть такое же как название pull request) ;
- после того как ветка с новой feature попало в main - удаляем ветку;
### Создание release
- создаем ветку из main (release/release_0.0.1+1);
- добавляем в changelog.md описание изменений в этой версии (обычно это список коммитов, от предыдущей версии):
- делаем сборки, отправляем на тестирование;
- получаем баг-лист от тестировщиков, делаем фиксы;
- отправляем на следующий раунд тестирования и.т.д;
- после проверки и получения разрешение от другого разработчика - создаем tag c номером версии (0.0.1+1), создаем релиз, фиксируем версию и squash commit в ветку main и development;
- после того как release попал в main - удаляем ветку;

View File

@@ -0,0 +1,75 @@
# Структура проекта
Рекомендуемая структура проекта (может отличатся в зависимости от проекта и согласований)
- **/** - папка проекта
- **/assets** - директория расположения графических ресурсов
- **/tools/** - все необходимые инструменты для проекта
- **/docs** - документация проекта
- **/android** - папка, содержащая нативный код для Android
- **/aurora** - папка, содержащая нативный код для Aurora
- **/ios** - папка, содержащая нативный код для IOS
- **/env** - папка, с внешними переменными окружения
- **/lib** - код на Dart, Flutter-приложение
- **/app** - содержит основные настройки нашего приложения
- **/impls** - реализация интерфейсов
- **/interfaces** - объявление интерфейсов
- **/data** - общие поставщики данных
- **/domain** - общий слой
- **/presentation** - общий слой
- **/di** - файлы конфигурации зависимостей.
- **/routing** - все, что касается роутинга
- **/features** - фичи приложения, для каждой фичи создается отдельная папка
- **/feature_name** - подробнее см в разделе Структура feature папок
- **/data**
- **/domain**
- **/presentation**
- **/gen** - для сгенерированных файлов
- **/targets** - таргеты для сборок
- **/prod.dart** - сборка для prod
- **/dev.dart** - сборка разработки на моковых репозиториях
- **/stage.dart** - сборка для stage окружения
## Пример структуры feature папок
- **/data** - слой данных
- **/dto** - реализация DTO ( [data transfer object](https://ru.wikipedia.org/wiki/DTO) )
- **/repository** - реализации репозиториев
- **/domain** - слой бизнес логики
- **/entity** - модели которые используются для работы в domain/presentation слоях
- **/repository** - интерфейсы репозиториев, которые используются в domain слое
- **/state** - state-management
- **/service** - реализации сервисов
- **/presentation** - слой представления
- **/screens** - все экраны должны заканчиваться на Screen, например UserProfileScreen.
- **/components** - виджеты, которые необходимы для работы в presentation слое. Например: SuperButton, AppTextFields итд.
# Пояснение к структуре feature папок
## Data (слой данных) Этот слой является поставщиком данных.
- Repository - сущность, которая реализует внутри себя предоставление данных. Должен реализовывать какой либо интерфейс репозитория из domain слоя.
- DTO - Dto(Data Transfer Object) модели, и модели с которыми происходит работа в data слое. Например: UserDto;
## Domain (слой бизнес логики)
- Entity - должны быть в максимально удобном виде для работы внутри Domain и Presentation. Например: UserEntity, ShopEntity;
- State - управления состоянием - state manager
- Service - различные сервисы, для выполнения различных задач.
- interfaces - интерфейсы репозиториев, которые используются в domain слое.
## Presentation (слой представления)
- сomponents - widget'ы которые реализуют работу какого либо визуального компонента(Buttons,TextFields,Lists, итд). Например: ShopList, RateButton. Модальные окна.
- screens - widget'ы которые представляют собой экран приложения. Например: UserInfoScreen.
# Основные правила общения объектов между папками
## В рамках всего приложения
- объекты внутри фичи должны быть инкапсулированы и не могут использоваться в других feature;
- если есть необходимость использовать объект в нескольких feature, его нужно вынести в папку app и использовать как глобальный для всего приложения;
- сервис, который должен быть использован в нескольких feature, создается как отдельная feature;
- если создаваемый сервис является платформно-зависимым, его необходимо выносить в app_services. В приложении должен быть только интерфейс.
## В рамках одной feature
- объекты data слоя не должны ничего знать про объекты слоя presentation. Имеют доступ к объектам entity из domain слоя для преобразования DTO в Entity ;
- объекты domain слоя не должны ничего знать про объекты слоя data, используемый экземпляр репозитория передается в объекты domain слоя через интерфейс репозитория, расположенного в этом же domain слое;
- объекты domain слоя не должны ничего знать про слой presentation, не должны использовать компоненты библиотек ui, material, cupertino, widget и прочих, не должны использовать context;
- объекты presentation слоя не должны ничего знать про объекты слоя data, все взаимодействия непосредственно через объекты слоя domain.