ПО как экосистема
«В ходе весьма общих размышлений ... я задался вопросом: почему одни погибают, а другие выживают? Ответ был вполне определенным: в целом выживают наиболее приспособленные... Затем меня внезапно озарило, что этот протекающий сам по себе процесс должен улучшать популяцию... Наиболее приспособленные будут выживать. И я сразу, как мне показалось, увидел все последствия этого» (А. Уоллес).
"Since we cannot expect to have algorithms that perform perfectly in all possible conditions, we would like to create a pool of methods that work very well for a particular situation instead, and use them in conjunction with each other whenever more complex problems are to be solved" (Radu Bogdan).
Хорошая вычислительная схема — это «надежная система из ненадежных элементов»
Сегодня мы поговорим о предметах, имеющих отношение к индустриальной надежности наших алгоритмов. Известно, что всякий зрелый инженерный код должен быть защищен юнит-тестом. Это особенно актуально, если речь идет не о готовом приложении, а о библиотеке с примитивным или вовсе несуществующим фронт-эндом. Причем полезная функциональность должна не просто работать, а работать надежно, если нас интересует качество программного обеспечения, выходящее за рамки требований к университетской лабораторной работе. О важности юнит-тестирования, как первого рубежа «конструкторских испытаний» нашего кода мы немного говорили в другой заметке.
С философской точки зрения, мне кажется весьма удачной аллегория, предложенная одним из архитекторов ACIS в заметке ACIS as an Ecosystem. Заметка небольшая, но я все-таки повторю основные моменты здесь, поскольку они представляются довольно важными в нелегком деле пропаганды «правильного» тестирования. Кроме того, взгляд на сложное (набор изолированных и взаимодействующих компонент) программное обеспечение как на экосистему применим отнюдь не только к «респектабельной» (характеристика Кена Версприлла, изобретателя NURBS) библиотеке ACIS, но и к любой другой библиотеке.
Итак, отдадим должное господину Джону Слоану (John Sloan) — автору указанной заметки — за удачно подобранное сравнение, и двинемся к сути вопроса. Начать следует с того, что «индустриальная зрелость», как характеристика программного обеспечения, определяется вовсе не нашим братом программистом и даже не командой QA. Говорить об этом явлении серьезно можно только по результатам реального применения ПО в промышленности (или бизнесе, это неважно). Сколь угодно исчерпывающая база нерегрессионного тестирования всего-лишь эмулирует применение наших алгоритмов в реальной жизни, но не дает гарантии безупречной работы. Это очевидно, поскольку тестируем мы обычно не совсем то, с чем алгоритму доведется столкнуться вне стен «лаборатории».
Библиотека как экосистема
Так же как ракета-носитель проходит ЛКИ, чтобы заступить в работу, так и программное обеспечение не может считаться предсказуемым и надежным без своего аналога «летно-конструкторских испытаний» — тестов. При этом набор тестов можно рассматривать как воздействие внешней среды на биологическую систему, в которой акторами (зверьками) являются алгоритмы.
Очевидно, что суровые условия среды (много разнообразных тестов) способны выдержать только наиболее подготовленные особи. Естественный отбор здесь обусловлен необходимостью подстраиваться под среду: вы не можете сказать заказчику, чтобы он поменял свои входные данные на что-то более «валидное». В результате отбора часть алгоритмов мутирует, обрастая припарками надежности (что нередко сопровождается нарушением фен-шуя в коде), а часть умирает, не выдерживая пресса и уступая место более приспособленным особям (новым алгоритмам). Процессы, происходящие в таких системах, нагляднее всего иллюстрируются феноменологически (на живых примерах без попыток формализации):
- Пусть алгоритм построения гладких сопряжений работает на точной геометрии, используя три опорные кривые (см. заметку Безье на семействе кривых).
- Другой пример. Пусть параметрическая триангуляция Делоне использовалась для построения конечно-элементной сетки по CAD-модели. Если поверхности, входящие в модель, имеют небольшую кривизну, то доморощенный фасетер может давать удовлетворительные результаты. Однако, если у заказчика найдется «более криволинейная» поверхность, то результаты триангуляции могут оказаться плачевными. В этом случае алгоритм построения регулярной сетки часто дешевле выбросить и использовать сторонний продукт, нежели доводить существующий.
От заказчика поступает модель с «плохой» геометрией, где срединная кривая не имеет точного представления, и алгоритм перестает работать. В этом случае мы имеем дело с несоответствием реальной и лабораторной сред. Модификация алгоритма для работы с толерантной геометрией (см., например, введение в булевы операции для начального знакомства с толерантным моделированием) делает его более надежным для конкретной среды заказчика.
Равновесие
Система пригодна к использованию только в том случае, если ее алгоритмы обладают достаточной надежностью в условиях конкретной среды. Такое состояние системы Джон Слоан именует равновесием (equilibrium), отмечая его хрупкость и чрезвычайную сложность осознания факторов, в результате которых таковое равновесие было достигнуто. Фактически, держать в уме все взаимосвязи между компонентами и степени их влияния друг на друга становится невозможно для человека. Поэтому физически невозможно модифицировать алгоритмы, не нарушая равновесия, если только речь не идет о совсем тривиальных изменениях.
Таким образом, любое изменение экосистемы (в ответ на изменение среды) есть не что иное, как движение от одного неустойчивого равновесного состояния к другому. В каждом равновесном состоянии система отвечает вызовам среды, то есть нерегрессионные тесты проходят успешно. В каждом промежуточном состоянии система не удовлетворяет тестам и мутирует до тех пор, пока очередное равновесие не будет достигнуто.
Зачем нам это?
Имея в виду все сказанное, становится понятно, что следует делать для достижения истинной индустриальной надежности. Рецепт прост: обеспечьте адекватную и предельно агрессивную среду для экосистемы вашего ПО и ищите равновесное состояние в ней. При этом негодные алгоритмы будут исчезать, а перспективные — отращивать когти и зубы, чтобы не спасовать в реальной производственной среде. Такова идея. А ее реальное применение на практике — это целая жизнь.