Жизненный цикл ПО

От требований до вывода из эксплуатации: проектирование, разработка, тестирование, релиз, CI/CD и сопровождение

Вячеслав Федоров

Лекция 8

Разработка и применение ПО

в физических исследованиях

v1.0

Содержание

Стадии жизненного цикла программы

01

Анализ и проектирование

02

Разработка

03

Тестирование

04

Релиз

05

CI/CD

06

Сопровождение

Цель лекции

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

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

Стадии

жизненного цикла

СтадияВопрос, который она закрывает
Анализчто требуется построить
Проектированиекак это будет устроено
Разработкакод и совместная работа над ним
Тестированиеполучилось ли задуманное
Релизкак продукт доходит до пользователя
Сопровождениекто следит за работающей системой
Завершениекак снять продукт с поддержки

Пояснение

Стадии повторяются циклами: требования, выяснившиеся после релиза, запускают цикл заново.

Для физика

У научного кода цикл короче, а роли заказчика, аналитика и приёмщика играет сам разработчик.

Важно

Цена ошибки растёт со стадией: неверно понятое требование обнаруживается на защите.

Анализ и проектирование

Требования, design-review, security-review, MVP

01

Анализ и проектирование

Разработка

Тестирование

Релиз

CI/CD

Сопровождение

Анализ

требований

Часть SRSСодержание
Назначениецель документа и продукта, границы
Общее описаниепользователи, окружение, допущения
Конкретные требованияфункции, входы и выходы
Интерфейсыформаты данных, API, взаимодействие
Ограниченияпроизводительность, оборудование, стандарты
Атрибуты качестванадёжность, точность, сопровождаемость

Задачи этапа:

01

определение требований

02

постановка целей

03

планирование работ и ресурсов

04

согласование сроков

Пояснение

Стандарт IEEE 830-1998 отменён и заменён ISO/IEC/IEEE 29148; основное содержание документа сохранилось.

Проектирование

системы

Если задачу можно решить без написания кода, это лучшее решение

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

Для физика

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

Design-review

и security-review

РазборЧто обсуждаетсяКогда
design-reviewчто и зачем делается, сравнение с аналогами, roadmapдо начала разработки
security-reviewдоступ, данные, аутентификация, секретывсегда; особенно новый сервис, деньги, персональные данные

01

Мотивация

цели, заказчики, будущие пользователи

02

Аналоги

почему не подходят существующие решения

03

Суть предложения

устройство и интерфейсы

04

Roadmap

этапы и сроки

Важно

Самодельная проверка паролей — типичная уязвимость лабораторных сервисов.

MVP —

минимально жизнеспособный продукт

Минимально жизнеспособный продукт обладает минимальными, но достаточными функциями, чтобы им начали пользоваться первые потребители. Смысл — как можно раньше выяснить, тот ли продукт создаётся.

Для физика

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

Идея

анализ спектров с установки

MVP

одна команда, один формат, один график

Отзывы пользователей

реальные потребности

Следующая версия

форматы, настройки, отчёт

Разработка

Контроль версий, ветвление, ревью кода, требования к коду, монорепозиторий

02

Анализ и проектирование

Разработка

Тестирование

Релиз

CI/CD

Сопровождение

Системы

контроля версий

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

ГодыСистемы
1960-еIEBUPDTE
1970-еSCCS
1980-еRCS, CVS
2000-еSubversion, Git, Mercurial
ЦентрализованныеРаспределённые
историяна сервереу каждого участника
коммит без сетинетда
примерыCVS, SubversionGit, Mercurial

Пояснение

Git написан Линусом Торвальдсом в 2005 году для разработки ядра Linux взамен BitKeeper.

Ветвление

в Git

A

B

C

D

E

M

main

feature

merge

git switch -c feature   # новая ветка
git commit -m 'Новая функция'
git switch main
git merge feature       # слияние

Пояснение

Ветка — указатель на коммит: создание мгновенно и ничего не копирует, поэтому ветвиться и сливать можно постоянно.

Методики

ветвления

