Структурирование проекта

Lino был разработан для упрощения создания масштабируемых и модульных проектов эффективно. Он предлагает хорошо структурированное решение с четким разделением обязанностей между слоями и готов к росту вместе с развитием вашего проекта.


При создании проекта с помощью Lino вы создаёте .NET-решение, организованное в соответствии с лучшими практиками архитектуры и модульности, с акцентом на производительность, масштабируемость и простоту обслуживания.

Создание нового проекта

Команда lino project облегчает создание новых проектов .NET простым и эффективным способом. С помощью этой команды вы можете настроить структуру проекта, выбрать необходимые зависимости и задать параметры языка и инфраструктуры.

Для создания нового проекта используйте следующую команду:

lino project new

Во время выполнения интерфейс командной строки запросит следующую информацию:

  • Пространство имен проекта: Определяет основное пространство имен решения.
  • Отображаемое имя: Дружественное имя, отображаемое в интерфейсах.
  • Язык программирования: В настоящее время поддерживается только C# (.NET).
  • Стек разработки: В настоящее время .NET 9 с Aspire.
  • Использовать анализаторы кода? Выберите Да или Нет.
  • Использовать распределенный кэш? Выберите Да или Нет.
  • Использовать асинхронную коммуникацию? Выберите Да или Нет.
  • Язык данных: Определяет язык, используемый для имен сущностей и других данных в системе.
  • Поддерживаемые языки приложения: Позволяет добавить поддержку до 10 языков для интернационализации (i18n).
  • Язык по умолчанию: Определяет основной язык, используемый в API, сообщениях, валидациях и пользовательском интерфейсе.

После подтверждения информации Lino автоматически создаст структуру проекта, как показано ниже:

MyApp/
├── MyApp.sln
├── src/
│   ├── Aspire/
│   │   ├── AppHost/
│   │   │   └── MyApp.AppHost.csproj
│   │   └── ServiceDefaults/
│   │       └── MyApp.ServiceDefaults.csproj
│   └── Services/
│       └── Shared/
│           ├── API/
│           │   └── MyApp.Shared.API.csproj
│           ├── Application/
│           │   └── MyApp.Shared.Application.csproj
│           ├── Domain/
│           │   └── MyApp.Shared.Domain.csproj
│           ├── Infrastructure/
│           │   └── MyApp.Shared.Infrastructure.csproj
│           └── Infrastructure.Persistence/
│               └── MyApp.Shared.Infrastructure.Persistence.csproj
└── tests/
    

Анализаторы кода

Статические анализаторы кода — это мощные инструменты, которые помогают обеспечить качество и согласованность кода в процессе разработки. Они делают это, проверяя исходный код без необходимости выполнения, выявляя ошибки, проблемы со стилем и другие несоответствия.

Когда вы решаете включить анализаторы кода при создании проекта, интерфейс командной строки автоматически настроит следующие пакеты:

  • StyleCop.Analyzers: Выполняет проверки стиля кода, такие как форматирование отступов, пробелов и соглашений по именованию.
  • SonarAnalyzer.CSharp: Набор правил для обеспечения качества и безопасности кода, который помогает выявлять общие ошибки и потенциальные уязвимости в коде.
  • Roslynator.Analyzers: Предлагает разнообразные правила качества и улучшений для кода C#, помогая находить возможности для рефакторинга и оптимизации.

Преимущества анализаторов кода:

  • Улучшение качества: Помогают поддерживать код чистым, читаемым и свободным от распространенных проблем.
  • Предотвращение ошибок: Обнаруживают ошибки до их выполнения, позволяя разработчику исправить их на раннем этапе.
  • Стандартизация: Обеспечивают соблюдение всех разработчиков одинаковых соглашений и правил стиля, улучшая согласованность кода.
  • Поддержка рефакторинга: Помогают с рефакторингом кода, предлагая улучшения.

Включив анализаторы кода, вы сможете проактивно улучшить качество вашего кода и снизить риски сбоев в рабочем окружении.

Распределенный кэш

Распределенный кэш — это техника, используемая для улучшения производительности и масштабируемости приложений, путем хранения часто запрашиваемых данных в кэш-системе, которая находится отдельно от базы данных. Это позволяет экземплярам приложения эффективно делиться кэшированными данными, обеспечивая высокую доступность и снижая время отклика.

Если вы решите активировать распределенный кэш при создании проекта, Redis будет интегрирован в ваш контейнер Aspire, предлагая систему кэширования с высокой доступностью.

