Все записи

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

Дима руководит группой прикладной разработки в 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. Это доступный способ тренировать навык декомпозиции каждый день.

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

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

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

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

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

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

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

В статье Даша, руководитель группы тестирования UI, делится тем, на что обращает внимание при проверке верстки и какие моменты важно проверять в первую очередь.

Как продакт и аналитик работают в одной задаче: три кейса из практики

Маша, продакт ITSM 365, рассказала в статье, как выстроить взаимодействие аналитика и продакта в одной задаче. В материале — три кейса из Delivery и Discovery, типичные ошибки и решения, которые помогли команде избежать хаоса и навести порядок в процессах.

Все новости