Перейти к основному содержимому

6.04. Руководство программиста по ГОСТ 19.504-79

Руководителю Аналитику Техническому писателю

Руководство программиста

ГОСТ
Основано на ГОСТ 19.504-79.

1. Введение: стандарт и его роль

1.1 Общая характеристика ГОСТ 19.504-79

  • Наименование документа: Руководство программиста
  • Статус: Государственный стандарт СССР, действует по сей день в РФ как межгосударственный стандарт (соответствует СТ СЭВ 2095-80).
  • Дата введения: 1 января 1980 г.
  • Утверждён: Постановлением Госстандарта СССР от 12.01.1979 № 74.
  • Область применения:
    • Разработка и сопровождение программного обеспечения (ПО) в рамках Единой системы программной документации (ЕСПД).
    • Обязателен к применению в организациях, работающих по ГОСТ 19.100–19.701 (ЕСПД), особенно в госсекторе, ОПК, энергетике, транспорте и других регулируемых отраслях.

💡 Примечание: Стандарт не отменён и часто используется в контексте требований к документации по ГОСТ Р ИСО/МЭК 12207 и 15288. В современной практике его требования адаптируются под agile, но базовая структура остаётся актуальной при составлении внутренней технической документации.

1.2 Назначение Руководства программиста

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

  • интеграции программы в состав комплекса ПО;
  • сопровождения и модификации;
  • отладки и тестирования;
  • обеспечения сопряжения с другими программами и системами.

Он не дублирует Руководство оператора (ГОСТ 19.505) и не заменяет Техническое задание (ГОСТ 19.201). Это — документ инженерного уровня, ориентированный на реализацию, а не на эксплуатацию.

1.3 Общая структура документа по ГОСТ

РазделОбязательностьКраткое содержание
Титульный лист / реквизитыДаНазначение документа, наименование ПО, номер версии, дата, ответственные
Аннотация (информационная часть)ДаКраткая характеристика, назначение, применимость
СодержаниеДаОглавление с нумерацией разделов
1. Назначение и условия применения программОбязательныйЦель, функции, требования к среде выполнения
2. Характеристика программыОбязательныйРежимы работы, временные/ресурсные характеристики, надёжность
3. Обращение к программеОбязательныйСпособы вызова, интерфейсы, передача управления и параметров
4. Входные и выходные данныеОбязательныйФорматы, структуры, кодировки, примеры
5. СообщенияОбязательныйТипы сообщений, тексты, действия при их возникновении
ПриложенияОпциональноДоп. схемы, примеры кода, таблицы, протоколы

📌 Важно: Структура оформляется в соответствии с ГОСТ 19.105-78 — требования к оформлению программных документов (шрифты, поля, нумерация, ссылки и т.п.).


2. Пошаговое руководство по составлению Руководства программиста

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

Шаг 1. Подготовительный этап

  • Определите полный состав программных модулей, к которым будет относиться документ:
    • Это может быть один модуль, подсистема или целая система (если она атомарна по функционалу).
  • Убедитесь, что у вас есть актуальные:
    • Архитектурная схема (в том числе API-контракты);
    • Техническое задание (ГОСТ 19.201);
    • Документация по использованным технологиям (SDK, runtime, библиотеки);
    • Спецификация данных (ERD / JSON Schema / XSD).
  • Назначьте ответственных:
    • Разработчик — поставляет технические данные;
    • Архитектор — утверждает интерфейсы и режимы;
    • Техписатель — формирует и редактирует документ.

Шаг 2. Раздел «Назначение и условия применения программ»

Что включать:

  • Назначение:

    «Программа auth-service предназначена для централизованной аутентификации и авторизации пользователей в распределённой системе X-Core. Реализует протоколы OAuth2.0 и OpenID Connect 1.0.»

  • Функции: перечислить только программные функции, реализованные внутри модуля (не «взаимодействует с БД», а «осуществляет JWT-валидацию токенов», «реализует эндпоинты /token, /userinfo, /revoke»).

  • Условия применения (строго по категориям):

    • Аппаратные требования:
      • Минимальный объём RAM: 512 МБ
      • Процессор: x86-64, 2 ядра
      • Наличие TPM-2.0 (если требуется)
    • Программные требования:
      • ОС: Linux (Ubuntu 20.04+, AlmaLinux 8+)
      • Среда: OpenJDK 17+, Node.js 18.x
      • Зависимости: PostgreSQL 14+, Redis 6.2+, Vault 1.12+
    • Сетевые требования:
      • Доступ к порту 5432 (PostgreSQL), 6379 (Redis), 8200 (Vault)
      • Возможность TLS-терминации на уровне ingress