СхемаВеткиДля чего
Git Flowmain, develop, feature, release, hotfixредкие версионированные релизы
GitHub Flowmain и короткие ветки через pull requestчастые выкатки, небольшие команды
GitLab FlowGitHub Flow плюс ветки окружений или релизоввыкатка через стенды
Trunk-basedкороткоживущие ветки, слияние ежедневноCI и feature-флаги

Пояснение

Методика ветвления упорядочивает добавление и публикацию изменений в общем репозитории.

Для физика

Научной группе почти всегда достаточно GitHub Flow: main всегда рабочая, изменения — через pull request.

Демонстрация:

ветки и конфликт

01

Граф веток: main, calib, docs

02

Слияние docs: перемотка вперёд

03

Слияние calib: конфликт в config.toml

04

Маркеры конфликта в файле

05

Выбор версии calib и коммит слияния

06

Итоговый граф с коммитом слияния

Что наблюдается

Обе ветки изменили energy_mev; Git остановил слияние и пометил спорные строки, решение принял человек.

root@lab — запись со стенда

Pull request

и ревью кода

Ветка задачи

коммиты с понятными сообщениями

Pull request

описание: что и зачем

Проверки CI

линтер и тесты

Ревью

обсуждение и правки

Слияние в main

01

Видимость

правка видна всей команде

02

Обсуждение

до попадания кода в main

03

Проверки

к pull request привязаны автоматические проверки

Пояснение

Ревью распространяет знание о проекте: код перестаёт быть понятным одному человеку.

Требования

к коду

ПравилоСодержание
PEP 8стиль: отступы, имена, пробелы
длина строки79 символов, задаётся в pyproject.toml
импортыотсортированы, неиспользуемых нет
docstringPEP 257: что делает функция
именапо смыслу, по-английски; константы вместо магических чисел

Пояснение

Большинство правил проверяют линтеры и форматтеры — ruff, flake8, black — в редакторе и в CI.

# .git/hooks/pre-commit
#!/bin/sh
ruff check . && python3 -m pytest -q
 
# pyproject.toml
[tool.ruff]
line-length = 79

Важно

black и ruff format по умолчанию форматируют по 88 символов: длину задают явно.

Демонстрация:

хук pre-commit

01

Хук: ruff и pytest перед коммитом

02

Функция momentum с лишним import os

03

Коммит отклонён: F401

04

Удаление импорта: ruff check --fix

05

Коммит после проверок и тестов

06

История с новым коммитом

Что наблюдается

Хук не пропустил коммит из-за неиспользуемого импорта; после исправления ruff и тесты прошли, коммит создан.

root@lab — запись со стенда

Монорепозиторий

или много репозиториев

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

Для физика

В одном репозитории хранят то, что выпускается и версионируется вместе; независимые части — отдельно.

Тестирование

Статический анализ, модульные, интеграционные, функциональные и нагрузочные тесты

03

Анализ и проектирование

Разработка

Тестирование

Релиз

CI/CD

Сопровождение

Виды

тестирования

нагрузочные

функциональные

интеграционные

модульные

статический анализ

01

Внизу

дешёвые и быстрые проверки, их много, запуск на каждое изменение

02

Вверху

дорогие и медленные проверки, их мало, запуск перед релизом

Пояснение

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

Статический

анализ

Анализатор читает исходный код, не запуская программу, и ищет ошибки, отклонения от стиля и уязвимости: неиспользуемые имена, опечатки, сравнение с None через ==, голые except.

ИнструментПроверяет
ruff, flake8стиль и очевидные ошибки
pylintсомнительные конструкции
mypyтипы по аннотациям
banditтиповые уязвимости

«Самое важное, что я сделал как программист за последние годы, — начал агрессивно применять статический анализ кода»

— Джон Кармак, 2011

Пояснение

Метрики качества: покрытие тестами, цикломатическая сложность, доля дублированного кода.

Демонстрация:

статический анализ ruff

01

Правила в pyproject.toml: E4, E7, E9, F, I

02

ruff check: восемь нарушений

03

ruff check --fix: четыре исправлены автоматически

04

Оставшиеся четыре: F403, E711, E722, F405

05

ruff format --diff: пустые строки по PEP 8

Что наблюдается

