← Назад к вопросам

Читаешь ли документацию для написания кода

2.0 Middle🔥 151 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Роль документации в разработке

Да, я активно читаю документацию

Да, чтение документации — это критически важная часть моей разработки. Я убедился, что пропуск документации приводит к багам, неправильному использованию API и потере времени.

Когда я читаю документацию

1. Перед началом проекта

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

# Например, выбираю между asyncio, trio, anyio
# Читаю:
# - asyncio (https://docs.python.org/3/library/asyncio.html)
# - trio (https://trio.readthedocs.io/)
# - anyio (https://anyio.readthedocs.io/)

# Вывод: anyio имеет лучший cancellation API
import anyio

async def main():
    with anyio.CancelScope() as cancel_scope:
        if some_condition:
            cancel_scope.cancel()  # Очень ясный API

2. При интеграции новой библиотеки

Никогда не копирую код с StackOverflow слепо. Всегда сначала читаю oficialную документацию:

# НЕПРАВИЛЬНО: скопировал с SO
from sqlalchemy import create_engine
engine = create_engine("sqlite:///db.sqlite")
session = Session(engine)
user = session.query(User).first()  # Deprecated pattern!

# ПРАВИЛЬНО: прочитал SQLAlchemy 2.0 docs
from sqlalchemy import create_engine, select
from sqlalchemy.orm import Session

engine = create_engine("sqlite:///db.sqlite")
with Session(engine) as session:
    stmt = select(User).limit(1)
    user = session.execute(stmt).scalar()  # Новый pattern

3. Перед использованием сложных фич

Документация помогает избежать подводных камней:

# Без документации мог бы упустить важность связи между
# timeout и cancel scope в asyncio

import asyncio

async def fetch_data_safely():
    # НЕПРАВИЛЬНО: timeout не отменяет задачу, только ждёт
    try:
        result = await asyncio.wait_for(
            slow_operation(),
            timeout=5
        )
    except asyncio.TimeoutError:
        # slow_operation всё ещё работает в фоне!
        pass
    
    # ПРАВИЛЬНО: использую cancel scope (trio) или task.cancel() (asyncio)
    task = asyncio.create_task(slow_operation())
    try:
        result = await asyncio.wait_for(task, timeout=5)
    except asyncio.TimeoutError:
        task.cancel()  # Явная отмена
        try:
            await task
        except asyncio.CancelledError:
            pass

Типы документации, которые я читаю

1. Официальная документация (первый приоритет)

✅ https://docs.python.org/
✅ https://fastapi.tiangolo.com/
✅ https://sqlalchemy.org/
✅ https://pydantic-docs.helpmanual.io/
✅ https://asyncio.readthedocs.io/

2. RFC и PEP (для понимания философии)

# PEP 8 — Style Guide
# PEP 20 — Zen of Python
# PEP 484 — Type Hints
# PEP 492 — Coroutines
# PEP 673 — TypeVar with bound

# Пример: после чтения PEP 492, понимаю различие:
async def coro():  # Это синтаксис async, определён в PEP 492
    await other_coro()

def gen():
    yield 1  # Это generator, работает иначе

3. Changelog и Migration guides

Критично при обновлениях версий:

# FastAPI 0.100.0 добавил новый параметр
# Если не читал changelog, мог бы использовать deprecated API

# ДО (FastAPI < 0.100)
from fastapi import APIRouter
router = APIRouter()

# ПОСЛЕ (читал changelog)
router = APIRouter(prefix="/api/v1")
# Теперь можно убрать prefix из всех routes

Как я организую изучение документации

Шаг 1: Overview

Прочитаю введение и основные концепции:

# FastAPI Docs
1. Introduction ← начинаю отсюда
2. Installation
3. Quickstart
4. User Guide (skip пока)

Шаг 2: Relevant Section

Нахожу раздел, относящийся к моей задаче:

# Ищу решение для async validation
- Request Body → Pydantic → Validators

Шаг 3: Example Code

Запускаю примеры локально, экспериментирую:

# Из документации FastAPI
from pydantic import BaseModel, field_validator

class Item(BaseModel):
    name: str
    price: float
    
    @field_validator('price')
    @classmethod
    def price_must_be_positive(cls, v):
        if v <= 0:
            raise ValueError('Price must be positive')
        return v

