.NET в SDLC и лучшие ресурсы
Заключительная статья связывает всё воедино. Язык и фреймворк — лишь инструменты; ценность возникает, когда они встроены в здоровый жизненный цикл разработки ПО (SDLC): от идеи до работающего в проде и обслуживаемого сервиса. Разберём, как .NET проходит каждый этап, и дадим карту ресурсов для дальнейшего роста.
SDLC глазами .NET-инженера
- Требования и дизайн. Здесь решается граница сервисов, доменная модель (см. статью про архитектуру), контракты API (OpenAPI/Swagger — ASP.NET Core генерирует спеку автоматически). ADR (Architecture Decision Records) фиксируют «почему» решений.
- Разработка. Ветвление (обычно trunk-based или короткие feature-ветки), pull
request-ы, обязательное code review,
.editorconfigи анализаторы держат единый стиль без споров. - Тесты и CI. На каждый PR — сборка, формат, анализаторы, юнит- и интеграционные тесты (статья про тестирование). Красная сборка блокирует мёрж.
- Релиз и CD. Сборка иммутабельного артефакта (контейнера), продвижение по средам, выкатка (статья про деплой).
- Эксплуатация. Наблюдаемость, алерты, on-call, разбор инцидентов, обратная связь в требования. Цикл замыкается.
Ключевая идея DevOps: границы между этапами размываются, а инженер отвечает за фичу «от коммита до прода и дальше». .NET хорошо это поддерживает единым тулчейном.
Code review: на что смотреть
Ревью — не про стиль (это делают анализаторы), а про суть:
- Корректность и краевые случаи — что при null, пустой коллекции, отмене, гонке.
- Конкурентность — нет ли sync-over-async,
async void, потерянных Task, гонок (см. статью про конкурентность). Это самые дорогие баги. - Границы и зависимости — не течёт ли инфраструктура в домен, правильны ли времена жизни DI.
- Тесты — покрыта ли новая логика, проверяют ли тесты поведение, а не реализацию.
- Наблюдаемость — логируются ли ключевые события структурно, есть ли метрики/трейсы для нового пути.
- Безопасность — валидация ввода, нет секретов в коде, параметризованные запросы.
Держите PR маленькими — большие ревью проходят формально и пропускают баги.
Пример CI/CD пайплайна
Ниже — реалистичный GitHub Actions workflow: сборка, проверки качества, тесты, сборка и публикация контейнера. Тот же принцип переносится на GitLab CI, Azure Pipelines.
name: ci-cd
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
packages: write
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
# Воспроизводимое восстановление по lock-файлу
- run: dotnet restore --locked-mode
# Качество: формат и анализаторы (TreatWarningsAsErrors уже в csproj)
- run: dotnet format --verify-no-changes
- run: dotnet build -c Release --no-restore
# Тесты + покрытие (Testcontainers работает — Docker есть на runner'е)
- run: dotnet test -c Release --no-build --collect:"XPlat Code Coverage"
# Аудит уязвимостей в зависимостях — блокируем при находках
- run: dotnet list package --vulnerable --include-transitive 2>&1 | tee audit.txt
- run: if grep -q "has the following vulnerable" audit.txt; then exit 1; fi
publish-image:
needs: build-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '9.0.x' }
# Сборка образа средствами SDK, без Dockerfile
- run: |
dotnet publish src/MyApp.Api -c Release \
-t:PublishContainer \
-p:ContainerRegistry=ghcr.io \
-p:ContainerImageTag=${{ github.sha }}
Принципы хорошего пайплайна:
- Быстрая обратная связь. Держите PR-пайплайн в пределах нескольких минут; тяжёлое выносите в отдельные джобы/ночные прогоны.
- Один артефакт через все среды. Собрали образ один раз, тегировали SHA коммита, продвигаем один и тот же бинарник dev → staging → prod. Не пересобирайте на каждую среду.
- Иммутабельность и трассируемость. Тег = SHA коммита; всегда знаете, что именно в проде.
Релизные стратегии
- Semantic Versioning для библиотек/NuGet-пакетов; инструмент
MinVer/Nerdbank.GitVersioningвыводит версию из git-тегов автоматически. - Blue-Green — две среды, переключение трафика; мгновенный откат.
- Canary / поэтапная выкатка — новую версию сначала на 1–5% трафика, наблюдаем метрики, потом расширяем.
- Feature flags (например, через
Microsoft.FeatureManagement) — отделяют деплой от релиза: код в проде, но фича включается флагом. Позволяет катить чаще и безопаснее.
Общий принцип: деплой должен быть рутинным, обратимым и наблюдаемым событием, а не героическим ночным подвигом.
Безопасность цепочки зависимостей
Большинство кода в вашем приложении — не ваш, а из NuGet-пакетов. Это поверхность атаки.
- Аудит уязвимостей —
dotnet list package --vulnerable --include-transitiveв CI (см. пайплайн выше). Данные — из GitHub Advisory Database. - Lock-файлы +
--locked-mode— воспроизводимость и защита от неожиданной подмены транзитивной версии (статья про тулчейн). - Dependabot / Renovate — автоматические PR на обновление зависимостей.
- Проверка происхождения пакетов. Предпочитайте пакеты с подписью и от проверенных авторов; включите NuGet package signature validation. Опасайтесь тайпсквоттинга имён.
- SBOM (Software Bill of Materials) — генерируйте перечень зависимостей для аудита и соответствия требованиям.
- Секреты — никогда в коде/репозитории; сканеры секретов (
gitleaks) в пре-коммит и CI. В проде — Key Vault / Secrets Manager. - Статический анализ безопасности — SonarAnalyzer,
security-scan, GitHub CodeQL.
Безопасность — не отдельный этап в конце, а сквозная практика («shift left»): чем раньше поймали проблему, тем дешевле.
Управление зависимостями и версиями .NET во времени
Отдельная часть жизненного цикла — поддержание проекта в актуальном состоянии, чтобы он не превратился в легаси:
- Планируйте обновление .NET. Сидите на LTS (.NET 8), закладывайте миграцию на
следующую LTS в её окне поддержки. Обновление major-версии .NET обычно сводится к
смене
TargetFrameworkи прогону тестов — команда серьёзно относится к совместимости. - Инструмент апгрейда.
Upgrade Assistant/dotnet upgradeпомогает с миграцией старых проектов (в т.ч. с .NET Framework). - Держите зависимости свежими понемногу. Renovate/Dependabot и регулярные мелкие обновления дешевле, чем редкий болезненный «большой прыжок».
- Читайте release notes. Каждая версия .NET приносит перф «бесплатно» — часто простой ребилд на новом рантайме ускоряет сервис на десятки процентов.
Технический долг по версиям — это риск безопасности (устаревшие рантаймы перестают получать патчи) и найма (мало кто хочет работать с мёртвым стеком). Обновление — не роскошь, а гигиена.
Документация как часть SDLC
- API-контракты. ASP.NET Core генерирует OpenAPI-спеку; держите её актуальной, она — контракт с потребителями.
- ADR (Architecture Decision Records) — короткие markdown-записи «что решили и почему». Спасают будущую команду от археологии.
- README и runbook. Как запустить локально, как задеплоить, что делать при типовом инциденте. Runbook экономит часы во время сбоя в 3 часа ночи.
- XML-doc комментарии (
///) на публичном API библиотек — попадают в IntelliSense и генерируемую документацию.
Курированный список лучших ресурсов
Официальные (первоисточники)
- learn.microsoft.com/dotnet — документация; образцовое качество, всегда актуальна.
- devblogs.microsoft.com/dotnet — блог команды .NET; «почему» решений, ежегодные «Performance Improvements in .NET» от Stephen Toub.
- github.com/dotnet — исходники runtime, ASP.NET Core, EF Core. Читать код BCL — лучший способ учиться.
- .NET API browser — справочник по всему BCL.
Блоги экспертов
- Stephen Cleary — blog.stephencleary.com:
абсолютный референс по async/await,
ConfigureAwait, дедлокам,Channel. - Andrew Lock — andrewlock.net: ASP.NET Core «в глубину», серия «ASP.NET Core in Action» (и одноимённая книга).
- Steve Gordon — stevejgordon.co.uk: внутренности ASP.NET Core, HttpClientFactory, производительность.
- David Fowler — github.com/davidfowl/AspNetCoreDiagnosticScenarios:
обязательный
AsyncGuidance.md— грабли async в проде от архитектора ASP.NET Core. - Nick Chapsas — YouTube: Nick Chapsas: короткие практичные видео по современным фичам и производительности.
- Konrad Kokosa — tooslowexception.com: память и GC.
- Jimmy Bogard — jimmybogard.com: архитектура, MediatR, DDD-подходы.
- Vladimir Khorikov — enterprisecraftsmanship.com: тестирование, DDD, Result vs исключения.
- Milan Jovanović — milanjovanovic.tech: архитектура, чистый код, практичные разборы.
Книги
- «C# in Depth», Jon Skeet — как язык устроен изнутри.
- «Dependency Injection Principles, Practices, and Patterns», Mark Seemann & Steven van Deursen — эталон по DI и архитектуре.
- «Pro .NET Memory Management», Konrad Kokosa — всё про GC и память.
- «ASP.NET Core in Action», Andrew Lock — веб-разработка на .NET.
- «Unit Testing Principles, Practices, and Patterns», Vladimir Khorikov — как писать тесты, которые не мешают, а помогают.
Сообщество и новости
- The .NET Docs Show и .NET Community Standup (стримы команды на YouTube).
- Рассылки: The .NET Weekly (Milan Jovanović), .NET News (Cezary Piątek).
- Reddit
r/dotnet,r/csharp; конференции NDC, .NET Conf (бесплатная, онлайн).
Заключение курса
Вы прошли путь от установки SDK до эксплуатации наблюдаемого сервиса. Главное, что стоит унести:
- Учите среду исполнения, а не только синтаксис — CLR и GC объясняют поведение.
- Включайте всё, что двигает ошибки в компайл-тайм: nullable, анализаторы,
TreatWarningsAsErrors. - Async — про освобождение потоков; уважайте
CancellationTokenи избегайте sync-over-async. - Держите домен чистым, зависимости — инвертированными, конфигурацию — типизированной.
- Тестируйте пирамидой, наблюдайте тремя столпами, релизьте часто и обратимо.
Дальше — практика. Возьмите реальный сервис, пройдите весь цикл сами, читайте первоисточники из списка выше и код BCL. Так растёт инженер, а не только кодер.
Что дальше
Вернитесь к обзору курса, чтобы перечитать разделы, к которым захочется углубиться, или откройте официальную документацию learn.microsoft.com/dotnet и начните свой проект.