Четыре нарушения исправлены автоматически; импорт со звёздочкой, сравнение с None, голый except и неопределённое имя требуют решения человека.

root@lab — запись со стенда

Модульные

тесты

import pytest
from physics import C, gamma
 
@pytest.mark.parametrize('beta, expected',
    [(0.0, 1.0), (0.6, 1.25), (0.8, 5 / 3)])
def test_gamma(beta, expected):
    assert gamma(beta * C) == pytest.approx(expected)
 
def test_gamma_rejects_light_speed():
    with pytest.raises(ValueError):
        gamma(C)

Что проверяетсяПример
известный ответγ(0,6c) = 1,25; γ(0,8c) = 5/3
предельный случайv ≪ c: E = mv²/2
инвариантсохранение энергии, симметрия
некорректный входv ≥ c → ValueError

Важно

Сравнение вещественных чисел — с допуском: pytest.approx, а не ==.

Демонстрация:

тесты pytest

01

Тесты: известные ответы, отказ при v = c, классический предел

02

Первый прогон: три неудачи из пяти

03

Исправление γ: квадрат β

04

Оставшаяся неудача: v ≪ c, 500 006,9 вместо 500 000

05

Устойчивая формула mv²γ²/(γ + 1)

06

Прогон без неудач: пять тестов из пяти

Что наблюдается

Тест предела нашёл потерю точности: γ − 1 при v = 1000 м/с вычисляется с относительной ошибкой 10⁻⁵.

root@lab — запись со стенда

Интеграционные

и функциональные тесты

01

Интеграционные

взаимодействие модулей между собой и с внешними системами: базой данных, файлами, сетью

02

Функциональные

сценарий целиком с точки зрения пользователя; вручную или автоматически, например Selenium

Пояснение

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

Для физика

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

Нагрузочное

тестирование

ПрофильЧто проверяет
loadожидаемая штатная нагрузка
stressнагрузка сверх расчётной
spikeрезкий всплеск и восстановление
soakштатная нагрузка часами и днями
breakpointрост нагрузки до предела системы

Пояснение

Инструменты: JMeter, Siege, Яндекс.Танк; на Python — locust.

Для физика

Сервис приёма данных с установки проверяют на пиковом потоке событий заранее, а не во время сеанса.

01

измерение производительности

02

проверка пиков и восстановления после них

03

планирование ресурсов

Демонстрация:

нагрузочный тест

01

Клиент: 100 запросов при 1–16 параллельных потоках

02

Запуск сервера в фоне: 20 мс на запрос, один поток

03

Пропускная способность — около 45 запросов/с

04

Рост задержки пропорционально числу потоков

Что наблюдается

Пропускная способность ограничена одной очередью — около 45 запросов/с; p50 выросла с 23 до 357 мс при 16 потоках.

root@lab — запись со стенда

Релиз

Стратегии развёртывания, контейнеры, feature-флаги, версии и релизные окна

04

Анализ и проектирование

Разработка

Тестирование

Релиз

CI/CD

Сопровождение

Стратегии

развёртывания

СтратегияКак устроенаПлюсМинус
blue-greenдве копии, переключение трафикамгновенный откатдвойные ресурсы
canaryновая версия для малой долиошибку видят немногиемедленная выкатка
rolling updateзамена экземпляров по одномубез простоя и лишних ресурсовдве версии сразу
A/Bверсии для случайных группрешение по метрикамсложная настройка

Пояснение

Главная забота при выкатке — возможность быстро откатиться.

Для физика

Для сервиса установки аналог canary — новая версия сначала на одном стенде или одном канале.

Контейнеры

и Docker

FROM python:3.12-slim
WORKDIR /app
COPY app.py .
ENV VERSION=1.0
CMD ["python3", "app.py"]

Пояснение

Образ отделяет приложение от инфраструктуры: один слепок работает на любой машине с той же архитектурой процессора.

Для физика

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

Dockerfile

рецепт: базовый образ, файлы, команда

docker build -t beam:1.1

образ — неизменяемый слепок

docker push / pull

реестр образов

docker run beam:1.1

контейнер — запущенный образ

Демонстрация:

релиз и откат

01

