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?
@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.)
- 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.
- 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.