0

The application is an API. Users can post data to the API, which is then transformed to a domain object.

I am wondering where to apply the domain rules, in the domain object.

Let's make it more clear with a real-world example:

Users input a calculation, with a Name and a CalculationScript. For ease of use, they are allowed to use square brackets in the script: [3-(5+2)]+9 is valid.

However, the domain object can only contain standard brackets, and square brackets are transformed.

I am wondering whether I should apply the rules in the constructor, or maintain knowledge of the raw string, and sanitize in the getter.

Is there a specific pattern it is common to use for such cases?

Assuming this very simple DTO:

public class CalcDto{
    public string Name {get;}
    public string CalcScript {get;} 
}

Do it in the constructor:

public class CalcDomain{
    public string Name {get;}
    public string CalcScript {get;}

    public CalcDomain(CalcDto dto){
        this.Name = dto.Name;   
        this.CalcScript = replaceSquareBrackets(dto.CalcScript);
    }
    private string replaceSquareBrackets(string str){
        //...
    }
}

Do it in the getter

public class CalcDomain{
    public string Name {get;}
    private string RawCalcScript;
    public string CalcScript {get => replaceSquareBrackets(RawCalcScript);}

    public CalcDomain(CalcDto dto){
        this.Name = dto.Name;   
        this.RawCalcScript = replaceSquareBrackets(dto.CalcScript);
    }
    private string replaceSquareBrackets(string str){
        //...
    }
}

1 Answer 1

2

In your specific case, the ability to use different kinds of brackets is really nothing more than a UI feature for your user. As such, I would contain the multi-bracket feature (and its inherent conversion method) to the UI itself.

In a web solution , I would do the conversion in Javascript and have the web application itself never be aware of multiple brackets.
In a WinForms/WPF application, I would have the Form/Window/Control handle the conversion in its code-behind.

EDIT I had missed part of your question:

Users can post data to the API, which is then transformed to a domain object.

I would consider the API the user's interface (since that's the layer they communicate with), and therefore do the conversion in the API. Ideally, you DTO/domain classes never contain multi-bracket values (other than your controller input model, if you have one)


You asked the question under a more general scope, so I want to point out that this is very dependent on what type of validation you have, and what your priorities are.

There are two major types of validation: client-side and server-side.

Note:
For local WinForms/WPF, there is usually little technical difference between frontend and backend since they are one application. The argument here mostly relies on a split front/backend application, where any communication between the two is a non-negligible cost. This can also apply to WinForms/WPF if the application still connects to a remote backend service.

There are three major considerations: user experience, data security (= avoiding invalid data), and ease of development.

  • Client-side validation has a high user experience (fast feedback, no page reloads) but a low data security (clients can circumvent local validation).
  • Server-side validation has a high data security ("gatekeeping" the database at the source) but a low user experience (needing a postback to confirm data validity)
  • Server-side AND client-side has the best of both worlds, but lowers the ease of development (having to ensure both validations are always up to date with each other).

Which one you choose depends on your priorities. Sometimes, not all priorities matter:

  • When creating a tool for developers, you can assume no malice and therefore don't have to worry about users circumventing the client validation.
  • There are cases of complex validation that require you to have access to the database, thus forcing you to rely on server-side validation.
4
  • Thank you @Flater for a very comprehensive answer! Unfortunately, I have no control over the front-end, but I guess the closest thing would be to do it in the controller, no?
    – Maxime
    Commented Jul 17, 2018 at 13:06
  • @Maxime I have already updated the answer :) Yes, the controller is, in a way, "the user's interface" :) The main point was to contain the "dirty" multi-bracket values to the smallest scope possible, which means converting immediately upon receving the value and ideally never have your state contain the dirty values.
    – Flater
    Commented Jul 17, 2018 at 13:09
  • I agree the best user experience will result from doing the validation in the UI frontend. And I agree for safety and security, the ONLY place that matters is the server side. So doing it in both makes sense. But I would probably NOT do the validation in the object constructors. I would do the validation in the web-service methods - as almost the first line or two - of those methods. I would write a Validate (or series of validation) methods for the arguments, and call it on each bit of data as it enters your system, and raise exceptions (which get mapped to 400 errors) on failure to validate. Commented Jul 17, 2018 at 15:01
  • @LewisPringle It really depends. If you build your application in multiple platforms (mobile, windows service, WPF app, ...) Doing it in the top layer meams you have to do it in every top layer. A better place is the repository or business layer, as this is intended to be the SPOC for data retrieval/updates. The performance cost of drilling down a layer or two, when done with no intermediary steps, is completely negligible.
    – Flater
    Commented Jul 17, 2018 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.