Dockerfile: python:3.12-slim и app.py

02

Сборка beam:1.0, запуск и запрос

03

Версия 1.1 с флагом NEW_FIT=1

04

Откат: снова контейнер beam:1.0

05

Два образа с разными тегами

Что наблюдается

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

root@lab — запись со стенда

Feature-флаги

и момент выпуска

01

Feature-флаг

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

02

Мораторий на выкатки

change freeze: выкатки запрещены — праздники, распродажи, крупные запуски

03

Релизные окна

заранее оговорённое время выкаток, когда на месте те, кто разберётся с последствиями

Для физика

Для установки: выкатки запрещены во время набора данных и перед конференцией; выкатка — в начале дня, когда автор на месте.

Важно

Флаги копятся: флаг, включённый для всех, удаляют вместе со старой ветвью кода.

Версии

и теги

ЧастьЧто меняетсяПример
MAJORнесовместимые изменения интерфейса1.4.2 → 2.0.0
MINORновые возможности с совместимостью1.4.2 → 1.5.0
PATCHисправления ошибок1.4.2 → 1.4.3

git tag -a v1.5.0 -m 'Подгонка с фоном'
git push origin v1.5.0
git describe    # v1.5.0-3-g1e5ddd7

Для физика

В статье указывают версию или хеш коммита кода; архив релиза с DOI (Zenodo) делает расчёт воспроизводимым.

CI/CD

Непрерывная интеграция, непрерывная поставка, непрерывное развёртывание

05

Анализ и проектирование

Разработка

Тестирование

Релиз

CI/CD

Сопровождение

Назначение

CI/CD

01

разработчики занимаются сборкой и ручным тестированием вместо разработки

02

тестирование пропускают, надёжность страдает

03

релизный цикл и время до выхода функции на рынок растут

04

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

Решение — автоматический конвейер, который на каждое изменение собирает, проверяет и выпускает код

Для физика

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

Три степени

автоматизации

ПрактикаЧто автоматизированоВыкатка
Continuous Integrationсборка, тесты, анализ на каждый push; ревьюминимальный уровень
Continuous Deliveryплюс сборка дистрибутива и выкатка на тестовые средывыкатка по решению человека
Continuous Deploymentплюс автоматическая выкатка в продакшенбез участия человека

Пояснение

Системы: GitHub Actions, GitLab CI, Jenkins, TeamCity.

Для физика

Научной группе обычно достаточно CI: тесты и линтер на каждый push.

Конвейер

GitHub Actions

name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.11', '3.12']
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-python@v7
        with:
          python-version: ${{ matrix.python-version }}
      - run: pip install ruff pytest
      - run: ruff check .
      - run: pytest -q

01

Матрица

те же шаги на нескольких версиях Python

02

Секреты

токены — в хранилище секретов, не в коде

03

Версии действий

полный хеш коммита; тег — у доверенных авторов

Пояснение

Тег версии запускает выпуск: пакет в PyPI, документация, PDF в релизе.

Демонстрация:

конвейер в контейнере

01

Шаги конвейера из ci.yml

02

Те же шаги в python:3.12-slim

03

Код завершения 0: проверка зелёная

04

Ошибка в формуле γ

05

Непройденные тесты: код завершения 1

Что наблюдается

Чистое окружение ставит зависимости с нуля; ненулевой код завершения pytest делает проверку красной.

root@lab — запись со стенда

Сопровождение

Наблюдаемость, дежурства, разбор инцидентов, учения, завершение жизненного цикла

06

Анализ и проектирование

Разработка

Тестирование

Релиз

CI/CD

Сопровождение

Сопровождение

работающей системы

ПрактикаНазначение
метрикинепрерывное измерение: задержки, ошибки, нагрузка
логижурнал событий для разбора
дежурствакто реагирует на сбой и в какие сроки
разбор инцидентовпричины без поиска виноватых
chaos engineeringнамеренные отказы в контролируемых условиях
ученияпроверка планов восстановления

Для физика

Минимум для лабораторного сервиса: программа ведёт журнал, а об отказе кто-то узнаёт раньше пользователей.

Пояснение

