Устойчивый код и реактивное программирование - след (часть 1)

Введение в ландшафт проблем, которые пытается решить реактивное программирование

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

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

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

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

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



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

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

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

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

К реактивности

За последнее десятилетие разработчики добились значительного прогресса в направлении более интуитивно понятных программных архитектур. С профессиональной точки зрения похоже, что функциональное программирование наконец-то входит в мейнстрим. Было создано много новых библиотек и методов для управления состоянием и информационным потоком в нашей кодовой базе. Фреймворки появляются каждый день, предлагая новые способы осмысления сложности. Реактивное программирование - одна из тех идей, которые в последнее время начали все больше принимать в различных сообществах разработчиков. Это не новая концепция, а скорее старый подход, который может иметь большое влияние. На протяжении всей серии статей я буду его анализировать и подробно обсуждать.

С другой стороны, в системах экспертного типа мы видим инструменты, которые упрощают программирование и дают представление о возможном будущем интегрированных сред разработки. Unreal Engine с его« Blueprints - хороший тому пример. Blueprints дает возможность как начинающим, так и опытным разработчикам игр создавать визуальные сценарии, которые обрабатывают задачи программирования, управляемого событиями. Эти сценарии компилируются в код и могут работать в производственных играх без серьезных проблем с производительностью. Посмотрите это вступление, если хотите увидеть, как оно выглядит:

Grasshopper 3D и Dynamo BIM - два примера чрезвычайно популярных инструментов параметрической разработки программного обеспечения, предназначенных для архитекторов. Благодаря этим расширенным интерфейсам сценариев они позволяют нам видеть сложные параметрические 3D-структуры, возникающие сразу же, когда провода и блоки соединяются друг с другом на холсте. ANSYS SCADE - аналогичное решение, используемое для критически важных систем управления. Существует еще много языков визуального программирования, таких как NoFloJs, Scratch и т. Д. Практически во всех областях в настоящее время разработаны аналогичные инструменты и подходы к кодированию. Написание текстовых инструкций больше не является обязательным условием для того, чтобы быть программистом, но в таком мире архитектурные шаблоны становятся еще более важными.

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

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

Что такое реактивное программирование?

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

Реактивное программирование - когда изменяемый модуль отвечает за определение этого изменения.

Не забудьте также прочитать его статью Введение в реактивное программирование, которое вам не хватало. Идея модульного агентства охватывает все происходящее вокруг реактивности. Будь то ячейка Excel, чистая функция или компонент в модели Blueprint Unreal Engines. Любой изменяемый модуль содержит всю логику, определяющую значение этого изменения. Это основное правило, которому удовлетворяет реактивное программирование. Это позволяет отключенным функциональным агентам работать согласованно без утечки или изменения внешнего состояния при реализации модели асинхронного потока данных. Асинхронный поток данных и разделение задач на уровне компонентов делают эти системы хорошо масштабируемыми.

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



В заключение Кевин подчеркивает, что

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

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



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

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

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

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