✅ Рекомендация: оформлять в виде таблиц.
❌ Ошибка: смешивать требования к системе и требования к разработке (например, «требуется опыт в Spring Security» — это НЕ условие применения, а требование к персоналу).

Пример оформления:

### 1. Назначение и условия применения программ

#### 1.1 Назначение
Модуль `calc-engine` реализует ядро расчёта финансовых показателей (IRR, NPV, DPP) для инвестиционных проектов в системе `X-Core`. Предоставляет REST API для клиентских сервисов.

#### 1.2 Функции
- Приём JSON-описания денежного потока;
- Расчёт IRR методом Ньютона–Рафсона (с итерационным уточнением);
- Валидация входных параметров (чек-лист: не пустой поток, не более 100 периодов, ставка в [0;1]);
- Логирование ошибок расчёта (коды 4xx/5xx).

#### 1.3 Условия применения

| Категория | Требование |
|-----------|------------|
| Аппаратное обеспечение | RAM ≥ 1 ГБ, CPU ≥ 2 vCPU |
| Операционная система | Linux (ядро ≥ 5.4) |
| Среда выполнения | Python 3.10+, `numpy==1.24.3`, `scipy==1.10.1` |
| Сетевые возможности | Доступ к `redis.internal:6379`, `logger.service:9000/udp` |
| Прочие ограничения | Не поддерживает Windows; требует `libgomp1` в системе |

Шаг 3. Раздел «Характеристика программы»

Это — «паспорт» поведения программы под нагрузкой и в штатных/нештатных режимах.

Обязательные подразделы (по смыслу ГОСТ):

  • Режим работы

    • Пакетный / интерактивный / фоновый / реального времени
    • Поддержка многопоточности, кластеризации, горизонтального масштабирования
    • Ограничения на параллельные запросы (например, max_concurrent_calculations = 50)
  • Временные характеристики

    • Среднее/максимальное время выполнения операции (в ms)
    • Зависимость от объёма входных данных
    • Пример: «Обработка потока из 10 периодов: ≤ 15 мс (P95); из 100 периодов: ≤ 210 мс (P95)»
  • Средства контроля и самовосстановления

    • Логирование: уровни, категории, формат (JSON, RFC5424)
    • Метрики: экспортируемые через Prometheus (calc_duration_seconds, calc_error_total)
    • Механизмы graceful degradation:
      • fallback на упрощённый алгоритм при timeout > 500 мс
      • circuit breaker после 5 ошибок подряд
    • Health-check: эндпоинт /healthz, возвращает { "status": "ok", "deps": { "redis": true } }

✅ Рекомендация: приводить измеренные данные (benchmark-результаты), а не оценочные.
❌ Ошибка: использовать расплывчатые формулировки вроде «высокая производительность» без метрик.

Пример:

### 2. Характеристика программы

#### 2.1 Режим работы
- Интерактивный (запрос–ответ по HTTP/1.1 и HTTP/2);
- Поддержка до 200 одновременных соединений (ограничено `gunicorn --workers=4 --threads=50`);
- Stateless: все сессии хранятся в Redis.

#### 2.2 Временные характеристики (на стенде: 2 vCPU, 4 ГБ RAM, SSD)

| Размер входа | Среднее время, мс | P95, мс | P99, мс |
|--------------|-------------------|---------|---------|
| 10 периодов | 8.2 | 14.1 | 19.7 |
| 50 периодов | 42.6 | 88.3 | 120.4 |
| 100 периодов | 163.9 | 211.5 | 302.8 |

> 📊 Замеры выполнены с помощью `k6` (1000 VUs, 30s ramp-up).

#### 2.3 Средства контроля и самовосстановления
- **Логирование**:
- Уровень `INFO` — старт/стоп запроса, `ERROR` — исключения, `DEBUG` — детали расчёта (опционально).
- Формат: JSON, поля: `ts`, `level`, `req_id`, `module`, `msg`, `duration_ms`.

- **Метрики (Prometheus)**:
promql
calc_duration_seconds{quantile="0.95"}
calc_error_total{type="input_validation", method="POST"}


- **Health-check**:
http
GET /healthz
→ 200 OK
{
"status": "ok",
"version": "2.3.1",
"deps": {
"redis": true,
"vault": true
}
}