Мониторинг подробно разобран в книге «Site Reliability Engineering», глава 6.

Демонстрация:

отказ и перезапуск

01

Контейнер с политикой --restart on-failure

02

Запрос к сервису

03

Внесённый отказ: процесс завершён

04

Автоматический перезапуск контейнера

05

Журнал: два старта сервиса

06

Ответ сервиса после перезапуска

Что наблюдается

Отказ, внесённый запросом /crash, завершил процесс; Docker перезапустил контейнер, и журнал сохранил оба старта.

root@lab — запись со стенда

Завершение

жизненного цикла

01

Заблаговременное объявление

сроки и причины прекращения поддержки

02

Путь перехода

замена и инструкция миграции

03

Выгрузка данных

в формате, переживающем сервис

04

Архивирование

репозиторий, README, версии зависимостей

Рано или поздно любой сервис выводится из эксплуатации

Для физика

Код к статье, заброшенный после публикации, должен оставаться воспроизводимым: README, зафиксированные зависимости, архив с DOI.

Итоги

лекции

01

Жизненный цикл: анализ, проектирование, разработка, тестирование, релиз, сопровождение, завершение.

02

Требования и разбор замысла до кода дешевле исправлений после релиза; MVP проверяет замысел рано.

03

Git, короткие ветки и pull request с ревью позволяют работать вместе, не затирая чужое.

04

Пирамида тестов: статический анализ и модульные тесты на каждое изменение, остальное — реже.

05

Выпуск — тег версии и образ; откат — запуск предыдущего образа, флаги выключают функции без выкатки.

06

CI/CD выполняет проверки и выпуск без ручных шагов; сопровождение и завершение тоже требуют работы.

Домашнее задание:

«Котики в мир»

01

Контекст

фронтенд и бэкенд стартапа «Котики в мир» остались в разных ветках

02

Репозиторий

слияние рабочих веток в main, код по каталогам frontend, backend, nginx

03

Docker

отдельные образы бэкенда и фронтенда, сборка через docker compose build

04

Готовность

фронтенд на http://localhost, бэкенд отвечает; трафик только через nginx

Пояснение

github.com/phys-dev/kitty-startup-task: форк, решение в ветке, ревьюер — преподаватель.

Для физика

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

Демонстрация:

репозиторий задания

01

Клонирование kitty-startup-task

02

Удалённые ветки: front_code, my_backend, writing_readme

03

Граф с именами веток: четыре линии от начального коммита

Что наблюдается

Три рабочие ветки разошлись от начального коммита и не слиты в main — с этого начинается задание.

root@lab — запись со стенда

Проект

курса

01

Постановка задачи

документ на 1–2 страницы с путём решения и таблицей этапов; последняя неделя ноября

02

Базовая функциональность

реализованы обязательные требования; вторая неделя декабря

03

Расширенная функциональность

часть дополнительных требований; зачётная неделя

Команда 2–3 человека, у каждого своя зона ответственности; задача связана с физикой, язык — Python.

АртефактТребование
кодсобирается без IDE, контейнеризация приветствуется
тестыпокрытие тестами
документацияпрограммный интерфейс
примерыдемонстрация функциональности
репозиторийвсе артефакты в VCS

Источники

1

Книга курса: главы «Жизненный цикл ПО», «Требования к коду», «От скрипта к приложению», «Git», «Docker»

phys-dev.github.io/soft-dev-book

2

Курсы информационных технологий 2024: «Жизненный цикл ПО»

youtube.com/watch?v=S-OvD6ShZOM

3

Software requirements specification: IEEE 830 и ISO/IEC/IEEE 29148

en.wikipedia.org/wiki/Software_requirements_specification

4

Pro Git — книга о Git на русском языке

git-scm.com/book/ru/v2

5

pytest и ruff — документация

docs.pytest.org, docs.astral.sh/ruff

6

Semantic Versioning 2.0.0

semver.org/lang/ru

7

GitHub Actions — документация

docs.github.com/actions

8

Beyer B. et al. Site Reliability Engineering. – O'Reilly, 2016

sre.google/books

Спасибо за внимание

Вопросы

phys-dev.github.io/soft-dev-book

eol