Как разрабатывать программное обеспечение - механизмы правил

Пройдитесь по компонентам минимального механизма правил и поймите некоторые мыслительные процессы, лежащие в основе его разработки.

Представьте себе этот сценарий

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

Какие у вас есть варианты?

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

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

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

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

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

Войдите в систему правил.

Что такое движок правил?

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

Инженеры постоянно, хотя и неосознанно, создают системы, основанные на правилах. Каждый раз, когда вы кодируете оператор if-else, вы фактически создаете жестко запрограммированное правило, которому следует система.

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

Эти так называемые «бескодовые» системы не новы. Программное обеспечение, такое как Zapier, Hubspot и IFTTT, основано на тех же концепциях, что и более технические реализации, такие как Boomi или Drools.

Механизм правил - это система, которая выполняет набор действий на основе определенных условий, которые можно настроить во время выполнения.

Хрупкость бетона

Зачем вообще нужны механизмы правил?

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

В этом есть смысл - код делает именно то, что он говорит, поэтому инженеры должны знать, что нужно сделать, чтобы правильно написать код.

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

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

Примеры включают:

  • «Приветственное» письмо должно быть отправлено через 2 часа после регистрации пользователя.
  • Если на платежном счете содержится более 100 000 долларов США в течение 3 дней подряд, вся сумма должна быть выплачена немедленно.
  • Сотрудники, являющиеся членами этого союза, должны получать отпуск по ставке, вдвое превышающей стандартную, на 2019 год, но не на 2021 год.

Все они также могут различаться по уровню стабильности или по частоте изменения деталей.

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

Когда он действительно меняется, вместе с ним должна меняться и реализация.

Развитие реализации

Давайте рассмотрим гипотетическую реализацию требования к "приветственной" электронной почте по мере его развития.

«Приветственное» письмо должно быть отправлено через 2 часа после регистрации пользователя.

Первый этап

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

Первая (и, к сожалению, часто последняя) реализация большинства разработчиков - это прямой подход.

Это так просто - одна строка кода может удовлетворить это требование:

def on_user_create
   WelcomeEmail.send(in: 2.hours)
end

Второй этап

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

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

Что, если мы обнаружим, что 2 часа - это слишком долго, и захотим изменить их на 15 минут? Если мы это сделаем, инженер должен пойти и изменить его.

def after_user_create
   WelcomeEmail.send(in: 15.minutes)
end

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

Третий этап

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

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

def after_user_create
   WelcomeEmail.send(in: Configuration.get('welcome_email_wait'))
end

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

Четвертый этап

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

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

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

def after_user_create
   WelcomeEmail.send(in: Configuration.get('welcome_email_wait'))
   TipsEmail.send(in: Configuration.get('tips_email_wait'))
end

И снова, однако, требуется, чтобы инженер добавил поддержку нового типа электронной почты.

Изучение эволюции

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

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

В приведенном выше сценарии разработчик решил связать механизм с вариантом использования. Это означает, что разработчик связал вместе что делалось с как что-то делать, почему что-то делалось. Они соединили бизнес-домен с техническим - механизм стал привязан к варианту использования.

Они соединили бизнес-домен с техническим - механизм стал привязан к варианту использования.

Когда мы представили электронную почту с советами и приемами, нам пришлось повторить реализацию. Реализация основывалась на конкретных деталях, а именно, когда что-то было сделано, сколько ждать и что на самом деле было отправлено. Затем эти детали изменились, что вынудило внести изменения в реализацию (также известную как дополнительная работа для инженеров).

Детали не имеют значения

На самом деле эти детали не имеют значения.

С технической точки зрения не имеет значения, будет ли отправлено приветственное письмо через 2 часа после регистрации пользователя или через 15 минут. Не имеет значения, что это было приветственное письмо или электронное письмо с советами и хитростями.

Это сфера бизнеса - это просто варианты использования базовой технологии.

Сама реализация должна оставаться такой же - что касается системы, она отправляет уведомление Foobar при создании записи Whatsittoya и может использовать (в основном) тот же точный код для отправки уведомления Fizzbuzz при удалении Whatchamacallit. записывать.

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

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

[1] Безопасность также включает безопасность работы.

Создание движка правил

Итак, теперь, когда мы изучили контекст, в котором будет полезен механизм правил, как на самом деле его создать?

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

Правило

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

Курок

Триггер - это то, что определяет, должен ли движок попытаться выполнить правило или нет. В большинстве случаев это контекстно.

В простых системах это может быть простая проверка строки или даже жестко запрограммированная, например строка в Правиле со значением on_create и PaymentAccount, чтобы указать, что правило должно выполняться только при создании записи типа PaymentAccount.

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

Состояние

Условие определяет, следует ли применять Правило в этих конкретных обстоятельствах и к этой конкретной записи.

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

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

Само условие, скорее всего, будет иметь некую ссылку на реальный код, который выполняет саму проверку, с некоторыми параметрами, передаваемыми в функцию.

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

Эффект

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

Подобно условию, он, скорее всего, будет иметь какую-то ссылку на реальный код, который применяет сам эффект.

Двигатель

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

Некоторые другие проблемы, вызывающие беспокойство

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

Поток движка правил

Как на самом деле будет работать этот механизм правил?

  • Шаг 1. Запустите двигатель
  • Шаг 2. Получите правила
  • Шаг 3. Проверьте условия
  • Шаг 4: примените эффекты

Шаг 1. Запустите двигатель

Первый шаг - запускается двигатель. Точкой входа может быть функция Engine#run. Этой функции передается запись и связанный с ней контекст (например, если запись создается заново, или движок вызывается при обновлении, и т. Д.)

Шаг 2. Получите правила

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

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

Шаг 3. Проверьте условия

Условие будет логической проверкой, которая определяет, следует ли применять эффекты правила. Если Правило имеет несколько Условий, необходимо выполнить дополнительную логическую логику, чтобы определить, как оцениваются Условия, чтобы определить, применяется ли Правило или нет (например, все или ничего, любой, кворум).

Шаг 4: примените эффекты

Если Условия Правила соблюдены, пора применить Эффекты. Сам Эффект произвольный. Вы захотите определить, как поступать в случаях, когда применение Эффекта терпит неудачу.

Как только это произойдет, Правило будет применено. Вы сделали это!

Конкретный пример

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

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

Можно создать Правило, которое:

  • имел триггер view
  • имел условие view_count было больше, чем 100
  • Эффект от установки поля пользователя на popular

Затем запись будет автоматически проходить через механизм правил и может быть изменена в будущем.

Образец кода

Трудно осмыслить это? Не бойтесь - я создал небольшой репозиторий Github, чтобы проиллюстрировать здесь некоторые концепции.



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

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

Механизмы правил - очень полезные инструменты - в правильном контексте. При правильном внедрении они могут значительно облегчить бремя разработки и повысить гибкость других отделов вашей организации.