Все записи

Разбираем фичи по кусочкам: атомарные коммиты как внутренняя дисциплина

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

Дима.jpg

В статье он рассказывает о декомпозиции: зачем она на самом деле нужна в разработке и какую неожиданную роль в этом играют атомарные коммиты.


Что такое декомпозиция и почему с неё всё начинается

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

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


Зачем вообще декомпозировать задачи 

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

1. Это помогает при планировании

Пока задача выглядит как абстрактное «сделать фичу», планировать нечего. Как только появляются шаги, появляется и план.

2. Оценка по времени даётся гораздо проще

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

3. Руководство к действию для коллег

Небольшие задачи можно эффективно распределять между разработчиками, отслеживать прогресс и понимать, где именно что‑то пошло не так.

4. Параллельная работа в команде

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


Как декомпозиция приводит к модулям

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

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

Лучше всего это видно на примере.


Как выглядит декомпозиция на примере фичи

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

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

  • страница для ввода трек‑номера;

  • создание трек‑номера и присвоение его заказу;

  • поиск заказа по трек‑номеру в базе данных;

  • запись географического статуса курьера в базу данных;

  • отображение текущего положения курьера на карте.


Что меняется, если смотреть на задачу через бизнес-действия

Посмотрим на задачу не с точки зрения экранов и таблиц, а с точки зрения бизнес‑действий. 

Бизнес‑действие — это то, что наблюдаемо извне и имеет ценность для бизнеса. Это не «страница» и не «поле в базе», а конкретное действие системы.

Если переписать нашу задачу в этих терминах, получится такой список:

  • сгенерировать уникальный трек‑номер;

  • сохранить трек‑номер при создании заказа и вернуть его;

  • найти заказ по трек‑номеру;

  • получить текущее местоположение курьера;

  • сохранить местоположение курьера;

  • вернуть местоположение курьера по заказу.


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

Следующий шаг — сгруппировать эти действия по смыслу. 

Про заказ:

  • сохранить трек‑номер при создании заказа и вернуть его

Про трек‑номер:

  • сгенерировать уникальный трек‑номер;

  • найти заказ по трек‑номеру

Про геолокацию курьера:

  • получить текущее местоположение курьера;

  • сохранить местоположение курьера;

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

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

image2.png

Чёрным цветом обозначен существующий модуль, зелёным — новые модули

Дальше всё действительно зависит от контекста: где провести границы и насколько сильно дробить. Например:
  • хранить ли трек‑номер прямо в заказе или вынести трекинг в отдельную модель;

  • делать ли отдельную таблицу или даже отдельную базу данных;

  • насколько мелко дробить систему.

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

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

image1.png

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

Если сложить всё воедино, то приложение управляет модулями, обращается к ним через публичный API и не лезет внутрь их реализации. Этот API не придуман абстрактно. Он напрямую вытекает из тех бизнес‑действий, которые мы выписали на этапе декомпозиции.


Что такое атомарный коммит

Атомарный коммит — это самостоятельный кусочек логики, который можно понять отдельно от общей логики. Один коммит — одна идея.


Почему атомарные коммиты упрощают работу с кодом и историей

Атомарные коммиты приносят очевидную пользу: легко откатывать изменения, переносить между ветками, ревьюить, находить «плохие» коммиты с помощью git bisect.

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


Как атомарные коммиты тренируют навык декомпозиции

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

Чтобы написать задачу серией атомарных коммитов, разработчику приходится каждый раз отвечать на вопрос: «Что здесь является отдельным, законченным шагом?». Это и есть декомпозиция. 

На практике я вижу две основные проблемы:

  • git является сложным инструментом, с которым трудно перейти «на ты»;

  • дробить большую задачу на маленькие шаги — сложная задача сама по себе.

Атомарные коммиты решают вторую проблему через регулярную практику. Повторение работает лучше любых теорий.


Как писать атомарные коммиты на практике

Всё сводится к очень простому процессу:

  1. Декомпозиция. Хотя бы мысленно расписываем по шагам, как будет решаться задача.

  2. Группировка кода. В один коммит попадает то, что решает одну логическую задачу и изменяется вместе. Например, тесты + реализация или отдельно модуль + отдельно его использование.


Что делать с правками и ревью

Частый страх: «Я выстрою красивую цепочку коммитов, а потом придётся всё переделывать». Если важна чистая история, используйте:
  • git commit ‑fixup <my‑bad‑commit‑hash>

  • git rebase ‑interactive ‑autosquash master

Если история не критична — просто добавляйте новые коммиты. Ничего страшного. 


Как понять, что коммит атомарный

Чёткого критерия нет — все зависит от контекста.

Но есть простой лайфхак: если название звучит как «X и Y», скорее всего, это два разных коммита. Например: «Создание трек‑номера и присвоение его заказу».

Лучше сделать так:

  • «Создание трек‑номера»

  • «Присвоение трек‑номера заказу»


Какие выводы можно из этого сделать

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

Атомарные коммиты — это не просто аккуратная история в git. Это доступный способ тренировать навык декомпозиции каждый день.

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

Похожие новости

Инструменты, которые упрощают iOS-разработку

Старый код усложняет рефакторинг, тесты в команде запускаются по-разному, баги не воспроизводятся на хорошем Wi-Fi, а после обновления инструментов локальная сборка начинает расходиться с CI — по отдельности все это мелочи, но именно они постепенно начинают тормозить разработку.

В статье Ринат, iOS-разработчик Naumen, рассказывает об инструментах, которые помогают ему решать такие задачи и упрощать повседневную работу.

ИИ против ИИ: кто победит в кибербезопасности

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

Денис — руководитель группы мониторинга и анализа инцидентов информационной безопасности в Naumen. Его команда отслеживает события в инфраструктуре, расследует инциденты и помогает коллегам разбираться с вопросами киберграмотности.

В статье на Хабре Денис рассказывает, какие именно изменения привнес ИИ в атаки, почему классическая модель защиты начинает давать сбои и где ИИ в защите действительно приносит пользу.

Как отдохнуть на майских и не потерять эффективность

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

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

Все новости