Вопросы архитектуры

Я пишу модуль правил /права. У меня есть два набора данных, один - данные клиента, а другой - данные о продуктах клиента. Данные клиента для данных о продуктах Клиента являются одними для многих.

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

Таким образом, во всех правилах мне необходимо иметь доступ к данным о клиентах и ​​клиентских продуктах (конкретная запись о том, что правила выполняются против). Поскольку все правила могут либо одобрить продукт, либо отказаться от продукта, я создал интерфейс с этими двумя методами и реализует этот интерфейс для всех правил. Я передаю данные Клиента и данные одного продукта для всех правил (поскольку правила должны выполняться в каждой строке данных продукта клиента). Идеальная ситуация заключалась бы в том, чтобы данные о клиенте и клиенте были доступны для правила вместо того, чтобы передавать их каждому правилу.

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

Изменить: Вот что я делаю

public class CustomerContract
{
    public DateTime StartDate { get; set; }
    public DateTime endDate { get; set; }
    //Other Contract related details

}
public class Customer
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string state { get; set; }
}

public class CustomerInfo
{
    public CustomerInfo(int CustomerID)
    {
        Customer = new Customer();// Get Customer from DB
        AppliedProducts = new List<CustomerProduct>();// Get the customer products by customerID
        CurrentContract = new CustomerContract();//Get the contract by CustomerID, State
        declineReasons = new List<int>();// just intailizing. the decline codes are added by rules.
    }

    public CustomerContract CurrentContract { get; set; }
    public IList<CustomerProduct> AppliedProducts { get; set; }
    public IList<int> declineReasons { get; set; }
    public Customer Customer { get; set; }
}

public class CustomerProduct
{
    public decimal AmountCharged { get; set; }
    public int DeclineReasonID { get; set; }
    public int Product { get; set; }
    public decimal DiscountApplicable { get; set; }
    public decimal AmountQuoted { get; set; }
    public decimal Tax { get; set; }
}

public interface IRule
{
    // Since we need to have access to contracts when deciding the eligibility
    CustomerProduct ExecuteRule(CustomerProduct currentproduct, CustomerInfo customerInfo);

    //when denied, 
    CustomerProduct DenyProduct(CustomerProduct currentProduct);
}

public class EligibityEngine
{
    List<IRule>  rules = new List<IRule>();
    private CustomerInfo c;

    public EligibityEngine(int CustomerID)
    {
        c = new CustomerInfo(CustomerID);
        LoadRules();
        foreach (var customerProduct in c.AppliedProducts)
        {
            ExecuteRules(customerProduct);
        }
    }

    private void ExecuteRules(CustomerProduct currentProductItem)
    {
        foreach (var rule in rules)
        {
            currentProductItem = rule.ExecuteRule(currentProductItem, c);
        }
    }

    private void LoadRules()
    {
        // add all the IRule types here
        //rules.Add();
    }
}

Когда я выполняю правило, я передаю данные о продукте и данных клиента. Я должен передать результат выполнения одного правила другому. В приведенном выше шаблоне, если правило изменяет данные в классе customerInfo, оно не сохраняется, если оно не проходит как ref.

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

Я хочу, чтобы метод executeRule был недействительным.

5 голосов | спросил katie77 25 52011vEurope/Moscow11bEurope/MoscowFri, 25 Nov 2011 03:56:20 +0400 2011, 03:56:20

3 ответа


3

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

ответил guillaume31 25 52011vEurope/Moscow11bEurope/MoscowFri, 25 Nov 2011 15:34:00 +0400 2011, 15:34:00
0

Я не уверен, поможет ли этот ответ, но я все равно даю ему шанс.

Основываясь на моем понимании того, что вы говорите, вот мое предложение:

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

Затем создайте интерфейс IRuleContext, который имеет методы для получения интерфейсов для доступа к данным клиента и данным о продукте клиента.

Напишите модуль «Правила», чтобы каждое правило принимало параметр типа «IRuleContext». Например, у вас может быть абстрактный базовый класс «EligibilityRules» с абстрактным методом «bool AppliesTo (IRuleContext)». Затем вы можете реализовать ряд конкретных правил с каждым из них, используя другой алгоритм для определения приемлемости.

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

ответил Manfred 25 52011vEurope/Moscow11bEurope/MoscowFri, 25 Nov 2011 07:28:46 +0400 2011, 07:28:46
0

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

  • Каждое бизнес-правило (правила приемлемости в вашем случае) было реализовано как логический предикат или спецификация.
  • Как и в вашем случае, существуют цепочки правил, которые могут быть организованы в сочетании (операция И) или в дизъюнкции (операция ИЛИ). В случае дизъюнкции параметр должен приниматься по крайней мере одним из правил и это правило должно сообщаться механизмом правил. В соединении параметр должен приниматься всеми правилами, и в этом случае должно быть сообщено первое правило в цепочке.
  • Был интерфейс Rule, который имел три важные реализации: один, делегированный предикату, а два других реализовали соединение и дизъюнкции, описанные выше.
  • Был RuleFactory, который упорядочил правила в порядке, указанном клиентом (что делается с помощью LoadRules() в вашем примере). Этот порядок можно легко изменить без ущерба для любой другой части приложения.

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

ответил Otavio Macedo 26 62011vEurope/Moscow11bEurope/MoscowSat, 26 Nov 2011 19:53:13 +0400 2011, 19:53:13

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132