Dru Steeby
Dru Steeby

Reputation: 185

Configurable Display Properties for Domain Models

Using DDD and following the clean architecture pattern and I'm a bit confused on where the ideal location is for configuring display properties for specific domain model ID's. That sounds confusing, I think I can best explain it with an example:

Here the domain model's business logic is simple: calculates a "scaled" value from an input, gain, and offset.

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

}

We have a use case that coordinates user actions with the domain models and manages persistence. The details here an unimportant so I've only included an example interface:

//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);

}

The use case is used by the controller to coordinate the use cases with a view or other controller. This specific controller allows the viewing of all the transducer names and can change their Gain property.

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");

    }
}

That's the scaffolding for this question. Here is the new requirement:

The solutions I've thought of: Placing a property in the Domain Model and returning it through the layers to the view. This does not seem like a logical place because the DisplayRounding property does not have any relevance to the business logic.

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

}

If not there, then where?

Could we put it in a separate Domain Model without any business logic? Persistence could be managed by the same Use Case class or a separate one.

public class TransducerDisplaySettings
{
    public int Rounding { get; set; }
    //plus other related properties
} 

Pros: It separates out the concerns better than having one combined model.

Cons: The model does not have any business logic, is this okay?


We've also considered managing these settings completley on the outer layers with some sort of service.

Pros: No domain models without business logic

Cons: Would probably be tied to a specific framework?


Are are there more pros/cons I'm missing? Is one approach obviously better than the other? Is there an approach that I completely missed? Thanks!

Upvotes: 1

Views: 100

Answers (2)

plainionist
plainionist

Reputation: 3573

The central decision you would have to make is whether the display rounding is an aspect of your applications business logic or "just an aspect of display".

In case you consider it as important for your business logic it should be modeled with your entities.

In case you consider it just as an aspect of "presenting values to the user" (so not relevant for business rules) it should be stored in a separate repository or service and then applied by the "presenter".

Upvotes: 1

Emmanuel Menezes
Emmanuel Menezes

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

}

Upvotes: 0

Related Questions