diff --git a/.cursorrules b/.cursorrules index 6ca7e36..685a117 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,64 +1,389 @@ -# Правила для Cursor AI +# Правила разработки Flutter проекта -## Соглашение о коммитах +Этот файл содержит правила и стандарты разработки для проекта. Все правила обязательны к соблюдению при написании кода. -При генерации сообщений коммитов ВСЕГДА используй следующий формат: -`<тип>(<контекст1>,<контекст2>,...): <короткое описание>` +**ВАЖНО:** Перед каждым PR необходимо отформатировать код (`dart format .`) и проверить анализатор на отсутствие сообщений (`dart analyze`). -Для Pull Request формат: -`<тип>(<контекст1>,<контекст2>,...): <короткое описание>` +--- -Где: -- `<тип>` - тип коммита (см. ниже) -- `<контекст>` - модули/компоненты, которые изменяются (можно указать несколько через запятую) -- `<короткое описание>` - краткое описание изменений на русском языке +# Стиль кода -### Типы коммитов согласно convention: +## Именование -- **feat** - новая функция -- **fix** - исправление ошибок -- **refactor** - изменение кода, которое не исправляет ошибку и не добавляет функции (рефакторинг кода) -- **build** - изменения, влияющие на систему сборки или внешние зависимости (примеры областей: android, ios, linux и так далее) -- **docs** - изменения только в документации -- **chore** - добавление/обновление/настройка инструментов и библиотек (пример: pubspec.yaml) -- **test** - добавление недостающих тестов или исправление существующих тестов -- **ci** - изменения в файлах конфигурации и скриптах CI (примеры областей: папка CI) +### Интерфейсы -### Контекст (scope): +Все интерфейсы в приложении должны начинаться с заглавной буквы "**I**". -Указывай модуль или компонент, который изменяется. Можно указать несколько через запятую: -- `app` - основное приложение -- `di` - dependency injection -- `auth` - аутентификация -- `api` - API endpoints -- `db` - база данных -- `config` - конфигурация -- `i18n` - интернационализация -- `scripts` - скрипты -- `pubspec` - зависимости проекта -- `android`, `ios`, `linux` - платформы -- другие модули проекта +Примеры: **IAuthRepository**, **IProfileRepository**, **IMainRunner** и т.д. -### Примеры правильных коммитов: +Таким образом, сразу видно, что работаешь с интерфейсом. -- `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 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 -- Следуй 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 diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b5a0dfa..5583e1d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -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//{data,domain,presentation}. +Этот файл содержит правила и стандарты разработки для проекта. Все правила обязательны к соблюдению при написании кода. ---- -## Обзор запроса на вытягивание -1. В начале ответа укажите решение: **«Принять»** или **«Отклонить»**. -2. Укажите оценку: **Оценка: X/100** (X — фактический балл). -3. Кратко и строгим тоном перечислите ключевые проблемы: - - Архитектура (слои `presentation`, `domain`, `data`). - - Принципы **DRY, KISS, SOLID**. - - Разделение ответственности (BLoC, репозитории, DTO, UI). - - Безопасность (`dio`, SSL, валидация данных). - - Кодстайл и соглашения (`flutter_lint_rules`). - - Цикломатическая сложность: избегать чрезмерно сложных функций и классов (оптимально ≤ 10). - -4. При необходимости предоставьте исправленный фрагмент кода или улучшенное решение. -5. Ответ должен быть в **Markdown** и полностью на **русском языке**. +**ВАЖНО:** Перед каждым PR необходимо отформатировать код (`dart format .`) и проверить анализатор на отсутствие сообщений (`dart analyze`). --- -## Критерии оценки -- **Чистая архитектура**: корректное разделение слоёв, отсутствие Flutter-зависимостей в `domain`. -- **KISS**: минимальная сложность и читаемость решений. -- **DRY**: отсутствие дублирования логики, использование утилит/виджетов. -- **SOLID**: правильная декомпозиция классов и интерфейсы вместо жёстких связей. -- **Безопасность**: корректная работа с API, валидация данных. -- **Кодстайл**: именование, структура файлов и папок. -- **Цикломатическая сложность**: методы и классы должны быть простыми, без избыточных ветвлений. +# Стиль кода +## Именование ---- +### Интерфейсы -## Пример ответа -**Отклонить** -**Оценка: 58/100** -- Нарушен принцип DRY: HTTP-запрос продублирован в двух репозиториях. -- BLoC перегружен бизнес-логикой (трансформация DTO → Entity должна быть в `data`). -- Domain-слой содержит зависимость от Flutter — это недопустимо. -- Отсутствует обработка ошибок и валидация данных в `dio`. +Все интерфейсы в приложении должны начинаться с заглавной буквы "**I**". + +Примеры: **IAuthRepository**, **IProfileRepository**, **IMainRunner** и т.д. + +Таким образом, сразу видно, что работаешь с интерфейсом. + +Пример: -**Исправленный фрагмент:** ```dart -// Вместо дублирования запроса используем общий DataSource -class UserRemoteDataSource { - final Dio dio; - UserRemoteDataSource(this.dio); +/// Интерфейс - **IUserRepository** +abstract interface class IUserRepository {} - Future fetchUser(String id) async { - final response = await dio.get('/users/$id'); - return UserDto.fromJson(response.data).toEntity(); - } +/// Основная реализация (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 = '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 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