[Перевод] Комплексный системный подход к разработке программного обеспечения

b16f3ead0f644a149012784458275ead.jpg

Содержание:

Предпосылки

Разработка программного обеспечения — решение бизнес-задач через построение сложных программных систем. Это такая же система, как в Теории систем — состоящая из многих подсистем, взаимодействующая с другими системами и окружающей средой.

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

Видимо, два самых важных параметра разработки ПО сформулировал Алан Кей. Это человеческие усилия и технологическая сложность:

[…] наиболее важные аспекты языка программирования —
(a) иметь мощные выразительные конструкции для передачи смысла
(b) быть пригодным к изучению, читаемым и гибким, насколько это возможно для пользователей (программистов).
— см. запись Алана Кея.

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

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

Давайте сравним существующие технологии на основе двух описанных выше параметров.

Вертикальная ось — энергоэффективность разработчика с заданной технологией, от низкой к высокой.
Горизонтальная ось — выразительная мощность технологии, также от низкой к высокой.

eb0ca22d01cae037c32c952fab661ea4.pngИ следует помнить, что в системе гораздо больше параметров, которые мы не учитываем или просто не знаем. Поэтому положения элементов на графике не являются точными и детерминированными. Скорее, это наиболее вероятные места для элементов-показателей. Вполне возможно, что некоторые элементы могут быть расположены в каком-то другом месте на графике.

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

b8d8e34a79207088449b2de7c9e6eef9.png

Эволюция

Здесь показан первый интересный паттерн высокого уровня: линии эволюции фреймворка сонаправлены внутри кластеров элементов и указывают на одну и ту же область — верхний правый угол. Вернемся к этому позже.

Еще один интересный паттерн — четкие кластеры в верхнем левом и нижнем правом углах и полоса посередине. Давайте выясним, почему так. 

Рассмотрим участвующие эволюционные силы как третий набор паттернов высокого уровня:

250e843b9548ee47ac5c43fac375846e.png

Красные линии — ограничивающие функции.

Верхняя — предел применимости энергоэффективных (простых) инструментов для комплексных решений. Действительно, легко подобрать очень энергоэффективные инструменты, например, Excel или shell, но эти инструменты нельзя использовать для создания больших, сложных приложений. Чем более совершенное и сложное решение требуется, тем более сложные (менее энергоэффективные с точки зрения человеческого мозга) нужны инструменты.

Правая красная линия обозначает предел когнитивной нагрузки. Чем мощнее и, соответственно, сложнее становятся инструменты — тем менее энергоэффективной становится когнитивная нагрузка, которую они создают для мозга. Вплоть до тех пор, пока они не окажутся непригодными для промышленного применения.

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

d8d2f9db68c19fc86c1e6c55b335a13c.pngИ обратите внимание, что нижний правый кластер не бесполезен. Это источник идей, которые перенимаются другими кластеры.

858706b71f607a9452c278af50476510.png

Игра

Итак, почему существуют кластеры?

Программирование — это управление сложностью. Согласно теории сложности, сложность нельзя контролировать. Но ею можно управлять, устанавливая границы, а затем добавляя механизмы, которые направляют систему в нужном направлении — или удаляя те, которые ведут в неправильном направлении.

Разделим область на зоны вокруг кластеров и посмотрим, какие методы работы со сложностью используются в данных зонах:

1e61dc6d47abd6df533b3404fa4e8d6b.png

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

Автодополнение в IDE привлекает внимание, поскольку делает разработку более стабильной: программисты работают эффективнее, тратя меньше интеллектуальных усилий на исправление ошибок, и больше — решению других вопросов.

Описание решаемой проблемы — конечный аттрактор, оно направляет разработку ПО в нужную сторону.

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

Некоторые аттракторы принудительно вводятся в действие и становятся ограничениями, например, правила линтера. Тесты, системы типов могут применяться принудительно и, таким образом, использоваться для установки ограничений.

Boundaries — наибольшие ограничения. Например, выбранный язык программирования или фреймворк (в смысле акторов в Акке, Эрланге): мы выбираем работу в пространстве, связывая себя с ним. Затем устанавливаем разрешающие и управляющие ограничения, например тесты и типизацию, чтобы ограничить себя внутри границ. Затем используем все, что у нас есть, чтобы направиться в желаемую сторону — принципы, цели.

Подумайте о химическом веществе, например воде. Она может находиться в твердом, жидком, газообразном состоянии, в виде плазмы. У данных состояний разные свойства сложности. Требуется энергия, чтобы перейти из одного состояния в другое. Такие переходы известны как фазовые сдвиги. Вещество поглощает или отдает энергию, изменяет свою сложность и энтропию в зависимости от состояния.

Внешняя система (например, вы) в любом случае должна тратить энергию на управление энергией и на собственные операции, переходя между состояниями.

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

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