- **Self-healing**:
При недоступности Redis > 3 с — переключение на in-memory LRU-кэш (ёмкость 1000 записей), с логированием предупреждения `WARN cache.fallback redis_unavailable`.

Шаг 4. Раздел «Обращение к программе»

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

Что включать:

  • Способы вызова:

    • REST API (методы, пути, заголовки)
    • CLI (команды, флаги)
    • Библиотечный интерфейс (публичные классы/функции)
    • Сообщения (AMQP, Kafka, gRPC)
  • Передача управления и параметров:

    • Как передаётся контекст (например, X-Request-ID, JWT в Authorization: Bearer …)
    • Формат тела запроса/ответа
    • Правила маршалинга/демаршалинга
    • Поведение при ошибках (статус-коды, структура error)

✅ Рекомендация: использовать OpenAPI/Swagger-подобные фрагменты.
❌ Ошибка: описывать внутреннюю логику вместо контракта («функция сначала проверяет…» — не надо!).

Пример:

### 3. Обращение к программе

#### 3.1 REST API (`/api/v1/calc`)

| Метод | Путь | Описание |
|-------|------|----------|
| POST | `/irr` | Расчёт внутренней нормы доходности |

##### Запрос

http
POST /api/v1/calc/irr HTTP/1.1
Host: calc-engine.x-core.internal
Content-Type: application/json
X-Request-ID: a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8
Authorization: Bearer <JWT>

{
"cashflow": [
{"period": 0, "amount": -1000000},
{"period": 1, "amount": 300000},
{"period": 2, "amount": 400000},
{"period": 3, "amount": 500000}
],
"guess": 0.1
}


- `cashflow`: обязательный массив объектов:
- `period` (int ≥ 0, уникальный)
- `amount` (float, может быть отрицательным)
- `guess`: необязательный (float ∈ [0; 1]), стартовое приближение.

##### Ответ (успех, 200 OK)

json
{
"irr": 0.1278,
"iterations": 7,
"converged": true
}


##### Ответ (ошибка валидации, 400 Bad Request)

json
{
"error": "INVALID_INPUT",
"detail": "cashflow[1].period must be `> cashflow[0].period"
}


##### Коды ответов
| Код | Причина |
|-----|---------|
| 200 | Успешный расчёт |
| 400 | Ошибка валидации входных данных |
| 401 | Отсутствует/некорректный JWT |
| 429 | Превышен лимит запросов (100/сек/IP) |
| 500 | Внутренняя ошибка сервера (см. логи по `X-Request-ID`) |
| 503 | Сервис недоступен (Redis down, fallback active) |

Шаг 5. Раздел «Входные и выходные данные»

🔍 Смысл раздела (по ГОСТ 19.504-79, п. 2.4):
«Описание организации используемой входной и выходной информации и, при необходимости, её кодирования».

Этот раздел — не описание бизнес-логики, а техническая спецификация форматов данных. Критически важен для сопряжения, тестирования, генерации моков и документирования API-контрактов.

Что включать (по смыслу и практике ЕСПД):

ЭлементТребования
Источники входных данныхОткуда поступают данные: API, файл, stdin, шина сообщений, БД-запрос, CLI-аргументы и т.п.
Структура входных данныхСтруктуры (JSON Schema, XSD, protobuf), поля, типы, ограничения (длина, диапазон, regexp), обязательность
КодировкиUTF-8, CP1251, Base64, Hex — указывать явно, если не по умолчанию
Форматы файлов (если применимо)CSV (разделитель, кавычки, escape), XML (DTD), JSON (RFC 8259), binary (endianness)
Выходные данныеАналогично — структура, типы, кодировки, форматы
Изменения состоянияКакие ресурсы изменяются: запись в БД, кэш, файл, отправка события — с указанием ключей/идентификаторов

✅ Рекомендация: прикладывать валидные примеры и невалидные (для пояснения ограничений).
❌ Типичная ошибка: описывать бизнес-смысл полей («amount — объём инвестиций»), тогда как нужно: «amount: float64, диапазон [-1e12; 1e12], 2 знака после запятой, обязательное».

Пример оформления:

### 4. Входные и выходные данные

#### 4.1 Источники входных данных
- HTTP-запрос (POST) к эндпоинту `/api/v1/calc/irr` (см. раздел 3);
- Входные данные передаются в теле запроса в формате JSON (RFC 8259);
- Кодировка: UTF-8 без BOM.