# Экспериментирую
item = Item(name="Book", price=-10)  # Проверяю, выбросится ли ошибка

Шаг 4: Edge Cases

Читаю про ограничения и подводные камни:

# Из документации Pydantic
# "Field validators run BEFORE type coercion"
# Это важно для правильного порядка проверок

from pydantic import BaseModel, field_validator

class Model(BaseModel):
    value: int
    
    @field_validator('value', mode='before')
    @classmethod
    def validate_before_coerce(cls, v):
        # v здесь может быть строка "123", не число
        if isinstance(v, str):
            return int(v)
        return v

Документация vs StackOverflow

ИсточникПлюсыМинусы
ДокументацияАктуальная, полная, правильнаяМожет быть скучной
StackOverflowРешения реальных проблемЧасто устаревает, может быть неправильной
БлогиПримеры use-casesСубъективно, не авторитетно

Мой подход:

Документация → StackOverflow → Исходный код (если документ молчит)

Примеры, где документация спасла меня

1. Asyncio и race conditions

Документация asyncio объясняет, почему asyncio.gather() с return_exceptions=True критична:

# БЕЗ знания документации, мог бы упустить одну из задач
tasks = [fetch_data(i) for i in range(10)]

# НЕПРАВИЛЬНО: одна ошибка — всё падает
results = await asyncio.gather(*tasks)  # ❌ Если task[5] упадёт, остальные отменяются

# ПРАВИЛЬНО: (после чтения docs)
results = await asyncio.gather(*tasks, return_exceptions=True)  # ✅ Все выполняются

2. SQLAlchemy Session scope

Документация объясняет, почему нужна session scope в многопоточности:

# Без документации, мог бы создавать session глобально
# Это привело бы к race conditions

from sqlalchemy.orm import sessionmaker, Session
from contextvars import ContextVar

# ПРАВИЛЬНО: после чтения docs
session_context: ContextVar[Session] = ContextVar('session')

def get_session() -> Session:
    try:
        return session_context.get()
    except LookupError:
        session = SessionLocal()
        session_context.set(session)
        return session

3. Pydantic model_dump vs dict

Документация объясняет разницу:

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str

user = User(id=1, name="John")

# СТАРЫЙ способ (deprecated)
user.dict()  # ❌

# НОВЫЙ способ (из docs v2)
user.model_dump()  # ✅ Правильно для Pydantic v2

Документация в команде

Когда я веду код review, проверяю:

# Вопрос: почему используется именно этот параметр?
from asyncio import gather

results = await gather(
    *tasks,
    return_exceptions=True  # ← Может быть улучшено?
)

# Проверяю документацию gather():
# "If return_exceptions is False (default), the first raised exception is immediately
# propagated to the task that awaits on gather()."

# Комментарий в code review:
# "Почему return_exceptions=True? Если мы хотим отказаться от одной из задач,
# может быть, лучше использовать asyncio.TaskGroup для явной отмены?"

Мой совет молодым разработчикам

"""
Ник(читаю ли документацию):
- ПЕРВЫЙ месяц: документация 80%, StackOverflow 20%
- ПОСЛЕ 6 месяцев: документация 60%, StackOverflow 40%
- ПОСЛЕ 2 лет: документация 50%, StackOverflow 30%, исходный код 20%

Ключное правило: никогда не доверяй примерам из StackOverflow
без проверки в официальной документации.
"""

Инструменты для чтения документации

# Просмотр docs локально
pip install sphinx-doc

# Поиск в документации
grep -r "timeout" /path/to/docs/

# Запуск примеров из документации
jupyter notebook  # для экспериментов

Итог

Я читаю документацию потому что:

  1. Экономия времени — один раз прочитал правильно, потом не ищу баги
  2. Избегаю ошибок — документация показывает подводные камни
  3. Понимаю философию — зачем именно так сделано, не просто копирую
  4. Уважение к авторам — они потратили время, я уважаю их работу
  5. Модель для команды — если я читаю docs, моя команда тоже будет

Программист без документации — как пилот без карты. Вроде можешь летать, но в 10 раз больше вероятность крушения.