...

воскресенье, 14 марта 2021 г.

Несеребряные пули или кратко про методы софтостроения

Давайте пробежимся по способам софтостроения, придуманным примерно за 70 лет его существования. Их не так много, как может показаться. Но достаточно много, чтобы завести в тупик.

Присказка


Человек по природе адаптивен. Заходишь, к примеру, на кухню, где на гриле вертится курица. Аромат бьет в нос, а если проголодался, так и вовсе слюнки потекут. Минут через пять перестаешь ощущать запах. О еде напоминает лишь крутящийся за стеклом духовки кусок мяса с растопыренными крыльями. Запах-то никуда не делся, его можно померить, но информация с рецепторов заблокирована мозгом.

Такое происходит повсеместно, и софтостроение не исключение. Начинаем с «открытий чудных», что нам «готовит просвещенья дух», плавно переходим к текучке, стыд-и-скрам, спринты-шминты, инкапсуляция-полиморфизм-народность, и, опаньки — крутится себе кусок мяса в печке, грозя подгореть до срока, несмотря на регулярную материальную стимуляцию выше средней по больнице.

В 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 для относительно небольших проектов и команд.

Вместо эпилога

Дедушка Брукс в своем бестселлере выделил четыре типа софта, который люди строят.

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

В условиях, когда человеческий ресурс программистов-техников избыточен при дефиците и сложностях найма проектировщиков и аналитиков, вместо горизонтальной организации («системщики» делают платформу для «прикладников») начинают использовать вертикальную, где каждая команда реализует свои функции на базе собственных велосипедов. С точки зрения управления второй способ выглядит проще, но лишь до того момента, когда вводится горизонтальная команда «архитектуры», снижающая путем долгих уговоров и согласований риски одних и тех же повторяющихся ошибок.

На этом, наверное, можно и остановиться, для начальной ориентации в пространстве информации должно хватить. Ключевые слова и некоторые ссылки в тексте есть, так что любознательные смогут копать тему дальше.

Оригинал текста на сайте «Механика софтостроения»

Let's block ads! (Why?)

Комментариев нет:

Отправить комментарий