обсуждении модульности программного обеспечения, сложность сопряжена с затратами, которые необходимо весьма тщательно предусматривать.
13.1.3. Необходимая, необязательная и случайная сложность
В идеальном мире Unix-программисты создавали бы только небольшие, совершенные 'жемчужины программирования', каждая из которых была бы минимальной, изящной и безупречной. Однако одной из негативных черт реальности является то, что она часто ставит сложные проблемы, требующие сложных решений. Невозможно управлять реактивным лайнером с помощью изящной процедуры из десяти строк кода. Существует слишком много блоков оборудования, множество каналов и интерфейсов, множество различных процессоров, т.е. слишком много различных подсистем, определенных независимыми разработчиками, которые часто не согласны друг с другом даже в фундаментальных вопросах. Даже если предположить, что разработчик добился успеха в изящной реализации всех отдельных частей программного обеспечения для авиационной электронной системы управления, в ходе их интеграции, вероятно, будет создан большой, сложный и нечеткий код с одним достоинством — он действительно будет
Реактивные самолеты обладают
Конечно, реактивные авиалайнеры не застрахованы от системных сбоев, возникающих из-за чрезмерной сложности. Но вопросы проектирования проще распознать и проанализировать в программном обеспечении, для которого требования более гибкие, а поиски компромисса между предполагаемыми функциями и сложностью просты. (Здесь и далее в настоящей главе понятие 'функции' используется в весьма широком смысле, который включает в себя различные элементы, такие как прирост производительности или общая степень изысканности интерфейса.)
Для того чтобы добиться более яркого видения проблемы, необходимо начать с определения отличия между
Когда разработчики не могут отличить необязательную сложность от случайной, споры по поводу проекта создают тупиковую ситуацию. Вопросы о том, каковы цели проекта, смешиваются с вопросами об эстетике простоты и о том, кто умнее среди участников спора.
13.1.4. Диаграмма видов сложности
Выше были показаны две различные шкалы для анализа сложности. Данные шкалы фактически перпендикулярны друг другу. Рис. 13.1 может помочь при выяснении связей. В каждом из девяти блоков на рисунке приведен общий источник определенного вида сложности.
Рис. 13.1. Источники и виды сложности
Некоторые из данных разновидностей сложности уже рассматривались ранее в данной книге, особенно случайная сложность. В главе 4 было показано, что случайная сложность интерфейса часто обусловлена неортогональностью в конструкции интерфейса, т.е. невозможностью тщательной организации интерфейсных операций, так чтобы каждая из них выполняла только одну функцию. Случайная сложность кода (создание более сложного кода, чем это требуется для решения задачи) часто является результатом преждевременной оптимизации. Случайное увеличение кодовой базы часто является результатом нарушения правила SPOT, дублирования кода или его неудачной организации, в которой трудно распознать возможности для повторного использования.
Необходимую сложность интерфейса обычно невозможно уменьшить без сокращения основных функциональных требований к программному обеспечению (данная тема развивается далее в настоящей главе при изучении учебных примеров). Необходимый размер кодовой базы связан с выбором средств разработки, поскольку, если список функций сохраняется постоянным, то наиболее значимым фактором в размере кодовой базы, вероятно, является выбор языка реализации (что следует из главы 8).
Источники необязательной сложности наиболее трудно поддаются наглядному обобщению, поскольку они часто зависят от тонких суждений о том, ради каких функций стоит повышать сложность. Необязательная сложность интерфейса часто связана с добавлением удобных функций, которые облегчают работу пользователей, но не являются существенными для работы программы. Необязательное увеличение размеров кода (в предположении, что список доступных пользователю функций и используемых алгоритмов является постоянным) часто может быть следствием различных практических приемов, направленных на то, чтобы сделать код более сопровождаемым. В число таких приемов входит добавление развернутых комментариев, использование длинных имен переменных и т.д. На необязательную сложность реализации часто влияет
С источниками сложности необходимо бороться различными способами. Размер кодовой базы можно уменьшить с помощью лучших инструментальных средств. Сложность реализации можно уменьшить с помощью более тщательного выбора алгоритмов. Сложность интерфейса необходимо исправлять, тщательнее проектируя взаимодействие программы с пользователем, данный навык предполагает анализ эргономических характеристик и психологии пользователя. Это умение менее широко распространено (и возможно, является более сложным в освоении), чем навык написания кода.
С другой стороны, бороться со сложностью необходимо больше при помощи понимания, чем с помощью различных методов. Разработчик уменьшает случайную сложность, понимая, что существует более простой способ решения задачи. Необязательную сложность можно уменьшить, предметно рассуждая о том, какие функции стоит реализовать. Что же касается необходимой сложности, то ее можно уменьшить только с просветлением, фундаментально переопределяющим решаемую проблему.
13.1.5. Когда простоты не достаточно
Неудачное решение вопроса простоты Unix-программистами заключается в том, что они часто действуют так, будто вся необязательная сложность является случайной. Более того, традиция Unix сильно склоняется к тому, чтобы удалять функции во избежание необязательной сложности.
Тем более, что отстаивать эту позицию не сложно (поистине большая часть данной книги направлена на это). Чистый минимализм позволяет нам порой чувствовать себя виртуозами, а минималистское проектирование — весомое противостояние естественной тенденции программных систем развивать все более сложное сопровождение слабо продуманных функций. Однако вычислительные ресурсы и время размышления человека подобны богатству, и их гораздо интереснее использовать, а не накапливать. Разработчику необходимо определить, когда минимализм в проектировании становится не ценной формой самодисциплины, а просто самоистязанием — способом 'приобретения добродетелей' в обмен на отказ от реального