docs(cursorrules,copilot-instructions): обновить правила разработки и нструкции для AI-агента (#41)

This commit is contained in:
Yuri Petrov
2025-12-10 12:42:49 +03:00
committed by GitHub
parent 73a13c99c6
commit ab64fb9246
2 changed files with 750 additions and 98 deletions

View File

@@ -1,64 +1,389 @@
# Правила для Cursor AI # Правила разработки Flutter проекта
## Соглашение о коммитах Этот файл содержит правила и стандарты разработки для проекта. Все правила обязательны к соблюдению при написании кода.
При генерации сообщений коммитов ВСЕГДА используй следующий формат: **ВАЖНО:** Перед каждым PR необходимо отформатировать код (`dart format .`) и проверить анализатор на отсутствие сообщений (`dart analyze`).
`<тип>(<контекст1>,<контекст2>,...): <короткое описание>`
Для Pull Request формат: ---
`<тип>(<контекст1>,<контекст2>,...): <короткое описание>`
Где: # Стиль кода
- `<тип>` - тип коммита (см. ниже)
- `<контекст>` - модули/компоненты, которые изменяются (можно указать несколько через запятую)
- `<короткое описание>` - краткое описание изменений на русском языке
### Типы коммитов согласно convention: ## Именование
- **feat** - новая функция ### Интерфейсы
- **fix** - исправление ошибок
- **refactor** - изменение кода, которое не исправляет ошибку и не добавляет функции (рефакторинг кода)
- **build** - изменения, влияющие на систему сборки или внешние зависимости (примеры областей: android, ios, linux и так далее)
- **docs** - изменения только в документации
- **chore** - добавление/обновление/настройка инструментов и библиотек (пример: pubspec.yaml)
- **test** - добавление недостающих тестов или исправление существующих тестов
- **ci** - изменения в файлах конфигурации и скриптах CI (примеры областей: папка CI)
### Контекст (scope): Все интерфейсы в приложении должны начинаться с заглавной буквы "**I**".
Указывай модуль или компонент, который изменяется. Можно указать несколько через запятую: Примеры: **IAuthRepository**, **IProfileRepository**, **IMainRunner** и т.д.
- `app` - основное приложение
- `di` - dependency injection
- `auth` - аутентификация
- `api` - API endpoints
- `db` - база данных
- `config` - конфигурация
- `i18n` - интернационализация
- `scripts` - скрипты
- `pubspec` - зависимости проекта
- `android`, `ios`, `linux` - платформы
- другие модули проекта
### Примеры правильных коммитов: Таким образом, сразу видно, что работаешь с интерфейсом.
- `feat(app,di,auth): Добавить локальный репозиторий` Пример:
- `fix(api): Исправить валидацию запросов`
- `docs(i18n): Обновить руководство по генерации`
- `refactor(handler): Оптимизировать обработку запросов`
- `test(security): Добавить тесты для rate limiter`
- `chore(pubspec): Обновить зависимости`
## Язык ```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 = 'default';
```
или
```dart
final String userName = 'default';
## Виджеты
Виджеты именуются 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
---
# Ведение документации и комментариев
## Документация
### Основные правила ведения документации в проекте
- Документация оформляется над описываемым объектом с использованием `///`
- Документацией необходимо покрывать все классы, конструкторы, поля, геттеры, сеттеры, методы, фабрики, все кастомные объекты
- Документация должна:
- указывать на назначение объекта
- содержать исчерпывающее описание объекта
- быть краткой и емкой
- быть понятной для любого разработчика
### Шаблоны и примеры документации объектов
#### Документация классов
```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 необходимо оставлять на тех участках кода, которые требуют дальнейшей доработки
- Если известно, в рамках какой задачи будет доработан помечаемый участок кода, ссылку на задачу необходимо оставить в скобках
Пример:
```dart
// TODO(username): Оптимизировать алгоритм сортировки
```
---
# Ведение проекта в git
## Создание commits/pull-request
- Всегда отвечай на русском языке
- Коммиты пиши на русском языке
- Документацию веди на русском языке
- Язык описания PR - Русский - Язык описания PR - Русский
- Описание должно отражать краткую суть изменений
- Коммит/PR должен содержать:
- исчерпывающую информацию об изменениях
- ссылку на задачу в таск-трекер
- Перечисление deprecated-кода (если есть)
## Стиль кода ### Типы коммитов согласно convention
- Следуй Dart/Flutter conventions - **feat**: — новая функция
- Используй осмысленные имена переменных и функций - **fix**: — исправление ошибок
- Добавляй комментарии к публичным функциям - **refactor**: — Изменение кода, которое не исправляет ошибку и не добавляет функции (рефакторинг кода)
- Группируй импорты (стандартные, внешние, внутренние) - **build**: — изменения, влияющие на систему сборки или внешние зависимости (примеры областей (scope): android, ios, linux и так далее)
- **docs**: — изменения только в документации
- **chore**: — добавление/обновление/настройка инструментов и библиотек (пример: pubspec.yaml)
- **test**: — добавление недостающих тестов или исправление существующих тестов
- **ci**: — изменения в файлах конфигурации и скриптах CI (примеры областей: папка CI)
# Структура проекта
Рекомендуемая структура проекта (может отличаться в зависимости от проекта и согласований)
- **/** - папка проекта
- **/assets** - директория расположения графических ресурсов
- **/tools/** - все необходимые инструменты для проекта
- **/docs** - документация проекта
- **/env** - папка, с внешними переменными окружения
- **/lib** - код на Dart, Flutter-приложение
- **/app** - содержит основные настройки нашего приложения
- **/data** - общие поставщики данных
- **/domain** - общий слой
- **/presentation** - общий слой
- **/di** - файлы конфигурации зависимостей
- **/router** - все, что касается роутинга
- **/features** - фичи приложения, для каждой фичи создается отдельная папка
- **/feature_name** - подробнее см в разделе Структура feature папок
- **/data**
- **/domain**
- **/presentation**
- **/gen** - для сгенерированных файлов
- **/targets** - таргеты для сборок
- **/prod.dart** - сборка для prod
- **/dev.dart** - сборка разработки на моковых репозиториях
- **/stage.dart** - сборка для stage окружения
## Пример структуры feature папок
- **/data** - слой данных
- **/dto** - реализация DTO (data transfer object)
- **/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 (слой представления)
- **components** - 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

View File

@@ -1,63 +1,390 @@
Инструкция для AI-агента (ревью Flutter-кода) # Правила разработки Flutter проекта
Вы — строгий ревьюер кода Flutter-приложения по принципам **Clean Architecture**. Этот файл содержит правила и стандарты разработки для проекта. Все правила обязательны к соблюдению при написании кода.
Ваша задача — проводить ревью кода, выявлять ошибки и давать корректные рекомендации.
Bloc и Cubit должны находиться в слое domain.
Контекст (справочно, не включать в ответ):
- Архитектура: три слоя (presentation, domain, data), каждый в своей папке.
- State management: flutter_bloc.
- Навигация: go_router.
- HTTP: dio.
- Анализатор: flutter_lint_rules.
- Feature-first структура: lib/features/<feature_name>/{data,domain,presentation}.
--- **ВАЖНО:** Перед каждым PR необходимо отформатировать код (`dart format .`) и проверить анализатор на отсутствие сообщений (`dart analyze`).
## Обзор запроса на вытягивание
1. В начале ответа укажите решение: **«Принять»** или **«Отклонить»**.
2. Укажите оценку: **Оценка: X/100** (X — фактический балл).
3. Кратко и строгим тоном перечислите ключевые проблемы:
- Архитектура (слои `presentation`, `domain`, `data`).
- Принципы **DRY, KISS, SOLID**.
- Разделение ответственности (BLoC, репозитории, DTO, UI).
- Безопасность (`dio`, SSL, валидация данных).
- Кодстайл и соглашения (`flutter_lint_rules`).
- Цикломатическая сложность: избегать чрезмерно сложных функций и классов (оптимально ≤ 10).
4. При необходимости предоставьте исправленный фрагмент кода или улучшенное решение.
5. Ответ должен быть в **Markdown** и полностью на **русском языке**.
--- ---
## Критерии оценки # Стиль кода
- **Чистая архитектура**: корректное разделение слоёв, отсутствие Flutter-зависимостей в `domain`.
- **KISS**: минимальная сложность и читаемость решений.
- **DRY**: отсутствие дублирования логики, использование утилит/виджетов.
- **SOLID**: правильная декомпозиция классов и интерфейсы вместо жёстких связей.
- **Безопасность**: корректная работа с API, валидация данных.
- **Кодстайл**: именование, структура файлов и папок.
- **Цикломатическая сложность**: методы и классы должны быть простыми, без избыточных ветвлений.
## Именование
--- ### Интерфейсы
## Пример ответа Все интерфейсы в приложении должны начинаться с заглавной буквы "**I**".
**Отклонить**
**Оценка: 58/100** Примеры: **IAuthRepository**, **IProfileRepository**, **IMainRunner** и т.д.
- Нарушен принцип DRY: HTTP-запрос продублирован в двух репозиториях.
- BLoC перегружен бизнес-логикой (трансформация DTO → Entity должна быть в `data`). Таким образом, сразу видно, что работаешь с интерфейсом.
- Domain-слой содержит зависимость от Flutter — это недопустимо.
- Отсутствует обработка ошибок и валидация данных в `dio`. Пример:
**Исправленный фрагмент:**
```dart ```dart
// Вместо дублирования запроса используем общий DataSource /// Интерфейс - **IUserRepository**
class UserRemoteDataSource { abstract interface class IUserRepository {}
final Dio dio;
UserRemoteDataSource(this.dio);
Future<UserEntity> fetchUser(String id) async { /// Основная реализация (prod и stage окружения)
final response = await dio.get('/users/$id'); class UserRepository implements IUserRepository {}
return UserDto.fromJson(response.data).toEntity();
} /// Иная реализация (мок, локальное хранилище) должна содержать
/// постфикс функциональности:
/// - 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 = 'default';
```
или
```dart
final String userName = 'user';
```
## Виджеты
Виджеты именуются 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
---
# Ведение документации и комментариев
## Документация
### Основные правила ведения документации в проекте
- Документация оформляется над описываемым объектом с использованием `///`
- Документацией необходимо покрывать все классы, конструкторы, поля, геттеры, сеттеры, методы, фабрики, все кастомные объекты
- Документация должна:
- указывать на назначение объекта
- содержать исчерпывающее описание объекта
- быть краткой и емкой
- быть понятной для любого разработчика
### Шаблоны и примеры документации объектов
#### Документация классов
```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 необходимо оставлять на тех участках кода, которые требуют дальнейшей доработки
- Если известно, в рамках какой задачи будет доработан помечаемый участок кода, ссылку на задачу необходимо оставить в скобках
Пример:
```dart
// TODO(username): Оптимизировать алгоритм сортировки
```
---
# Ведение проекта в git
## Создание commits/pull-request
- Язык описания PR - Русский
- Описание должно отражать краткую суть изменений
- Коммит/PR должен содержать:
- исчерпывающую информацию об изменениях
- ссылку на задачу в таск-трекер
- Перечисление deprecated-кода (если есть)
### Типы коммитов согласно convention
- **feat**: — новая функция
- **fix**: — исправление ошибок
- **refactor**: — Изменение кода, которое не исправляет ошибку и не добавляет функции (рефакторинг кода)
- **build**: — изменения, влияющие на систему сборки или внешние зависимости (примеры областей (scope): android, ios, linux и так далее)
- **docs**: — изменения только в документации
- **chore**: — добавление/обновление/настройка инструментов и библиотек (пример: pubspec.yaml)
- **test**: — добавление недостающих тестов или исправление существующих тестов
- **ci**: — изменения в файлах конфигурации и скриптах CI (примеры областей: папка CI)
# Структура проекта
Рекомендуемая структура проекта (может отличаться в зависимости от проекта и согласований)
- **/** - папка проекта
- **/assets** - директория расположения графических ресурсов
- **/tools/** - все необходимые инструменты для проекта
- **/docs** - документация проекта
- **/env** - папка, с внешними переменными окружения
- **/lib** - код на Dart, Flutter-приложение
- **/app** - содержит основные настройки нашего приложения
- **/data** - общие поставщики данных
- **/domain** - общий слой
- **/presentation** - общий слой
- **/di** - файлы конфигурации зависимостей
- **/router** - все, что касается роутинга
- **/features** - фичи приложения, для каждой фичи создается отдельная папка
- **/feature_name** - подробнее см в разделе Структура feature папок
- **/data**
- **/domain**
- **/presentation**
- **/gen** - для сгенерированных файлов
- **/targets** - таргеты для сборок
- **/prod.dart** - сборка для prod
- **/dev.dart** - сборка разработки на моковых репозиториях
- **/stage.dart** - сборка для stage окружения
## Пример структуры feature папок
- **/data** - слой данных
- **/dto** - реализация DTO (data transfer object)
- **/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 (слой представления)
- **components** - 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