Преимущества распределенного кэша:

  • Улучшение производительности: Снижает время отклика запросов, минимизируя доступ к базе данных.
  • Масштабируемость: Позволяет масштабировать приложение горизонтально, так как кэш может быть доступен из разных экземпляров.
  • Высокая доступность: С Redis кэш остается доступным даже при сбоях, обеспечивая надежную систему для распределенных приложений.
  • Снижение затрат: Уменьшает нагрузку на базу данных и систему, сокращая необходимость в повторных вычислениях для одинаковых запросов.

Включив распределенный кэш, вы значительно улучшите производительность вашего приложения, обеспечив более быстрые отклики для пользователей и снижая нагрузку на серверы.

Асинхронная коммуникация

Асинхронная коммуникация — это подход, который позволяет системам и компонентам обмениваться данными без блокировки выполнения других задач. Это особенно полезно в распределенных системах и в условиях высокой нагрузки, где эффективность и устойчивость критичны.

Если вы решите активировать асинхронную коммуникацию, RabbitMQ будет интегрирован в ваш проект, а MassTransit будет настроен для упрощения работы с асинхронной коммуникацией в приложении.

Преимущества асинхронной коммуникации:

  • Улучшенная производительность: Позволяет выполнять операции параллельно, не блокируя выполнение других задач.
  • Масштабируемость: Облегчает масштабирование системы, позволяя обрабатывать большие объемы данных и пользователей без потери производительности.
  • Устойчивость: В случае временных сбоев асинхронная коммуникация позволяет повторно обработать или сохранить сообщения для последующей обработки.
  • Разделение компонентов: Системы могут обмениваться данными без необходимости ждать немедленных ответов, что повышает гибкость и организацию.

Интеграция с RabbitMQ и использование MassTransit делает коммуникацию между компонентами более эффективной и надежной, помогая обеспечить масштабируемость и гибкость вашего приложения.

Следующие шаги

Теперь, когда вы создали свой проект .NET с Lino, откройте его в вашем любимом редакторе кода. Вы можете использовать Visual Studio, Visual Studio Code или любую другую IDE по вашему выбору.

Открыв проект, вы можете начать добавлять и настраивать сервисы, которые составляют ваше приложение. Это следующий шаг в процессе разработки.

В следующем разделе мы покажем, как создать и настроить эти сервисы в вашем новом проекте, подготавливая его к росту организованным и масштабируемым образом в зависимости от потребностей вашего приложения.

Создание и управление сервисами

После создания проекта следующим шагом является добавление сервисов. Lino предлагает простой и интуитивно понятный способ создания сервисов, которые могут использоваться в монолитных системах или архитектурах микросервисов.

Для создания нового сервиса используйте следующую команду:

lino service new

Во время выполнения команда CLI запросит следующую информацию:

  • Пространство имен сервиса: Определяет имя и пространство имен сервиса.
  • Отображаемое имя: Удобное имя, отображаемое в интерфейсах.
  • Тип сервиса: Выберите между Простым или Модульным.
  • База данных: Выберите между PostgreSQL или SQL Server.

Если выбран тип сервиса Простой, также будут запрашиваться следующие данные:

  • Архитектурный стиль: В настоящее время только Clean Architecture.
  • Использовать Strongly Typed ID? Выберите между Да или Нет.

Типы сервисов

Простой сервис: Простой сервис имеет более компактную структуру, подходит для монолитных систем или проектов микросервисов, где каждый сервис выполняет независимую роль.

Модульный сервис: Для более крупных систем, требующих лучшей организации и масштабируемости, можно выбрать модульный сервис. Этот тип позволяет разделить сервис на меньшие и более специфические модули, облегчая обслуживание и расширение системы.

Будь то простой или модульный сервис, база данных будет уникальной для каждого сервиса. Архитектура и использование Strongly Typed IDs применяются к простым сервисам. В случае модульных сервисов решение будет приниматься на уровне каждого модуля внутри сервиса.

Структура Lino гибка, позволяя создавать как простые, так и модульные сервисы в одном проекте.

Архитектурный стиль

Lino уже применяет Clean Architecture ко всем сервисам. Это гарантирует, что ваше приложение будет следовать хорошо структурированной архитектуре, обеспечивая разделение обязанностей и упрощая обслуживание и масштабируемость.

Преимущества Clean Architecture:

  • Разделение: Логика бизнеса независима от технических деталей, что дает большую гибкость и тестируемость.
  • Обслуживаемость: Поскольку слои четко разделены, проще вносить изменения, не влияя на другие части системы.
  • Тестируемость: Разделение забот упрощает создание юнит- и интеграционных тестов для каждого слоя независимо.
  • Масштабируемость: Проект проще масштабировать, так как компоненты могут быть изменены или заменены, не затрагивая бизнес-логику.

Если вы выберете создание сервиса типа Простой, используя реализацию Clean Architecture, проект будет сгенерирован со следующей структурой:

