ЧАСТЬ III: НОВАЯ ПАРАДИГМА

Метафора выращивания — практика

Глава 15. Метафора выращивания — практика

"Программа — это живой организм, который растёт, адаптируется и эволюционирует."


15.1. Органический рост vs детальное планирование

Традиционный подход (Waterfall)

1. Требования (100% детализация)    ─┐
2. Проектирование (полная архитектура) │ Планирование
3. Разработка (по спецификации)       │ занимает 50%
4. Тестирование                      │ времени
5. Деплой                            ─┘

Проблема: К моменту деплоя требования уже изменились.

Growing Software подход

1. Ядро идеи (минимальный MVP)        ─┐
2. Выращивание функций итерациями      │ Рост
3. Адаптация под feedback              │ происходит
4. Эволюция архитектуры                │ постоянно
5. Continuous growth                  ─┘

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


15.2. Программа как живой организм

Три уровня аналогии

Уровень 1: Растение

Семя — начальная идея / MVP:

# Семя: простейший TODO app
todos = []

def add_todo(task):
    todos.append(task)

def list_todos():
    for i, task in enumerate(todos, 1):
        print(f"{i}. {task}")

Росток — базовая функциональность:

# AI: добавь возможность отмечать задачи выполненными
todos = []

def add_todo(task):
    todos.append({"task": task, "done": False})

def mark_done(index):
    if 0 <= index < len(todos):
        todos[index]["done"] = True

def list_todos():
    for i, item in enumerate(todos, 1):
        status = "✓" if item["done"] else " "
        print(f"[{status}] {i}. {item['task']}")

Ветви — новые функции:

# AI: добавь приоритеты и сроки
def add_todo(task, priority="medium", due_date=None):
    todos.append({
        "task": task,
        "done": False,
        "priority": priority,
        "due_date": due_date,
        "created_at": datetime.now()
    })

def get_by_priority(priority):
    return [t for t in todos if t["priority"] == priority]

Плоды — продукт, который используют.

Уровень 2: Домашнее животное

Программа как питомец:

  • Требует регулярного внимания (maintenance)
  • Учится на ваших примерах (обучение на данных)
  • Адаптируется к вашим привычкам
  • Может "болеть" (баги) — нужно лечить
  • Эволюционирует со временем

Пример: AI-агент Ева

# Ева запоминает мой стиль ответов
class Eva:
    def __init__(self):
        self.memory = []  # память о прошлых взаимодействиях
        self.preferences = {}  # мои предпочтения

    def learn_from_feedback(self, response, feedback):
        """Ева учится на моих корректировках"""
        self.memory.append({
            "response": response,
            "feedback": feedback,
            "timestamp": datetime.now()
        })

    def adapt_style(self):
        """Анализирует память и адаптирует стиль"""
        # AI анализирует паттерны в feedback
        # Корректирует будущие ответы
        pass

Как это работает:

  1. Ева генерирует ответ
  2. Я даю feedback ("слишком формально" / "хорошо")
  3. Ева запоминает
  4. Следующий ответ учитывает мои предпочтения

Уровень 3: Ребёнок

Программа как ребёнок:

  • Начинает с простого (ползает)
  • Постепенно усложняется (ходит, бегает)
  • Учится на ошибках
  • Требует наставника (вас!)
  • Со временем становится самостоятельной

Пример эволюции программы:

Младенец (неделя 1):

# Простейший калькулятор
def add(a, b):
    return a + b

Малыш (месяц 1):

# AI: расширь функциональность
class Calculator:
    def add(self, a, b): return a + b
    def subtract(self, a, b): return a - b
    def multiply(self, a, b): return a * b
    def divide(self, a, b):
        if b == 0:
            raise ValueError("Division by zero")
        return a / b

Подросток (месяц 3):

# AI: добавь научные функции и историю вычислений
class ScientificCalculator(Calculator):
    def __init__(self):
        self.history = []

    def calculate(self, operation, *args):
        result = operation(*args)
        self.history.append({
            "operation": operation.__name__,
            "args": args,
            "result": result
        })
        return result

    def sqrt(self, x): return math.sqrt(x)
    def power(self, base, exp): return base ** exp
    def log(self, x, base=math.e): return math.log(x, base)

Взрослый (месяц 6):

# AI: добавь UI, сохранение в БД, API
class CalculatorApp:
    def __init__(self):
        self.calculator = ScientificCalculator()
        self.db = Database()
        self.api = FastAPI()

    @self.api.post("/calculate")
    async def calculate_api(self, expression: str):
        result = self.calculator.evaluate(expression)
        await self.db.save_calculation(result)
        return {"result": result}

15.3. От детерминизма к вероятности

Детерминистический код

def get_greeting(name):
    return f"Hello, {name}!"

print(get_greeting("Alice"))  # Всегда: "Hello, Alice!"

Характеристики:

  • Результат всегда одинаковый
  • Полный контроль
  • Предсказуемо
  • Тестируется точными значениями

Вероятностный код (с AI)

def generate_greeting(name, style="friendly"):
    prompt = f"Generate a {style} greeting for {name}"
    return llm.generate(prompt)

