Using app-level settings in rich domain models

限于喜欢 提交于 2019-12-11 21:28:02

问题


I want to have a global/app level setting that I want to use in my rich domain models.

I have a method that does some calculations based on the argument passed.

This might not be the best example and might not look like a method belonging to the domain model but I try to keep it simple so you could understand the problem.

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

Now let's say I have many methods like this in my other domain models that also accept CalculationMethod in their methods. I would like to have a global setting so I can set a calculation method globally so it could be used by all methods that take it as a parameter.

One solution would be to read the configuration every time I call this method.

I wonder if there's any better way so I can set CalculationMethod globally and never pass it and instead, having some kind of static variable(singleton) that holds the calculation method and reading it directly inside my methods without passing it. But I think there would be a problem of thread-safety then.

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;
    }
}

I can't pass it in the constructor because it's not something that belongs to my domain model.

How to approach this kind of problem? Is there any way better than the two I mentioned?

I asked this question in the comment under Mark Seemann's answer here: App-level settings in DDD?


回答1:


As Clean Code explains, passing flags to methods is generally considered sub-optimal design. I understand that the OP is a stand-in for another, more complicated problem, but I'd be inclined to recommend to refactor to a polymorphic object model:

public interface ICalculator
{
    decimal Calculate();
}

You can now define implementations as required:

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;
    }
}

You can inject an ICalculator object into any class that has a need for it, using Constructor Injection. In your Composition Root, you can read a configuration file, or in some other way decide which implementation to use, and then create only a single instance of that class. This gives the object Singleton lifetime, so that the calculation method is entirely selected at startup time, and shared among all objects in the application.



来源:https://stackoverflow.com/questions/52327508/using-app-level-settings-in-rich-domain-models

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!