MyApp/
├── MyApp.sln
├── src/
│   ├── Aspire/
│   │   ├── AppHost/
│   │   │   └── MyApp.AppHost.csproj
│   │   └── ServiceDefaults/
│   │       └── MyApp.ServiceDefaults.csproj
│   ├── Integrations/
│   │   └── Internal/
│   │       └── MySimpleService/
│   │           └── Http/
│   │               ├── Clients/
│   │               │   └── MyApp.Integrations.MySimpleService.Http.Clients.csproj
│   │               └── Contracts/
│   │                   └── MyApp.Integrations.MySimpleService.Http.Contracts.csproj
│   └── Services/
│       ├── Shared/
│       │   ├── API/
│       │   │   └── MyApp.Shared.API.csproj
│       │   ├── Application/
│       │   │   └── MyApp.Shared.Application.csproj
│       │   ├── Domain/
│       │   │   └── MyApp.Shared.Domain.csproj
│       │   ├── Infrastructure/
│       │   │   └── MyApp.Shared.Infrastructure.csproj
│       │   └── Infrastructure.Persistence/
│       │       └── MyApp.Shared.Infrastructure.Persistence.csproj
│       └── MySimpleService/
│           ├── API/
│           │   └── MyApp.MySimpleService.API.csproj
│           ├── Application/
│           │   └── MyApp.MySimpleService.Application.csproj
│           ├── Domain/
│           │   └── MyApp.MySimpleService.Domain.csproj
│           ├── Infrastructure/
│           │   └── MyApp.MySimpleService.Infrastructure.csproj
│           ├── Infrastructure.Persistence/
│           │   └── MyApp.MySimpleService.Infrastructure.Persistence.csproj
│           └── IntegrationEvents/
│               └── MyApp.MySimpleService.IntegrationEvents.csproj
└── tests/
    └── Services/
        └── MySimpleService/
            ├── IntegrationTests/
            │   └── MyApp.MySimpleService.IntegrationTests.csproj
            └── UnitTests/
                └── MyApp.MySimpleService.UnitTests.csproj
    

При выборе сервиса типа Модульный проект будет иметь следующую структуру, позволяя добавлять новые модули гибко и организованно по мере разработки сервиса:

MyApp/
├── MyApp.sln
├── src/
│   ├── Aspire/
│   │   ├── AppHost/
│   │   │   └── MyApp.AppHost.csproj
│   │   └── ServiceDefaults/
│   │       └── MyApp.ServiceDefaults.csproj
│   └── Services/
│       ├── Shared/
│       │   ├── API/
│       │   │   └── MyApp.Shared.API.csproj
│       │   ├── Application/
│       │   │   └── MyApp.Shared.Application.csproj
│       │   ├── Domain/
│       │   │   └── MyApp.Shared.Domain.csproj
│       │   ├── Infrastructure/
│       │   │   └── MyApp.Shared.Infrastructure.csproj
│       │   └── Infrastructure.Persistence/
│       │       └── MyApp.Shared.Infrastructure.Persistence.csproj
│       └── MyModularService/
│           ├── Host/
│           │   └── MyApp.MyModularService.Host.csproj
│           ├── Infrastructure/
│           │   └── MyApp.MyModularService.Infrastructure.csproj
│           └── Modules/
└── tests/
    

Strongly Typed ID

Strongly Typed ID — это подход, направленный на улучшение безопасности и ясности кода, гарантируя, что типы идентификаторов (ID) будут более специфичными и строго типизированными, что предотвращает использование общих типов, таких как int или guid, для представления уникальных сущностей.

С Strongly Typed ID, вместо использования общих типов, таких как целое число для представления идентификатора пользователя, вы создаете конкретный тип для ID пользователя. Это помогает избежать распространенных ошибок, таких как неправильное использование ID различных типов в неверных контекстах.

Преимущества использования Strongly Typed IDs:

  • Безопасность типов: Гарантирует правильное использование ID, предотвращая смешивание различных типов идентификаторов, таких как ID пользователей и ID продуктов.
  • Ясность: Код становится более ясным, так как каждый тип ID явно представлен конкретным классом.
  • Упрощение рефакторинга: Если тип идентификатора нужно изменить, вы изменяете только конкретный тип ID, и остальная часть кода остается безопасной.
  • Предотвращение ошибок: Снижает вероятность ошибок, связанных с неправильным использованием общих идентификаторов в неверных контекстах.

Следующие шаги для модульных сервисов

После создания модульного сервиса следующим шагом будет добавление модулей в него. Модули позволяют организовать бизнес-логику и инфраструктуру независимо внутри сервиса, делая систему более масштабируемой и организованной.

