Благодаря очередной революционной новинке под названием .NET многие компании воспользовались представившейся в очередной раз возможностью переделать и пересмотреть свои существующие приложения. Сегодня я вам расскажу небольшую историю об одной такой организации (большой розничной компании), решившей перепроектировать большую часть своей основанной на COM системы исполнения заказов, которая была создана при помощи прошлой революционной новинки - Windows DNA.

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

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

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

Ниже представлен код, создающий правило определяющее должен ли заказ быть отменен или нет. Даже не знаю, что здесь для меня интереснее всего: то, что комментарии содержат эквивалентный код на C#, то, что это является, возможно, самым большим конструктором в мире или то, что это сможет работать с такой системой, которой требуется сравнивать только строки. К счастью .NET 2.0 возможно предоставит очередную возможность снова переписать всю систему...

/////////////////////////////
// CanCancelOrder
/////////////////////////////
// Определяет подлежит ли заказ отмене:
// (
//   (   order.OrderStatus != OrderStatus.Approved
//    && order.OrderStatus != OrderStatus.Packed
//    && order.OrderStatus != OrderStatus.Billed
//    && order.OrderStatus != OrderStatus.Shipped
//    && order.OrderStatus != OrderStatus.Canceled
//   )
//   || ( IsAuthorizedForOperation (
//          currentUser,
//          Operations.LateStatusCancel ) )
// )
/////////////////////////////
_ruleset.AddRule
(
  new EreRule
  (
    OrderRule.CanCancelOrder,

    // -- Заказ может быть отменен если -- //
    new EreRuleAtomGroup[]
    {
      // -- Статус - OK -- //
      new EreRuleAtomGroup[]
      {
        // ( order.OrderStatus != OrderStatus.Approved
        new EreRuleAtomGroup
        (
          new EreRuleAtom[]
          {
            new EreRuleAtom
            (
              order.OrderStatus,
              Operands.IsNotEqualTo,
              OrderStatus.Approved
            )
          }
        ),
        ...
        // && order.OrderStatus != OrderStatus.Canceled
        new EreRuleAtomGroup
        (
          EreRuleAtomGroupType.And,
          new EreRuleAtom[]
          {
            new EreRuleAtom
            (
              order.OrderStatus,
              Operands.IsNotEqualTo,
              OrderStatus.Approved
            )
          }
        )
      },

      // -- Пользователь авторизован  -- //
      new EreRuleAtomGroup[]
      {
        //   || ( IsAuthorizedForOperation (
        //          currentUser,
        //          Operations.LateStatusCancel ) )
        new EreRuleAtomGroup
        (
          EreRuleAtomGroupType.Or,
          new EreRuleAtom[]
          {
            new EreRuleAtom
            (
              IsAuthorizedForOperation(
                  currentUser, 
                  Operations.LateStatusCancel),
              Operands.IsEqualTo,
              true
            )
          }
        )
      }
    }
  )
)

А чтобы проверить можно ли отменить заказ, просто напишите IsRuleValid(OrderRule.CanCancelOrder) ...

Оригинал:http://worsethanfailure.com/Articles/The_Enterprise_Rules_Engine.aspx
Перевод:Евгений Виговский