Эта картина напоминает еще один фреймворк для управления сложностью — Cynefin:

eca922cae7d325e1c1245a2d1c374ccf.png

Видно, например, как область с нулевыми или специальными ограничениями изменяется и становится областью с:

  • разрешающими ограничениями: модульные тесты, автодополнение в IDE, динамические типы 

  • управляющими ограничениями: сквозное тестирование, интеграционные тесты, системы сильных типов

  • фиксированными ограничениями: чистые, детерминированные системы типов, исчерпывающие тесты на основе свойств

Мы обнаружили, что спектр инструментов разработки ПО сгруппирован по областям на графике, и данные области демонстрируют различные подходы к управлению сложностью, которые совпадают с областями сложности Cynefin. У нас на карте указаны даже пограничные зоны, когда технологии находятся на краю зон, и мы можем получить или вывести полезные свойства из других зон, или переключиться на них для удобства экспериментов.

0d4b03a40b64bc9a738c0f397b48d359.png

Результат довольно интересный. Cynefin — устоявшаяся структура для управления сложностью, со своими собственными методологиями и применениями в других областях, и теперь можно использовать ее для технологической части разработки программного обеспечения.

Программные продукты — сложные системы, которые эволюционируют от первоначального хаотичного состояния до сложного и до конечной упорядоченной системы.

На различных этапах необходимы различные подходы и инструменты, например:
1. Сначала те, что минимизируют затраты на изменения, пока не получится MVP.
2. Затем — те, что сводят к минимуму затраты на отходы при увеличении масштаба продукта и на регрессы для уже существующих устаревших продуктов.

bd458a7ba2ddb01bf2617183ba36c40c.png

18210a695f9767393c46fcd955128c85.pngОбратите внимание, что эволюция разработки программного продукта отличается от эволюции технологии разработки ПО. В этой статье в основном говорится о последнем. А первое является новым компонентом процесса разработки ПО.
  • Эволюция разработки программного продукта идет по пути эволюции сложности.

  • Эволюция сложности определяет выбор правильных процессов, команд, людей и инструментов для каждого этапа.

Правильный инструмент для работы

Теперь понятно, как различные технологии обеспечивают необходимые свойства для стадий эволюции продукта. Данная диаграмма направляет нас в выборе технологий, дает представление о вековом вопросе: «Что значит «правильный инструмент для работы»?

Во время эволюции продукта нужны различные способы решения проблемы управления сложностью:  

  • Сначала нужен быстрый успех, никаких ограничений для инструментов первоначального исследования и моделирования. Понятно, что не требуется писать тесты в данной зоне. 

  • Затем — инструменты, которые предоставят возможности ограничения для быстрого экспериментирования -: линтеры, код-конвенции модульные тесты. 

  • Затем — направляющие ограничения, чтобы масштабировать продукт быстро и без нарушения отдельных элементов. Большинство продуктов стремится остаться в этой зоне. 

  • В редких случаях нужно, чтобы у продукта были детерминированные свойства, чтобы он был полностью упорядоченной системой — есть инструменты и для этого.

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

Первый очевидный ответ — технологический стек, который позволит добавлять и изменять ограничения и аттракторы на лету. Некоторые инструменты на диаграмме именно для этого, например, переход Javascript→Typescript или другие примеры динамических типов.

Менее очевидный ответ — архитектура. Хорошая архитектура перемещает каждый элемент, к которому она применяется, вправо и вверх. Архитектура — катализатор эволюции. С другой стороны, плохая архитектура легко переместит элемент влево или вниз. По диаграмме можно оценить и проверить предлагаемую архитектуру:

36255187810381ddb88c323bfa915205.png

Эта структура применима не только к разработке ПО, но и к любой другой области аналогичной структуры.

Хуже — лучше

Еще один ответ, который мы получим — почему хуже значит лучше. 

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

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

Энтропия — возникающее, высшее свойство систем, которое подтверждается всеми действующими законами.

В нашей системе законы — энергоэффективность и стремление к росту сложности. Данные силы формируют общую картину. Один из способов определения энтропии в данной системе — мера беспорядка в пределах того, что разрешено законами.

Тот факт, что желтые и синие точки распределены почти равномерно и в рамках существующих кластеров, точно соответствует ожидаемому результату. Это наблюдение намекает на то, что энтропия играет свою роль.

Энтропия, в свою очередь, необходима для эволюции, и мы наблюдаем эволюцию на еще более высоком уровне. Это указывает на энтропийную природу системы.

Более глубокие источники энтропии носят информационный характер, связанный с объемом скрытой информации в квантовых запутанных состояниях, как их понимают в настоящее время в физике.

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

Действительно, заметно, что синие, желтые и белые элементы равномерно распределены по диаграмме:

