Проектирование предварительное и проектирование эволюционное
В этой статье я опишу два стиля проектирования, принятых в разработке программного обеспечения. Наверное, наиболее привычным является эволюционное проектирование. Определение "эволюционный" указывает на то, что во время реализации системы ее дизайн растет вместе с ней. Проектирование, в этом случае, является частью процесса программирования, поэтому в ходе развития системы дизайн меняется.
В большинстве случаев, эволюционное проектирование - это нечто ужасное. В конце концов, все равно вместо дизайна системы вы получаете просто набор из специфических решений, каждое из которых затрудняет дальнейшие изменения в программном коде. Часто это вообще нельзя считать дизайном (и, уж конечно, такой дизайн никак нельзя назвать хорошим). Как говорит Кент, дизайн существует для того, чтобы дать возможность оперативно вносить в систему любые изменения. Если дизайн плох, то такая возможность исчезает. В результате вы будете иметь дело с энтропией программного продукта, и со временем и без того плохой дизайн системы станет еще хуже. Теперь вам будет не только сложнее вносить в систему изменения, но и отыскивать и исправлять ошибки, которые начинают множиться с катастрофической быстротой. Все это - кошмар разработок в стиле "code and fix", когда с течением времени исправление ошибок обходится все дороже и дороже.
Предварительное проектирование - полная противоположность эволюционному. Оно построено на идеях, заимствованных из другой области инженерной деятельности. Если вам надо построить собачью будку, то вы сами в состоянии сколотить несколько досок, чтобы получить удовлетворительное подобие желаемого. Если же вы решите построить небоскреб, то прежний способ не подойдет - небоскреб рухнет, прежде чем вы соорудите его хотя бы наполовину. Чтобы этого не случилось, вам нужно начинать с чертежей, которые разрабатывают в инжиниринговых компаниях (вроде той, в которой работает моя жена). Проектируя, она вычисляет все необходимые данные, иногда путем математического анализа, но чаще всего - с помощью "Строительных норм и правил".
Эти "Нормы" представляют собой правила, по которым и создаются проектные конструкции. Все они основаны на опыте реальных работающих решений (ну, и небольшом количестве математики). После того, как работы по проектированию закончены, инжиниринговая компания передает проектные чертежи другой компании, которая занимается строительством.
Приблизительно так же обстоит дело и с предварительным проектированием при разработке ПО. Проектировщики заранее продумывают все основные вопросы. При этом они не пишут программный код, поскольку не создают программный продукт, а только разрабатывают его дизайн. В своей работе они могут использовать такие техники, как UML, что позволяет им абстрагироваться от некоторых подробностей разработок, относящихся непосредственно к программированию. Как только проектный план готов, его можно передавать в другой отдел (или даже в другую компанию), где будут вестись работы по непосредственному созданию системы. Поскольку проектировщики работают на некотором уровне абстракции, им удается избежать принятия ряда тактических решений, ведущих к энтропии программного продукта. Программисты же могут руководствоваться проектным планом и (если они ему следуют) создавать качественно выстроенную систему.
Такой подход к разработке ПО не нов - им активно пользуется множество людей, начиная с 70 годов. По многим показателям он гораздо лучше, чем эволюционное проектирование в стиле "code and fix", однако и у него есть существенные недостатки. Один из главных недостатков заключается в том, что невозможно заранее продумать все вопросы, с которыми придется столкнуться во время кодирования системы. Таким образом, в ходе работ непременно возникнет ситуация, когда у программистов появятся вопросы относительно спроектированного дизайна. А что, если проектировщики, закончив свою часть работы, уже переключились на другой проект? Тогда программисты начинают самостоятельно решать сложившуюся проблему, отступая от уже принятых проектных решений, и внося при этом в программный продукт долю энтропии.
И даже если проектировщик еще работает над проектом и может помочь, все равно ему потребуется довольно много времени, чтобы выяснить ситуацию, внести изменения в диаграммы и уже затем менять код. А при разработке, как правило, вопрос времени всегда стоит остро. Отсюда энтропия (опять-таки).
Кроме того, существует еще и проблема культур. Проектировщиками становятся благодаря высокому мастерству и большому опыту в программировании. Однако, став проектировщиком, программист настолько поглощается новой работой, что просто не имеет физической возможности заниматься написанием программного кода. При этом инструментарий и материалы программных разработок постоянно меняются. А когда вы перестаете сами писать код, вы не только теряете возможность отслеживать новшества в этой области. Вы теряете уважение тех, кто продолжает заниматься написанием программного кода.
Противостояние между разработчиками и проектировщиками мы находим и в области строительства, однако там оно выражено не так ярко, как в сфере программирования. И это не случайно. В области строительства разница в навыках тех, кто проектирует и тех, кто строит, достаточно очевидна. В программировании это не так. Любой программист, работающий с дизайном высокого уровня, должен быть очень хорошим специалистом (достаточно хорошим для того, чтобы задать проектировщику нужные вопросы относительно проектных решений, которые тот предлагает, особенно в тех случаях, когда проектировщик не так хорошо осведомлен об особенностях платформы, для которой ведется разработка системы).
Однако такие проблемы все же можно как-то урегулировать. Может быть, можно что-то сделать с напряженностью в отношениях между людьми. Может быть, можно найти таких проектировщиков, которые могли бы разбираться в большинстве вопросов, и такой дисциплинированный процесс разработки, который позволял бы вносить изменения в диаграммы. Однако остается еще одна проблема: изменяющиеся требования. Именно изменяющиеся требования являются проблемой номер один и главной головной болью во всех проектах, над которыми я работал.
Бороться с изменяющимися требованиями можно по-разному. Один из возможных путей - делать дизайн достаточно гибким, чтобы при изменениях в требованиях его можно было легко менять. Однако для этого требуется заранее знать, какого типа изменения следует ожидать. Да, при проектировании системы можно попытаться угадать те области, в которых наиболее вероятны изменения, и учесть их в дизайне. В этом случае вы, действительно, облегчите себе работу с ожидаемыми изменениями в требованиях, но ничуть не облегчите (а возможно, только ухудшите) ситуацию с изменениями неожиданными. Кроме того, чтобы заранее определить те области, в которых наиболее вероятны изменения, вы должны прекрасно понимать требования, что по моим наблюдениям, очень непросто.
Впрочем, не все проблемы с изменениями в требованиях возникают из-за их непонимания. Множество людей напряженно работает над разработкой технических требований к системе в надежде, что это убережет их от дальнейших поправок при проектировании. Но и так вы далеко не всегда сможете решить проблему. Многие изменения в требованиях диктуются изменениями в экономике и том виде бизнеса, для которого предназначается система. Такие изменения предугадать невозможно, сколько бы вы не сидели над разработкой требований.
После всего этого можно подумать, что предварительное проектирование вообще невозможно. Но это не так. Да, есть серьезные трудности. Однако я вовсе не склонен полагать, что предварительное проектирование хуже эволюционного в его обычной манере "code and fix". Сам я предпочитаю предварительное проектирование, но тем не менее, прекрасно представляю себе все сложности, которые с ним связаны и пытаюсь найти новые пути их преодоления.