В следующем разделе мы рассмотрим, как создавать и управлять модулями внутри модульного сервиса. Это позволит вам максимально использовать гибкость и масштабируемость, которые предлагают модульные сервисы.

Создание и управление модулями

После создания модульного сервиса следующим шагом является добавление в него модулей. Модули позволяют организовать бизнес-логику независимо, обеспечивая еще большую масштабируемость и организацию системы.

Чтобы создать новый модуль, используйте следующую команду:

lino module new

Во время выполнения команда CLI запросит следующую информацию:

  • Сервис: Определяет, для какого сервиса будет создан новый модуль.
  • Пространство имен модуля: Определяет имя и пространство имен модуля.
  • Отображаемое имя: Дружественное имя, отображаемое в интерфейсах.
  • Архитектурный стиль: В настоящее время только Clean Architecture.
  • Использовать Strongly Typed ID? Выберите между Да или Нет.

В конце Lino создаст новый модуль, сохраняя структуру вашего модульного сервиса:

MyApp/
├── MyApp.sln
├── src/
│   ├── Aspire/
│   │   ├── AppHost/
│   │   │   └── MyApp.AppHost.csproj
│   │   └── ServiceDefaults/
│   │       └── MyApp.ServiceDefaults.csproj
│   ├── Integrations/
│   │   └── Internal/
│   │       └── MyModularService/
│   │           └── MyModule/
│   │               └── Http/
│   │                   ├── Clients/
│   │                   │   └── MyApp.Integrations.MyModularService.MyModule.Http.Clients.csproj
│   │                   └── Contracts/
│   │                       └── MyApp.Integrations.MyModularService.MyModule.Http.Contracts.csproj
│   └── Services/
│       ├── Shared/
│       │   ├── API/
│       │   │   └── MyApp.Shared.API.csproj
│       │   ├── Application/
│       │   │   └── MyApp.Shared.Application.csproj
│       │   ├── Domain/
│       │   │   └── MyApp.Shared.Domain.csproj
│       │   ├── Infrastructure/
│       │   │   └── MyApp.Shared.Infrastructure.csproj
│       │   └── Infrastructure.Persistence/
│       │       └── MyApp.Shared.Infrastructure.Persistence.csproj
│       └── MyModularService/
│           ├── Host/
│           │   └── MyApp.MyModularService.Host.csproj
│           ├── Infrastructure/
│           │   └── MyApp.MyModularService.Infrastructure.csproj
│           └── Modules/
│               └── MyModule/
│                   ├── API/
│                   │   └── MyApp.MyModularService.MyModule.API.csproj
│                   ├── Application/
│                   │   └── MyApp.MyModularService.MyModule.Application.csproj
│                   ├── Domain/
│                   │   └── MyApp.MyModularService.MyModule.Domain.csproj
│                   ├── Infrastructure/
│                   │   └── MyApp.MyModularService.MyModule.Infrastructure.csproj
│                   ├── Infrastructure.Persistence/
│                   │   └── MyApp.MyModularService.MyModule.Infrastructure.Persistence.csproj
│                   └── IntegrationEvents/
│                       └── MyApp.MyModularService.MyModule.IntegrationEvents.csproj
└── tests/
    └── Services/
        └── MyModularService/
            └── Modules/
                └── MyModule/
                    ├── IntegrationTests/
                    │   └── MyApp.MyModularService.MyModule.IntegrationTests.csproj
                    └── UnitTests/
                        └── MyApp.MyModularService.MyModule.UnitTests.csproj

Структура базы данных

Важно отметить, что база данных связана с сервисом. В рамках модульного сервиса каждый модуль представлен собственным схемой в связанной базе данных. Такой подход обеспечивает изоляцию и организацию, без необходимости создавать несколько отдельных баз данных.

О независимости модулей

Так же, как и сервисы, не имеющие прямых зависимостей друг от друга, модули создаются как независимые проекты внутри сервиса.

Преимущества такого декомпозирования:

  • Изоляция: Каждый модуль может развиваться независимо, облегчая обслуживание и непрерывное совершенствование.
  • Организация: Приложение становится действительно модульным, соблюдая границы контекстов (Bounded Contexts) и способствуя хорошим практикам архитектуры программного обеспечения.
  • Гибкость: Позволяет добавлять, удалять или рефакторить модули, не затрагивая другие модули сервиса.
  • Тестируемость: Каждый модуль может быть протестирован изолированно, повышая надежность и качество системы.

Таким образом, мы завершаем процесс создания модулей. В следующих разделах мы рассмотрим, как структурировать внутренние элементы модуля, такие как сущности, объекты значений, перечисления, команды, запросы, API, интеграции и многое другое.

Произошла необработанная ошибка. Обновить 🗙