f90d99fa529faf367d189e0456a4141a.png

За пределами технологий

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

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

После проверки на соответствие рынку и получения MVP переходите к этапу масштабирования. В этот период продукт выигрывает от ограничений как в области технологий, так и в области менеджмента. Это scrum, последовательные короткие итерации.

В процессе разработки продукта он приобретает больше функионала, становится более сложным. У него есть определенный внутренний порядок, который необходимо сохранять и поддерживать. И в этом заключается одна из основных трудностей как в области технологий, так и в области управления проектами. С точки зрения последнего это похоже на Shape Up или Scaled Agile, как должно было быть — более длинные итерации, которые включают в себя этапы стратегического проектирования, последовательный рабочий процесс. В значительной степени так можно поддерживать и legacy-системы.

8b29a37081d8dc80183810688e372beb.pngКритически важные приложения, которые стоит реализовать в виде заказанных систем, требуют много предварительного проектирования и построения архитектуры, а также тщательной проверки согласованности. Лучше всего для таких случаев использовать каскадную модель, так как у каждого шага может быть свой темп и сложность, от хаотических исследований на этапе проектирования до длительных этапов поддержки.

Можно свериться с другими фреймворкам с различными командными установками — исследователи, поселенцы, градостроители — и предоставить им правильные инструменты для работы.

Кроме того, мозг каждого человека работает по-разному. Существует три типа мышления, и, как правило, один из них доминирует. 

  • Руководящий — этот метод мышления лучше всего работает в упорядоченных и сложных областях, в рамках соответствующих процессов и с соответствующими инструментами.

  • Абстрагирующийся, видящий суть — хорошее качество для сложных и иногда хаотичных областей, где существуют творчество, изобретения и инновации.

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

Например, критически важные для миссии приложения были разработаны в очень гибкой среде — коммерческая программа NASA для экипажей, где конкурс выиграла SpaceX.

Это подтверждает эволюционное стремление к вершине графика.

Как уже сказано, люди действительно отказываются от попыток построить упорядоченные системы с помощью каскадных моделей и обращаются к более подходящим с точки зрения Теории сложности — строят в сложной области с использованием ограничений, аттракторов и гибких методов.

Инструмент Chaos Monkey — идеальный пример использования негативного аттрактора для большей выгоды.

Будущее

Теперь обратим внимание на верхний правый угол диаграммы. Там ничего нет. Это место для будущих технологий разработки программного обеспечения. По диаграмме можно предсказать, какими свойствами должны обладать эти будущие решения.

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

Видно, что эти инструменты должны пересекать границы ограничивающих функций — стать более продвинутыми, чем человеческая когнитивная способность, и более энергоэффективными, чем современные решения. Энергоэффективность означает автоматизацию, а снижение когнитивной нагрузки — что машины должны  стать более компетентными. Пересечение данных линий — также фазовый сдвиг, поэтому для создания таких технологий потребуется много энергии. Можно предположить, что такие решения потребуют много энергии для работы, потому что сложные вещи с простым интерфейсом означают уменьшение местной энтропии. А поскольку энтропия никогда не уменьшается, мы должны ожидать увеличения глобальной энтропии — то есть потребления энергии.

c73315ef8334c2daa569068b4db0c0dc.pngПересечение пределов энергоэффективности и сложности означает, что программирование становится товаром — не только разработчик, а любой человек может взять и применить такой инструмент, решить задачу и получить приложение.

Как упоминалось ранее, управление сложностью происходит при помощи ограничений, правил и аттракторов. Можно ожидать, что будущие инструменты будут ограничены в зависимости от доменной области и смогут выводить автоматические ограничения — возможно, из совокупности знаний о домене. 

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

b5436cfa81ec00de132f08ef19725a9c.png

Один из примеров — что-то похожее на сервис Amazon Lambda. Он усердно работает над повышением энергоэффективности и скрывает большую часть существенной сложности, но создает свою собственную сложность и не решает бизнес-задач. Потребуется библиотека универсальных архитектурных элементов и автоматическое решение для их объединения вокруг аттрактора — описания проблемы, которую необходимо решить.

Еще один пример — система искусственного интеллекта Github Copilot, который анонсировали сразу после публикации первого черновика этой статьи, буквально в тот же день. Довольно смелый подход — изготовление ИИ для написания кода на уровне функции на основе шаблона, например, имени функции или содержания комментариев. Насколько я понимаю, в настоящее время он работает на уровне оператора (слова), не понимая семантические объекты из кода. Но даже так это выглядит впечатляюще. Он решает проблему ограничения энергоэффективности, автоматически генерируя фрагменты кода, который на графике находится рядом с автодополнением в интегрированной среде разработки. Для начала просто отлично!

53c687da42d7e5f8d8c6112a8734232e.png

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

© Habrahabr.ru