Используя DDD и следуя шаблону чистой архитектуры, я немного запутался в том, где идеальное место для настройки свойств отображения для конкретных идентификаторов модели домена. Это звучит запутанно, я думаю, что лучше всего могу объяснить это на примере:
Здесь бизнес-логика модели предметной области проста: вычисление «масштабированного» значения на основе ввода, усиления и смещения.
//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
на основе идентификации. Таким образом, датчик с идентификатором «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
}
Плюсы: это лучше разделяет проблемы, чем одна комбинированная модель.
Минусы: В модели нет никакой бизнес-логики, это нормально?
Мы также рассмотрели возможность полного управления этими настройками на внешних слоях с помощью какой-либо службы.
Плюсы: нет моделей предметной области без бизнес-логики.
Минусы: Вероятно, будет привязан к определенному фреймворку?
Есть ли еще плюсы/минусы, которые я упускаю? Является ли один подход явно лучше другого? Есть ли подход, который я полностью пропустил? Спасибо!