Intention-Revealing Interface

Я думаю, что у каждого было такое при чтении кода. В одном случае всё понятно с первой строчки, метода, класса. В другом случае можно перерыть тонну кода, но уверенности в его понимании не возникает. В первом случае часто говорят, что его писал профи. Так ли это? И как научиться писать понятный код?!

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

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

Код должен отвечать на вопрос что, а не как.

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

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

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

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

Перейдем к примерам.

Посмотрите на следующий отвратительно красочный пример-гиперболу. В нём беспощадно использован мощный инструмент — Spring Data JPA Query Methods, который строит SQL-запрос по имени метода.

interface AccountRepository {

  List<Account> findByPersonIdInAndDeletedAtNullAndBindingsNotNullOrderByPersonIdAscUpdatedAtDesc(List<UUID> personIds);

}

Что мы вынуждены делать в таких случаях? Провалиться в реализацию метода и начать ментально исполнять код.

findBy PersonId In (personIds) And DeletedAt Null And Bindings NotNull OrderBy PersonId Asc UpdatedAt Desc

Давайте снимем эту ненужную ментальную нагрузку.

interface AccountRepository {

  @Query("""
         SELECT a
         FROM Account a
         WHERE a.personId IN :personIds
           AND a.deletedAt IS NULL
           AND a.bindings IS NOT NULL
         ORDER BY a.personId ASC, a.updatedAt DESC
         """)
  List<Account> findByPersonId(List<UUID> personIds);

}

Согласитесь, что стало “легче”, но этого недостаточно! Метод по-прежнему отвечает на вопрос “как”.

Допустим, нужен не просто список аккаунтов, а список аккаунтов, удовлетворяющий условиям рассылки уведомлений. В итоге, используя имеющийся словарь предметной области проекта (ubiquitous language), принимаем решение назвать метод findDeliverableAccounts. Так мы чётко выражаем намерения и исключаем какие-либо попытки сделать неверные предположения о назначении этого кода.

Рассмотренный принцип называется Intention-Revealing Interface. Он является шаблоном рефакторинга в DDD и естественен для последователей TDD. Помимо прочего, принцип провоцирует писать тесты, которые проверяют функциональность, а не то, как написан код.

И, кстати, частично подобную работу можно переложить на AI, написав промт в стиле:

Проанализируй выделенный метод и места его использования. Предложи название для этого метода, следуя принципам Domain-Driven Design (DDD) и Intention-Revealing Interface. Название должно отвечать на вопрос не как, а что, соответствовать бизнес-цели и использовать слова предметной области (ubiquitous language).

May the Clarity be with you!



Понравилась статья?

Посмею напомнить, что у меня есть Telegram-канал Архитектоника в ИТ, где я публикую материал на похожие темы примерно раз в неделю. Подписчики меня мотивируют, но ещё больше мотивируют живые дискуссии, ведь именно в них рождается истина. Поэтому подписывайтесь на канал и будем оставаться на связи! ;-)

Статьи из той же категории: