【发布时间】:2019-04-12 08:23:24
【问题描述】:
使用 DDD 并遵循干净的架构模式,我对配置特定域模型 ID 的显示属性的理想位置有点困惑。这听起来令人困惑,我想我最好用一个例子来解释它:
这里域模型的业务逻辑很简单:根据输入、增益和偏移量计算“缩放”值。
//Domain Model
public class Transducer
{
//Name is the ID
public string Name { get; set; }
public double Gain { get; set; }
public double Offset { get; set; }
public double RawValue { get; set; }
public double ScaledValue { get; private set; }
public double CalculateScaledValue(double RawValue)
{
ScaledValue = (Gain * RawValue) + Offset;
return ScaledValue;
}
}
我们有一个用例将用户操作与域模型协调并管理持久性。这里的细节并不重要,所以我只包含了一个示例界面:
//implementation of execution of business logic and persistance would go in the implentation, details left out for this example
public interface ITransducerUseCase
{
IEnumerable<string> GetAllTransducerNames();
void AddNewTransducer(string Name, double Gain, double Offset);
void SetGain(string Name, double Gain);
void SetOffset(string Name, double Offset);
void SetRawValue(string Name, double Raw);
double GetScaledValue(string Name);
}
控制器使用用例来协调用例与视图或其他控制器。此特定控制器允许查看所有传感器名称并可以更改其增益属性。
public class Controller
{
ITransducerUseCase _TransducerUseCase;
//these are sent to the view to be displayed
public Dictionary<string, double> _transducerScaledValues = new Dictionary<string, double>();
public Controller(ITransducerUseCase TransducerUseCase)
{
_TransducerUseCase = TransducerUseCase;
//Get all the names and populate the dictionary to display.
foreach (var transducerName in _TransducerUseCase.GetAllTransducerNames())
_transducerScaledValues.Add(transducerName, _TransducerUseCase.GetScaledValue(transducerName));
}
//bound to the view
public string SelectedName { get; set; }
//bound to the view, a property for setting a new gain value
public double Gain { get; set; }
public void OnButtonClick()
{
//update the gain
_TransducerUseCase.ChangeGain(SelectedName, Gain);
//get the new scaled value
_transducerScaledValues[SelectedName] = _TransducerUseCase.GetScaledValue("PumpPressure");
}
}
这就是这个问题的支架。这是新的要求:
我们希望为 为
ScaledValue显示的“小数位数”Transducer基于身份。所以一个带有 Id 的换能器 "PumpPressure" 的值可能与DisplayRounding不同 名为“PumpTemperature”的传感器。此设置必须是应用程序范围的(任何时候值是 显示,请使用此设置)。如果
ScaledValue曾经被记录到一个文件中,所以这是一个横切 业务需求。
我想到的解决方案:
将属性放置在域模型中并通过层将其返回到视图。这似乎不是一个合乎逻辑的地方,因为DisplayRounding 属性与业务逻辑没有任何关联。
public class Transducer
{
//This seems like an SRP violation
public int DisplayRounding { get; set; }
//Name is the ID
public string Name { get; set; }
public double Gain { get; set; }
public double Offset { get; set; }
public double ScaledValue { get; private set; }
public double CalculateScaledValue(double RawValue)
{
ScaledValue = (Gain * RawValue) + Offset;
return ScaledValue;
}
}
如果不在那里,那么在哪里?
我们可以把它放在一个没有任何业务逻辑的单独领域模型中吗?持久性可以由相同的用例类或单独的类管理。
public class TransducerDisplaySettings
{
public int Rounding { get; set; }
//plus other related properties
}
优点:它比使用一个组合模型更好地分离关注点。
缺点:模型没有任何业务逻辑,这样可以吗?
我们还考虑使用某种服务在外层完全管理这些设置。
优点:没有没有业务逻辑的领域模型
缺点:可能会绑定到特定框架?
我还缺少更多的优点/缺点吗?一种方法明显优于另一种吗?有没有我完全错过的方法?谢谢!
【问题讨论】:
标签: c# dns domain-driven-design dto clean-architecture