#### 4.2 Структура входных данных (JSON Schema Draft-07)

json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["cashflow"],
"properties": {
"cashflow": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"required": ["period", "amount"],
"properties": {
"period": {
"type": "integer",
"minimum": 0,
"maximum": 1000
},
"amount": {
"type": "number",
"minimum": -1e12,
"maximum": 1e12,
"multipleOf": 0.01
}
},
"additionalProperties": false
}
},
"guess": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0
}
},
"additionalProperties": false
}


#### 4.3 Примеры

##### Валидный запрос:
json
{
"cashflow": [
{"period": 0, "amount": -500000.00},
{"period": 1, "amount": 200000.00},
{"period": 2, "amount": 350000.00}
],
"guess": 0.15
}


##### Невалидный запрос (ошибка: неуникальный period):
json
{
"cashflow": [
{"period": 0, "amount": -100000},
{"period": 1, "amount": 50000},
{"period": 1, "amount": 60000} ← дубликат
]
}
→ Возвращается код 400 с ошибкой "DUPLICATE_PERIOD".


#### 4.4 Выходные данные

| Поле | Тип | Описание | Ограничения |
|------|-----|-----------|--------------|
| `irr` | number | Рассчитанное значение IRR | ∈ [–1; 1], 4 знака после запятой |
| `iterations` | integer | Число итераций метода Ньютона | ≥ 1, ≤ 1000 |
| `converged` | boolean | Сходимость достигнута | `true`/`false` |
| `warning` | string | (опционально) предупреждение | max 256 символов, UTF-8 |

> ⚠ Примечание: при `converged: false` поле `irr` содержит последнее приближение (не гарантируется корректность).

#### 4.5 Изменения состояния
- Логирование операции в `calc_log` (таблица в PostgreSQL):
- `req_id UUID NOT NULL`
- `user_id TEXT` (из JWT.claims.sub)
- `duration_ns BIGINT`
- `status TEXT` (`ok`, `input_error`, `timeout`, `diverge`)
- При `status = 'diverge'` — инкремент счётчика `diverge_counter` в Redis (`INCR calc:diverge:2025-11`).

Шаг 6. Раздел «Сообщения»

🔍 Смысл раздела (п. 2.5 ГОСТ):
«Тексты сообщений, выдаваемых программисту или оператору в ходе выполнения программы, описание их содержания и действий, которые необходимо предпринять по этим сообщениям».

Важно:

  • «программисту или оператору» означает — любые диагностические сообщения, включая логи, HTTP-ошибки, CLI-вывод, алерты.
  • Нужно разделять:
    • Информационные (INFO, DEBUG)
    • Предупреждения (WARN)
    • Ошибки (ERROR, FATAL)

Для каждой категории — указать:

  • Код/идентификатор (рекомендуется)
  • Текст (точный, включая параметры в шаблоне)
  • Условие возникновения
  • Рекомендуемое действие

Пример оформления:

### 5. Сообщения

| Код | Уровень | Текст | Условие | Действие |
|-----|---------|-------|---------|----------|
| `CALC-001` | INFO | `Request {req_id} started. user={user_id}, cashflow_len={len}` | Начало обработки запроса ||
| `CALC-002` | DEBUG | `Newton iteration {i}: x={x:.6f}, f(x)={fx:.3e}` | Включён `log_level=DEBUG` | Только для отладки; не в проде |
| `CALC-003` | WARN | `Fallback to in-memory cache: Redis unavailable (err={err})` | Таймаут подключения к Redis > 3 с | Проверить сетевую доступность Redis; кэш ограничен — возможна деградация |
| `CALC-004` | ERROR | `Input validation failed: {detail}` | Нарушение условий JSON Schema | Исправить клиентский запрос; проверить `X-Request-ID` в логах |
| `CALC-005` | ERROR | `Divergence after {n} iterations. guess={g}, last_irr={irr}` | Метод не сошёлся за 1000 итераций | Увеличить `guess` ближе к ожидаемому значению; или использовать `npv=0` для подбора вручную |
| `CALC-006` | FATAL | `Critical: Vault token expired. Cannot fetch decryption key.` | Vault возвращает 403 на `/transit/decrypt` | Перезапустить sidecar `vault-agent`; проверить lease duration |

> 📌 Все сообщения экспортируются в JSON-лог с полем `"msg_code": "CALC-004"`.
> 📌 Коды используют префикс `CALC-` + трёхзначный номер → легко фильтровать в SIEM.

