Несеребряные пули или кратко про методы софтостроения
Присказка
Человек по природе адаптивен. Заходишь, к примеру, на кухню, где на гриле вертится курица. Аромат бьет в нос, а если проголодался, так и вовсе слюнки потекут. Минут через пять перестаешь ощущать запах. О еде напоминает лишь крутящийся за стеклом духовки кусок мяса с растопыренными крыльями. Запах-то никуда не делся, его можно померить, но информация с рецепторов заблокирована мозгом.
Такое происходит повсеместно, и софтостроение не исключение. Начинаем с "открытий чудных", что нам "готовит просвещенья дух", плавно переходим к текучке, стыд-и-скрам, спринты-шминты, инкапсуляция-полиморфизм-народность, и, опаньки -- крутится себе кусок мяса в печке, грозя подгореть до срока, несмотря на регулярную материальную стимуляцию выше средней по больнице.
В 1960-х годах один любознательный мужик по фамилии Досс (Richard B. Doss) установил, что в пропитанной протестантским трудоголизмом Америке 70-80 % людей трудятся сильно ниже своих возможностей. Причем, в отличие от робота-манипулятора, белковый работник способен это быстро просечь. Исследования повторяли в "нулевые" и "десятые" с тем же результатом. На здоровье такая ситуация влияет, мягко говоря, неважно.
Цель текста не разубеждать вас в недостаточной продуктивности или давать какие-то советы. Мы только кратко пробежимся по способам софтостроения, придуманным примерно за 70 лет его существования.
Три способа
Не буду тянуть резину, начну с главного. Способов разработки программного обеспечения всего три. Да, три - хорошее число, красивое. Итак:
Нисходящий способ. Это когда сначала глобально думают "что делать", потом "как делать", а потом уже делают, если время осталось.
Восходящий способ. Это когда сначала делают, понемножку, мелкими частями. Думают "что, да как" только над этой частью, не заморачиваясь на глобальное и непреходящее.
Спиральный способ. Начинаем думать глобально, но по звонку будильника просыпаемся и выкатываем прототип. И так несколько раз, накапливая опыт, пока не появится решение согласно требованиям.
Нисходящая разработка
В просторечии все нисходящие методы обзывают "водопадом". Если вам уже рассказывали о существовании нескольких штук аджайлов, то такая "простота хуже воровства" должна вызывать подозрения.
Сошествие способа в массы приходится на 1960-е годы, органично дополняя требования структурного программирования мыть руки перед едой и пользоваться столовыми приборами и салфетками. Глобальная задача делилась на более мелкие подзадачи, те, в свою очередь, на еще более детальные и так далее до уровня структурного блока, который можно непосредственно реализовать на языке программирования. Кстати, тесты к этим блокам пишутся параллельно, привет TDD-шникам из 1960-х.
Русская пословица "Семь раз отмерь -- один раз отрежь" как раз про нисходящий метод.
В ортодоксальном варианте "водопада" фидбэк от заказчика поступает только после поставки сделанного. Год трудились, выкатили рояль из кустов, оказалось "не совсем то", нужны доделки. А заказчик, тем временем, родил длинный список новых функций. С непривычки немного стремно в такой схеме работать. Поэтому в гуманном варианте вернуться для уточнений на предыдущую стадию можно с любой точки, получается "каскад с возвратами".
Преимущества способа ясны. Чем больше продумано в начале, тем меньше лишней работы придется делать в середине и конце. Исключается многократное переизобретение велосипедов, дублирование функций и ошибок.
Однако, если функций изначально много, то родить правильную разбивку нелегко. Нужны хорошие аналитики, проектировщики с опытом работы в данных предметных областях. И даже в этом случае есть риск затянуть планирование реализации на неприличный срок.
В дальнейшем способ неоднократно улучшался, например V-метод, где стадиям разработки по левому спуску буквы "V" соответствуют стадии тестов и приемок подъема справа. По горизонтальному уровню сразу видно, какой проектный документ подрядчика служит основанием для приемочного документа заказчика.
Понятно, что улучшения не могут преодолеть принципиальных ограничений способа. На то они и принципиальные. Это не значит, что способ плох. Просто у него есть риски вот такого типа. Если можно риски парировать, то все отлично, начинаем думать и наслаждаемся преимуществами по ходу процесса.
Восходящая разработка
На самом деле, восходящий способ еще древнее нисходящего. В 1950-х уже существовали и Фортран, и Кобол, но не было ясных представлений, как строить софт. Поэтому поступали самым естественным образом: сегодня сделаем одно, завтра другое, потом когда-нибудь склеим в третье. Если нужно реализовать несколько задач, то выбираем наиболее важные.
Иногда способ также называют инкрементальным, видимо, по аналогии с i++
. Добавили функцию -- инкремент. При желании натянуть глобус на меркаторову проекцию инкрементальным можно обозвать и спиральный метод, но об этом позже. Способ также любят изображать в виде цикла, хотя для i++
не определены конечные значения, поэтому "копать" придется "отсюда и до обеда". Продолжая тему русских пословиц, есть у нас поговорка "крутится, как белка в колесе" -- вот это как раз про восходящий способ.
Методика была и остается наиболее характерной для домашних (in-house) разработок. Свои программисты должны делать то, что нужно для бизнеса еще вчера. Чтобы думать о более глобальном, в 1960-х появились "софтверхаузы" -- крупные проектные конторы по разработке заказных систем, включая таких монстров, как IBM.
Продолжалось все это восходящее софтостроительство без существенных изменений до 1990-х. Основная борьба за соответствие академических теорий инженерной практике обошла стороной тихую гавань, потому что велась в джунглях нисходящих и спиральных методов.
В 1990-х годах пошел мощный тренд замены "домашних" программистов на внешних консультантов. Одна из причин -- усложнение технологий и специализация, труднодостижимая внутри фирмы для которой софтостроение -- непрофильная деятельность. Домашний софт теперь разрабатывается временными командами шабашников контрактников. Изменились отношения, а заказчик -- не спец во всех этих методологиях, анализах, архитектурах. Заказчик в лучшем случае знает, в чем отдельные проблемы и может расставить над ними приоритеты. Команда контрактников в свою очередь, не знает о бизнесе заказчика достаточно, чтобы cпланировать всю реализацию.
В такой ситуации простой метод "функция за функцией" снова кажется подходящим. Но при работе с подрядчиком на подневной ставке требуется больше контроля, чем за штатными работниками "на окладе". Подход нужно адаптировать, избегая бюрократических процедур. Действительно, чтобы "выдать техническое задание" требуется общее планирование и соответствующие документы, то есть, воленс-ноленс, пришлось бы переходить на формальные нисходящие или спиральные методы. А зачем это нужно транспортной компании или производителю авто, например? Люди просто хотят решить небольшую внутреннюю проблему, зарплату там посчитать, или свести расписание отпусков.
Спрос рождает предложение, к концу 1990-х появились так называемые проворные agile методы, худо-бедно позволявшие заказчику держать руку на пульсе, а подрядчику постепенно понять, что, собственно, они реализуют.
Что улучшилось:
- планирование по-прежнему короткое, но охватывает не одну функцию, а их группу при этом срок этапа жестко ограничен;
- ведется протокол сделанного;
- теоретически, должно выделяться время на упрощение и чистку кода (рефакторинг);
- теоретически, риски регрессии должны парироваться всеобъемлющими тестами.
Почему я пишу "теоретически"? На практике при ограничении бюджета или в цейтноте этими двумя пунктами жертвуют в первую очередь. "Святая корова" в аджайлах отнюдь не качество кода, как задумывали авторы, а срок сдачи очередной функции.
Дублирование кода, ненужные усложнения, отложенные "на потом" неэффективные реализации -- если вовремя не разгребать сделанное ранее, то растет технический долг. Чем позже долг возвращается, тем больше в итоге приходится платить: временем, человеко-днями, ошибками, сбоями, медленной работой и т.п.
Спустя каких-то 10-15 лет авторы "Манифеста аджайла" начали бить в набат: "Ребята, что вы делаете, мы имели в виду другое". Они в чем-то правы, восходящая разработка так проста и тем притягательна, что все эти дополнительные процедуры кажутся необязательными.
Подведем итоги, что в восходящей разработке хорошего. Прежде всего, резко снижается порог входа. Чтобы запуститься "с нуля" не нужны дорогущие спецы по анализу и проектированию с опытом. Хотя вся стройка может длиться бесконечно, первые бараки возводятся скоро, и в них можно начинать обживаться. Управлять процессом проще, контрольные точки и локальные цели прозрачны.
Проблемы, как и в случае с "водопадами", принципиальные. Проще управлять процессом, но практически невозможно -- конечным результатом, так как он нигде четко не фиксируется. Риски перекладываются на заказчика: пускай владелец продукта думает, у него башка большая. Если с технической архитектурой при наличии опыта, тестов и рефакторинга команда справляется (до определенного порога сложности), то с архитектурой функциональной дело плохо. Упрощение постановки задачи, тот самый "рефакторинг", теперь уже модели предметной области, помог бы избавиться от навороченного и дорогого в сопровождении кода, но сделать его некому. Да и модели-то нет, если честно, вся семантика в головах и в коде.
Но нет повода расстраиваться, вспомните про самый провальный спринт в мировой истории: 5 дней сотворения и полтора миллиарда лет непрерывного рефакторинга.
Спиральная разработка
Упомянутые "водопадные" ограничения стали ясны еще в 1970-х, после массовых внедрений соответствующих методологий типа SADT/IDEF. Параллельно работали и по восходящим методикам на "домашних" проектах с другими заморочками, что создавало ощущение некоторого тупика. Поэтому озадаченные проблемой исследователи (прежде всего Barry Boehm), почесав репу, выдали к середине 1980-х годов обновленное видение процесса софтостроения в виде спирали.
Логика рассуждений "спиральщика" примерно такова. Да, с ростом сложности задач мы тратим все больше времени на анализ и проектирование, риск ошибок на этой стадии растет. Но реализуя отдельные функции без общего плана мы рискуем ошибиться не меньше, получив в итоге неэффективно работающие или просто несовместимые части. Поэтому оставим в покое "святую корову" -- проектирование, но а) ограничим ему сроки и б) будем жестко проверять принятые решения, выкатывая полный прототип.
Пункт "б" очень важен. При восходящей разработке вы тоже постоянно что-то выдаете, багфиксы там, новые фичи. Но это сработает, если система уже в эксплуатации и на сопровождении. А если нет? Представьте, заказчик хочет систему управления движением поездов, а вы ему через пару-тройку недель показываете экраны ввода информации о подвижном составе и симулятор расписания. Несерьезно.
Прототип должен включать в себя большинство функций, пусть не до конца реализованных или даже с "заглушками". С полного прототипа, соответственно, получаем и полный фидбэк: здесь облажались, не поняли сути требований, тут не учли среду эксплуатации, там выходной формат не стыкуется с входным и т.д. С этим драгоценным фидбэком начинаем второй виток спирали, обоснованно полагая высоким шанс довести следующий прототип до уровня готового продукта. Системам среднего масштаба (до миллиона строк кода примерно) два-три витка хватает.
Из сказанного понятно, что относить спираль к инкрементным способам так же нелепо, как китов к рыбам, хотя у тех и других есть хвост.
Что в спирали хорошего? Мы резко снижаем риски выкатить заказчику вместо продукта откровенную лажу, но при этом не приносим в жертву проектирование. То есть, глобальное видение ситуации сохраняется, конечным результатом можно управлять, рассчитывая бюджет и прибыль. Всем, клиенту и подрядчику, виден свет в конце тоннеля. Заказчик, если он серьезен в намерениях, тоже не будет бухтеть: "Что вы мне то хвост, то хобот подсовываете, покажите мне всего слона!" На каждом витке слон виден целиком.
Однако, по сравнению с восходящим софтостроением, обойтись взводом программистов-техников без аналитиков и проектировщиков не получается, и вам придется объяснять этот щекотливый момент заказчику в обосновании более высокой цены. После стадии проектирования первого витка спецы не простаивают, а продолжают вгрызаться в задачу, ожидая фидбэк, но на финальном витке они, скорее всего, вообще не понадобятся. Длина витка может составлять до нескольких месяцев, но обычно обходится двумя-тремя. На еженедельный спринтовый экстрим не похоже, но и на годовое ожидание продукта тоже. Нелегким остается и выбор, когда на данном витке "уже хватит проектировать" и пора начинать класть кирпичи.
Наиболее известная и успешная реализация спиральной методики -- MSF (Microsoft Solution Framework). У Микрософта позднее появилась и обстриженная версия, заточенная под восходящие методы, и продаваемая как MSF for Agile для относительно небольших проектов и команд.
Вместо эпилога
Дедушка Брукс в своем бестселлере выделил четыре типа софта, который люди строят.
На картинке видно, что в некоторый момент вы можете перестать "просто писать программу" и "за втридорога" захотеть сделать из нее то ли продукт (то, что поставляется множеству разных клиентов), то ли комплекс (то, что состоит из многих программ и бесшовно интегрируется в среду заказчика, включая оборудование). И если "писать программу", по большому счету, можно любым из софтостроительных способов, то ваши прекрасные планы по дальнейшему развитию могут быть нарушены недостатками нисходящих и восходящих методов.
В условиях, когда человеческий ресурс программистов-техников избыточен при дефиците и сложностях найма проектировщиков и аналитиков, вместо горизонтальной организации ("системщики" делают платформу для "прикладников") начинают использовать вертикальную, где каждая команда реализует свои функции на базе собственных велосипедов. С точки зрения управления второй способ выглядит проще, но лишь до того момента, когда вводится горизонтальная команда "архитектуры", снижающая путем долгих уговоров и согласований риски одних и тех же повторяющихся ошибок.
На этом, наверное, можно и остановиться, для начальной ориентации в пространстве информации должно хватить. Ключевые слова и некоторые ссылки в тексте есть, так что любознательные смогут копать тему дальше.
Пока и берегите здоровье!
blog comments powered by Disqus