Проектирования больше нет

         

"Простой дизайн" - что же это за зверь такой?


Итак, мы хотим, чтобы наш программный код был максимально прост. С этим никто не спорит. В конце концов, кому нужно, чтобы код был сложный и запутанный? Осталось только понять, что мы разумеем под словом "простой".

В книге Extreme Programming Explained Кент приводит четыре критерия простой системы. Вот они в порядке убывания важности:

  • Система успешно проходит все тесты
  • Код системы ясно раскрывает все изначальные замыслы
  • В ней отсутствует дублирование кода
  • Используется минимально возможное количество классов и методов

Успешное тестирование системы - довольно простой критерий. Отсутствие дублирования кода тоже вполне четкое требование, хотя большинство разработчиков нужно учить, как этого достичь. Самое сложное скрывается в словах "раскрывает изначальные замыслы". Действительно, что же это значит?

Основное достоинство программного кода, в данном случае - его ясность. ХР всячески подчеркивает, что хороший код - это код, который можно легко прочесть. Скажите ХР-шнику, что он пишет "заумный код", и будьте уверены, что обругали этого человека. Но понимание замыслов программиста, написавшего код, зависит также и от опыта и ума того, кто этот код пытается прочесть.

В своем докладе на конференции XP 2000, Джош Кериевски (Josh Kerievsky) приводит хороший пример на данную тему. Он подвергает анализу, возможно, самый открытый из всех кодов ХР - JUnit. JUnit использует декораторы (паттерн Decorator), для того, чтобы дополнить тестовые сценарии дополнительным поведением, таким как синхронизация доступа и установка начальных предусловий для групп тестов. Так как подобное поведение реализуется в отдельных классах-декораторах, код тестов становится проще, чем если бы эта функциональность присутствовала в них самих.

Однако в данном случае нужно задать себе вопрос: а понятнее ли будет код, полученный в результате этих операций? С моей точки зрения да, но я-то знаком с паттерном Decorator. Для тех, кто не имеет о нем ясного представления, этот код может показаться довольно сложным.
Аналогично этому, в JUnit используются методы-вставки (pluggable methods), которые, по моим наблюдениям, большинство программистов расценивают как что угодно, но только не как простое и понятное решение. Получается, что структура JUnit является простой для опытных проектировщиков, но сложной для менее опытных программистов?

Я думаю, что одним из самых очевидных и полезных советов, которые только можно дать, это избегать повторов в коде, как провозглашается в ХР ("Once and Only Once") и в книге Pragmatic Programmer's (принцип DRY - Don't Repeat Yourself). Следуйте этому принципу, вы уйдете далеко вперед. Но это далеко не все, что необходимо для простого дизайна. А создать простой дизайн - это весьма сложная задача.

Недавно мне пришлось работать над системой с весьма заумным дизайном. После проведенного мной рефакторинга дизайн лишился некоторой гибкости (за ненадобностью). Однако, как заметил один из разработчиков, "гораздо проще делать рефакторинг системы со сложным дизайном, чем рефакторинг системы, у которой дизайна вообще нет". Лучше всего быть немного проще, чем требуется, но нет ничего ужасного в том, чтобы быть немного сложнее.

А самый лучший совет, который я слышал по этому поводу, исходил из уст "Дядюшки Боба" (Роберта Мартина). Заключается он в следующем: не стоит сушить голову над вопросом, как сделать дизайн максимально простым. В конце концов, позже вы сможете (и должны, и будете) заняться рефакторингом. В конце работы над проектом желание делать рефакторинг гораздо важнее, чем точное понимание того, какое решение является самым простым.


Содержание раздела