print(generate_greeting("Alice"))
# Вариант 1: "Hey Alice! How's it going?"
# Вариант 2: "Hi Alice! Great to see you!"
# Вариант 3: "Hello Alice! Hope you're having a wonderful day!"

Характеристики:

  • Результат варьируется
  • Направленный контроль (через промпт)
  • Непредсказуемо в деталях, но предсказуемо в общем
  • Тестируется паттернами, а не точными значениями

Как тестировать вероятностный код

Плохой подход:

def test_greeting():
    result = generate_greeting("Alice")
    assert result == "Hello, Alice!"  # FAIL! Результат разный каждый раз

Хороший подход:

def test_greeting():
    result = generate_greeting("Alice")

    # Проверяем паттерн, а не точное значение
    assert "Alice" in result  # Имя должно быть
    assert len(result) > 0  # Не пустой ответ
    assert result.endswith(("!", ".", "?"))  # Корректная пунктуация

    # Проверяем тон (если важен)
    sentiment = analyze_sentiment(result)
    assert sentiment == "positive"

15.4. Практика: Выращивание TODO-приложения

Итерация 0: Семя

Промпт:

AI, создай простейшее TODO-приложение на Python.
Функции: добавить задачу, показать список.
Хранение в памяти (список).

Результат:

todos = []

def add_todo(task):
    todos.append(task)
    print(f"Added: {task}")

def list_todos():
    if not todos:
        print("No tasks yet!")
        return

    print("Your tasks:")
    for i, task in enumerate(todos, 1):
        print(f"{i}. {task}")

# CLI
while True:
    cmd = input("Command (add/list/quit): ").strip().lower()
    if cmd == "add":
        task = input("Task: ")
        add_todo(task)
    elif cmd == "list":
        list_todos()
    elif cmd == "quit":
        break

Итерация 1: Росток — отметка выполненных

Промпт:

AI, модифицируй код:
- Задачи должны иметь статус (done/not done)
- Добавь команду 'done <номер>' для отметки
- Отображай статус в списке

Результат:

todos = []

def add_todo(task):
    todos.append({"task": task, "done": False})
    print(f"Added: {task}")

def mark_done(index):
    if 1 <= index <= len(todos):
        todos[index - 1]["done"] = True
        print(f"Marked as done: {todos[index - 1]['task']}")
    else:
        print("Invalid task number")

def list_todos():
    if not todos:
        print("No tasks yet!")
        return

    print("Your tasks:")
    for i, item in enumerate(todos, 1):
        status = "✓" if item["done"] else " "
        print(f"[{status}] {i}. {item['task']}")

# CLI расширен
while True:
    cmd = input("Command (add/list/done/quit): ").strip().lower()
    if cmd == "add":
        task = input("Task: ")
        add_todo(task)
    elif cmd == "list":
        list_todos()
    elif cmd.startswith("done"):
        try:
            index = int(cmd.split()[1])
            mark_done(index)
        except (IndexError, ValueError):
            print("Usage: done <number>")
    elif cmd == "quit":
        break

Итерация 2: Ветви — приоритеты и сроки

Промпт:

AI, добавь:
- Приоритет задачи (high/medium/low)
- Срок выполнения (due_date)
- Команду 'filter priority <level>' для фильтрации
- Команду 'overdue' для просроченных задач
- Сортировку по приоритету и сроку

Результат: (код стал больше, показываю ключевые части)

from datetime import datetime, timedelta

todos = []

def add_todo(task, priority="medium", due_date=None):
    todos.append({
        "task": task,
        "done": False,
        "priority": priority,
        "due_date": due_date,
        "created_at": datetime.now()
    })

def list_todos(filter_priority=None):
    filtered = todos
    if filter_priority:
        filtered = [t for t in todos if t["priority"] == filter_priority]

    # Сортировка: high > medium > low, потом по due_date
    priority_order = {"high": 0, "medium": 1, "low": 2}
    filtered.sort(key=lambda t: (
        priority_order[t["priority"]],
        t["due_date"] if t["due_date"] else datetime.max
    ))

    for i, item in enumerate(filtered, 1):
        status = "✓" if item["done"] else " "
        priority_emoji = {"high": "🔴", "medium": "🟡", "low": "🟢"}[item["priority"]]
        due = f"(due: {item['due_date'].strftime('%Y-%m-%d')})" if item["due_date"] else ""

        print(f"[{status}] {priority_emoji} {i}. {item['task']} {due}")

def get_overdue():
    now = datetime.now()
    overdue = [t for t in todos if t["due_date"] and t["due_date"] < now and not t["done"]]
    return overdue

Итерация 3: Плоды — Web UI + БД

Промпт:

AI, преобразуй приложение:
- Используй Flask для web-интерфейса
- Сохраняй задачи в SQLite
- Создай REST API:
  GET /tasks - список
  POST /tasks - создать
  PUT /tasks/<id> - обновить
  DELETE /tasks/<id> - удалить
- Добавь простой HTML/CSS фронтенд

Результат: (показываю backend)

from flask import Flask, request, jsonify, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todos.db'
db = SQLAlchemy(app)

class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    task = db.Column(db.String(200), nullable=False)
    done = db.Column(db.Boolean, default=False)
    priority = db.Column(db.String(10), default="medium")
    due_date = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.now)

@app.route('/api/tasks', methods=['GET'])
def get_tasks():
    priority = request.args.get('priority')
    query = Todo.query

    if priority:
        query = query.filter_by(priority=priority)

    tasks = query.order_by(Todo.priority, Todo.due_date).all()
    return jsonify([{
        "id": t.id,
        "task": t.task,
        "done": t.done,
        "priority": t.priority,
        "due_date": t.due_date.isoformat() if t.due_date else None
    } for t in tasks])

@app.route('/api/tasks', methods=['POST'])
def create_task():
    data = request.json
    new_task = Todo(
        task=data['task'],
        priority=data.get('priority', 'medium'),
        due_date=datetime.fromisoformat(data['due_date']) if data.get('due_date') else None
    )
    db.session.add(new_task)
    db.session.commit()
    return jsonify({"id": new_task.id}), 201

@app.route('/api/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
    task = Todo.query.get_or_404(task_id)
    data = request.json

    task.task = data.get('task', task.task)
    task.done = data.get('done', task.done)
    task.priority = data.get('priority', task.priority)

    db.session.commit()
    return jsonify({"success": True})

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

Эволюция:

  • Семя: 20 строк Python
  • Росток: 50 строк
  • Ветви: 100+ строк
  • Плоды: Полноценное веб-приложение с БД

Время разработки с AI: ~2-3 часа вместо 2-3 дней!


15.5. Направление роста, а не контроль деталей

Садовник vs Микроменеджер

Микроменеджер (традиционное программирование):

# Вы контролируете каждую деталь
result = ""
for char in input_string:
    if char.isalpha():
        result += char.upper()
    elif char.isdigit():
        result += char
# ... ещё 50 строк деталей

Садовник (Growing Software):

# Вы направляете, AI реализует детали
prompt = """
Обработай строку:
- Буквы → в верхний регистр
- Цифры → оставить
- Остальное → удалить
"""
result = ai_process(prompt, input_string)

Как направлять рост

1. Начните с ядра (core value)

Не пытайтесь сразу создать всё. Начните с того, что даёт максимальную ценность.

Пример: Интернет-магазин

  • ❌ НЕ начинайте с: регистрация, профили, отзывы, рекомендации
  • ✅ Начните с: каталог товаров, корзина, оформление заказа

2. Растите итерациями

Каждая итерация добавляет 1-2 новые функции.

Итерация 1: Каталог + Корзина (MVP)
Итерация 2: Оформление заказа
Итерация 3: Регистрация пользователей
Итерация 4: История заказов
Итерация 5: Отзывы и рейтинги

3. Обрезайте лишнее (рефакторинг)

Как садовник обрезает ветки, вы удаляете:

  • Неиспользуемый код
  • Дублирующуюся логику
  • Ненужные зависимости
AI, проанализируй код и найди:
- Неиспользуемые функции
- Дублирующуюся логику
- Места для рефакторинга

Предложи улучшения.

4. Удобряйте (улучшайте)

  • Добавляйте тесты
  • Улучшайте производительность
  • Оптимизируйте UX
AI, добавь тесты для модуля заказов.
Покрытие должно быть >80%.
Используй pytest.

15.6. Практические упражнения

Упражнение 1: Вырастите блог

Итерация 0 (семя):

AI, создай простейший блог:
- Список постов (title, content)
- Добавление поста
- Хранение в памяти
- CLI интерфейс

Итерация 1-3: Самостоятельно определите, какие функции добавить.

Подсказка:

  • Авторы постов?
  • Категории / теги?
  • Комментарии?
  • Web UI?

Упражнение 2: Эволюция калькулятора

Начните с простого калькулятора (+, -, *, /).

Вырастите его до:

  • Научного калькулятора
  • С историей вычислений
  • С графиками функций
  • С web-интерфейсом

Итерации определите сами.

Упражнение 3: Анализ роста

Возьмите любой open-source проект на GitHub.

Посмотрите его историю коммитов (git log).

Проанализируйте:

  • С чего начинался (первые коммиты)?
  • Как рос (какие функции добавлялись)?
  • Были ли "обрезки" (удаление функций)?

Вопрос: Это был "рост" или "строительство"?


Ключевые выводы главы

Органический рост: Программа растёт итерациями, а не строится по плану

Три уровня аналогии: Растение (семя→плоды), Животное (учится), Ребёнок (эволюционирует)

От детерминизма к вероятности: AI-код тестируется паттернами, а не точными значениями

Направление, а не контроль: Вы садовник, направляете рост, не контролируете детали

Итеративный процесс: Семя → Росток → Ветви → Плоды

С AI быстрее: Эволюция за 2-3 часа вместо 2-3 дней

Обрезайте лишнее: Рефакторинг — это удаление ненужных веток


Следующая глава: Работа с LLM — интеграция AI в ваши программы