Настраиваемые свойства отображения для моделей домена

Использование 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);

}

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

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 чем преобразователь с названием "PumpTemperamer".

  • Этот параметр должен быть общедоступным (каждый раз, когда отображается значение, используйте этот параметр). Эту настройку также можно использовать, если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
} 

Плюсы: он лучше разделяет проблемы, чем одна объединенная модель.

Минусы: модель не имеет бизнес-логики, это нормально?


Мы также рассмотрели возможность полного управления этими настройками на внешних уровнях с помощью какого-либо сервиса.

Плюсы: нет доменных моделей без бизнес-логики

Минусы: Возможно, будет привязан к конкретной структуре?


Есть ли еще плюсы / минусы, по которым я скучаю? Один подход явно лучше другого? Есть ли подход, который я полностью пропустил? Спасибо!

1 ответ

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

В случае, если вы считаете это важным для вашей бизнес-логики, его следует смоделировать с вашими сущностями.

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

[table("NameTable")]
public class Transducer
{
    //Name is the ID
    [Key] //is Key from table
    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;
    }

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