Использование настроек уровня приложения в моделях с расширенным набором доменов

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

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

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

public decimal Calculate(CalculationMethod calculationMethod)
{
    switch (calculationMethod)
    {
        case CalculationMethod.Multiply: 
            return _x * _y; // _x and _y are fields
        case CalculationMethod.Divide: 
            return _x / _y;
    }
}

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

Одним из решений будет чтение конфигурации каждый раз, когда я вызываю этот метод.

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

public decimal Calculate()
{
    // or read it from file here?
    switch (GlobalSettings.CalculationMethod)
    {
        case CalculationMethod.Multiply: 
            return _x * _y; // _x and _y are fields
        case CalculationMethod.Divide: 
            return _x / _y;
    }
}

Я не могу передать это в конструкторе, потому что это не то, что принадлежит моей модели предметной области.

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

Я задал этот вопрос в комментарии под ответом Марка Симанна: Настройки уровня приложения в DDD?

1 ответ

Как объясняет Чистый код, передача флагов методам обычно считается неоптимальным дизайном. Я понимаю, что OP является заменой для другой, более сложной проблемы, но я был бы склонен рекомендовать рефакторинг к полиморфной объектной модели:

public interface ICalculator
{
    decimal Calculate();
}

Теперь вы можете определить реализации как требуется:

public class Multiplier : ICalculator
{
    public decimal Calculate()
    {
        return _x * _y; // _x and _y are fields
    }
}

public class Divider : ICalculator
{
    public decimal Calculate()
    {
        return _x / _y;
    }
}

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

Другие вопросы по тегам