4. Пример вымышленной системы: X-Core — Финансовый калькулятор

Ниже — фрагменты Руководства программиста для модуля calc-engine, оформленные строго по ГОСТ 19.504-79, без «воды», с фокусом на техническую реализуемость.

💡 Обратите внимание: в реальной практике такой документ может занимать 15–30 страниц. Приведены ключевые разделы — то, что реально используют при интеграции.


📄 Руководство программиста

Модуль: calc-engine (версия 2.3.1)
Система: X-Core
Дата: 11.11.2025
Разработчик: Тагиров Т.В.
Утверждено: Архитектурный комитет, протокол № 47 от 05.11.2025


1. Назначение и условия применения программ

1.1 Назначение

Программа calc-engine реализует численные методы расчёта финансовых показателей (IRR, NPV) для инвестиционных проектов. Предоставляет stateless REST API для сервисов user-portal и reporting.

1.2 Условия применения
КатегорияТребование
ОЗУ≥ 1 ГБ (реком.: 2 ГБ)
CPU2 ядра x86-64 (частота 2.4 ГГц)
ОСLinux (ядра 5.4); не поддерживает Windows/macOS
СредаPython 3.10+, numpy==1.24.3, scipy==1.10.1, gunicorn==21.2.0
ЗависимостиPostgreSQL 14+ (calc_log), Redis 6.2+ (cache), Vault 1.12+ (keys)
СетьДоступ к redis:6379, vault:8200, pg:5432; outbound HTTPS для метрик

2. Характеристика программы

2.1 Режим работы
  • Интерактивный, запрос–ответ;
  • Поддержка до 200 concurrent-соединений (gunicorn --workers=4 --threads=50);
  • Horizontally scalable: stateless → можно деплоить N реплик.
2.2 Временные характеристики
Размер потокаP50 (мс)P95 (мс)P99 (мс)
10 периодов8.214.119.7
50 периодов42.688.3120.4
100 периодов163.9211.5302.8

📊 Замеры: k6 (1000 VUs, 30s), сервер: 4 vCPU, 8 ГБ RAM, NVMe. Алгоритм: Ньютон–Рафсон с fallback на бисекцию.

2.3 Средства контроля
  • Health-check: GET /healthz{ "status": "ok", "deps": { "redis": true } }
  • Метрики: calc_duration_seconds, calc_error_total{code} (экспорт в Prometheus)
  • Логи: JSON, ts, level, req_id, msg_code, duration_ms
  • Circuit breaker: после 5 ошибок CALC-005 подряд — возврат 503 на 30 с.

3. Обращение к программе

3.1 REST API (/api/v1/calc)
ЭндпоинтМетодОписание
/irrPOSTРасчёт IRR
/npvPOSTРасчёт NPV при заданной ставке

Заголовки:

  • Обязательно: Content-Type: application/json, Authorization: Bearer <JWT>
  • Рекомендуется: X-Request-ID (генерируется клиентом)

См. полную OpenAPI-спецификацию в docs/openapi/calc-engine.v2.yaml.


4. Входные и выходные данные — см. пример выше (раздел 4).

5. Сообщения — см. таблицу выше (раздел 5).


5. Чек-лист: Проверка Руководства программиста перед утверждением

Используйте этот список при ревью. Достаточно одного «Нет» — документ требует доработки.

КритерийДа / НетКомментарий
1Есть аннотация (назначение, версия, ответственные)?
2Есть содержание с правильной нумерацией?
3Раздел 1: указаны точные требования к среде (не «современный ПК», а «RAM ≥ 1 ГБ»)?
4Раздел 2: есть измеренные временные характеристики (не «быстро»)?
5Раздел 3: есть полный контракт вызова (метод, заголовки, тело, коды ответа)?
6Раздел 4: есть валидный пример входных/выходных данных?
7Раздел 4: указаны ограничения на поля (диапазон, длина, формат)?
8Раздел 5: каждое сообщение имеет код, точный текст, условие, действие?
9Все примеры воспроизводимы (можно скопировать в Postman и получить ответ)?
10Нет упоминаний внутренней реализации («функция сначала проверяет…»)?
11Нет расплывчатых формулировок («высокая надёжность», «гибкая настройка»)?
12Документ соответствует ГОСТ 19.105-78 по оформлению (шрифты, поля, заголовки)?

📌 Рекомендуется: прогонять документ через peer review с участием как минимум одного разработчика и одного техписателя.