Дефрагментация мозга. Софтостроение изнутри. Сергей Тарасов
бригады[34] с главным программистом, отвечающим за всё решение. Собственно, и Бьёрн Страуструп, создатель C++, прежде всего преследовал цели увеличения производительности своего программистского труда.
Как только «главным программистом» стал «коллективный разум» муравейника, неважно мечущийся ли на планёрках «гибкой» (agile) разработки, прозаседавшийся ли на совещаниях по тяжёлой поступи RUP[35], проблема мгновенно всплыла, порождая Ад Паттернов[36], Чистилище нескончаемого рефакторинга[37] и модульных тестов, недосягаемый Рай генерации по моделям кода безлюдного Ада.
Термин «Ад Паттернов» может показаться вам незнакомым, поэтому я расшифрую подробнее это широко распространившееся явление:
• слепое и зачастую вынужденное следование шаблонным решениям;
• глубокие иерархии наследования реализации, интерфейсов и вложения при отсутствии даже не очень глубокого анализа предметной области;
• вынужденное использование все более сложных и многоуровневых конструкций в стиле «новый адаптер вызывает старый» по мере так называемого эволюционного развития системы;
• лоскутная[38] интеграция существующих систем и создание поверх них новых слоёв API[39].
В результате эволюционного создания Ада Паттернов основной ценностью программиста становится знание, как в данной конкретной системе реализовать даже простую новую функцию, не прибегая к многодневным археологическим раскопкам и минимизируя риски дестабилизации. Код начинает изобиловать плохо читаемыми и небезопасными конструкциями:
Services.Oragnization.ContainerProvider.ProviderInventory.InventorySectorPrivate.
Stacks[0].Code.Equals("S01")
Последствия от создания Ада Паттернов ужасны не столько невозможностью быстро разобраться в чужом коде, сколько наличием многих неявных зависимостей. Например, в рамках относительно автономного проекта мне пришлось интегрироваться с общим для нескольких групп фреймворком ради вызова единственной функции авторизации пользователя: передаёшь ей имя и пароль, в ответ «да/нет». Этот вызов повлёк за собой необходимость явного включения в. NET-приложение пяти сборок. После компиляции эти пять сборок притащили за собой ещё более 30, б€ольшая часть из которых обладала совершенно не относящимися к безопасности названиями, вроде XsltTransform. В результате объём дистрибутива для развёртывания вырос ещё на сотню мегабайтов и почти на 40 файлов. Вот тебе и вызвал функцию…
Разумеется, превратить код программы в тарелку спагетти можно без особого труда и в процедурно-модульной технологии. Разница в том, что распутывать процедурное спагетти гораздо легче, чем лапшу объектно-ориентированную. Потому что кроме вложенности вызовов процедур в ООП имеет место различного типа вложенность объектов – от наследования реализации до многоуровневых ассоциаций, и совмещение в классах собственно структур данных и процедурного кода.
Несомненно, C++ является
34
Ф. Брукс описывает софтостроение по принципу «операционной бригады» в своей книге «Мифический человеко-месяц»[0].
35
Rational Unified Process – итеративная тяжеловесная методология софтостроения от компаний Rational и IBM.
36
От англ. design pattern – шаблон проектирования.
37
От англ. refactoring – реструктуризация и факторизация программного кода. В экстремальных методиках при отсутствии концепции системы и анализа предметной области формально требуется постоянный рефакторинг кода, при помощи которого предполагается чудесным образом прийти к хорошему решению ничего не проектируя.
38
Термин широко используется в автоматизации предприятий и происходит от «лоскутного одеяла» – разрозненного набора программ и пакетов, решающих локальные задачи подразделений.
39
API (Application Programming Interface) – интерфейс программирования приложений, функциональность, которую предоставляет модуль, компонент или библиотека программисту.