2

I recently asked a question about validation here: What is the "best" way to apprach validation from the perspective of a DDD purist?

Please see the code below, which I borrowed from here:

if (string.IsNullOrWhiteSpace(email) || email.Length > 100)
            throw new ArgumentException(“E-mail is invalid”);
        if (!Regex.IsMatch(email, @”^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$”))
            throw new ArgumentException(“E-mail is invalid”);

This makes sense. If the user enters an invalid email then the application throws an exception.

Now, say I was developing an application to accept credit card applications. To apply for a credit card in the UK you have to be 18 or over by law (I believe). Say a user enters a date of birth that means they are 17. Is this a validation failure? 17 is a valid age to be. I realise -1 is an invalid age; however what about 0-17?

On the presentation layer there would be JavaScript in place to stop users continuing if they are below the age of 18, however say a user managed to reach the domain layer because JavaScript was disabled on the browser or the developer of the presentation layer/application layer failed to enforce this properly.

w0051977
  • 7,031
  • 6
  • 59
  • 87
  • 2
    Depends on your domain and application requirements. I would say yes, but I wouldn’t throw an exception, but rather a string with the error message to the UI. – G.T.D. Oct 15 '17 at 12:35
  • 1
    @B313, I believe it should throw an exception because it would mean the presentation layer has not done it's job properly. – w0051977 Oct 15 '17 at 12:42
  • 3
    Ok. Like I said, it depends on your domain and application requirements. – G.T.D. Oct 15 '17 at 12:45
  • Its not the presentation layer's responsibility to ensure the domain models are valid. That responsibility is the domain models. – Andy Oct 15 '17 at 14:52
  • @Andy, just following the fail fast principle preventing unnecessary roundtrips to server. The domain model will do the validation as well. – w0051977 Oct 15 '17 at 14:57
  • At quick glance your email validation will reject .info even though it's a valid TLD, or any valid TLD over 3 characters – whatsisname Oct 15 '17 at 23:32
  • Your email checking regex will throw an exception for valid email addresses (eg, `fred@fredbloggs.blog` doesn't match), so throwing an exception for a valid age makes equal sense... – David Arno Oct 16 '17 at 10:45

2 Answers2

3

I believe it should throw an exception because it would mean the presentation layer has not done it's job properly

While throwing may be still be fine, this is not necessarily an issue of UI.

The way you are phrasing the question, you're postulating an unknown and underage user is entering their birth date on a UI form for credit application.

But what if the (underage) user is already known to the system, e.g. because they have an ATM card or savings account (and let's presume here that then the system knows their birth date).

And now they apply for a credit card as a logged in user. If you already know their birth date, you wouldn't expect them to fill out a form with their birth date.

So, in this case, their credit application would not meet the business rules for issuing credit cards. So, in accordance with @Ewan's answer, depending what the business wants, you should either not accept their credit application in the first place, or accept it and then subsequently deny the application in processing.


Would an age between 0 and 17 cause validation to fail?

and

@Andy, just following the fail fast principle preventing unnecessary roundtrips to server. The domain model will do the validation as well.

These sound like you're thinking of this as basic model validation.

However, I consider what you're talking about as a business rule for a specific business function (credit card issuing), rather than as basic model validation. (e.g. just because this customer can't get a credit card doesn't mean the model is invalid.)


In short,

  1. Do what the business wants both in terms of business rules and the UI experience. For example, is fail fast (of credit applications) driven by business interests or it is a programmer idea?

Usually fail fast would be about catching typo's the user can immediately fix. So, for an invalid or malformed date (e.g. Feb 31st, 00/00/0000) make sense, though for a valid date that is underage for some operation probably doesn't.

  1. Put business rules in the most appropriate place for them for the purposes of long term maintainability of the software. (In this case somewhere along the path where credit cards are issued.) If you duplicate business rules into the UI for fail fast purposes, you should be aware that you are doing that.

Making copies of code is considered WET (vs. DRY). (Making copies of data is considered caching or denormalizing, depending on context.) In general when we make copies (code or data), we are trading off performance for complexity. Complexity, being error prone, requires more testing right off. Also, copies hamper maintainability as they can go out of sync with each other.

Erik Eidt
  • 33,282
  • 5
  • 57
  • 91
1

A good example. I would use a combination of the techniques from your previous question.

You could make Age a new value type which cant be less than 0. (although date of birth is prob better all round in this particular example)

The form the user enters has its own separate presentation logic to help guide the user fill it in successfully.

The Domain Object should check the business requirements in the Sell Method and throw exceptions (or perform appropriate alternate logic) when they fail.

This allows you to collect applications which fail the business logic. You might need these for reporting or if the processing is delayed or if the logic changes. ie send emails to young applicants offering an alternate.

Ewan
  • 70,664
  • 5
  • 76
  • 161