2

We are having a heated discussion about this at work: For sake of simplicity, I will use examples in the question.

Assume there is an application with an account request form, for which we have these requirements:

  1. Dates and Email must match a regex
  2. If the user already has an account request, he should not request for another

The problem is: where to verify the second requirement?

  1. If we check on the controller, we would have to access the database from there and it is a business logic, so it doesn't seem right.

  2. If we validate on the business layer, we would have to somehow return the validation information in case of a failed validation. Doing this would require either:

    • Each business method to have an "out" parameter;
    • We to encapsulate our return object into a "response" object with the validation information
    • The use of exceptions in case of failed validations (which, to me, falls in the anti-pattern of using exceptions for programm flow).

How should we design this?

  • How do you deal with the situation that, after starting to process a request, you encounter a problem that makes it impossible to fulfill the request? – Bart van Ingen Schenau Jan 20 '15 at 13:47
  • 1
    What is wrong with accessing the database? – JeffO Jan 20 '15 at 15:41
  • @BartvanIngenSchenau in these cases we throw an Exception, but usually this is a exceptional scenario, so the exception is (as far as I know) correctly used. – JSBach Jan 20 '15 at 16:46
  • @JeffO please correct me if I am wrong, but in a layered architecture, the presentation layer should not access the data layer directly, it should go through the service layer. In this case specially, the business knowledge ("If the user already has an account request, he should not request for another") would be in the controller, instead of the business layer, this is not recommended. – JSBach Jan 20 '15 at 16:48
  • This logic would be in your business layer (which will need to check the database). – JeffO Jan 22 '15 at 1:57
2

Go for the second solution. Your AccountRequestValidator uses the db information and some rules to determine of the request is valid or not. Then use a "response" object, but don't create one yourself if you use a language that has already implemented that for you like Scala or Haskell. This type is usually called Either. It should throw an Exception if it is not able to check if the validation is valid, for whatever reasons there might be.

Your code would therefore look similar to:

AccountRequestValidator validator = new AccountRequestValidator(db)
AccountRequest request = //...
try {
    Either<RequestAllowed, RequestForbidden> validationResult = validator.validate(request )
    //Do sth. with validationResult
}
catch (Exception e) {
    //Was unable to check if the request is valid...
}

If you use Java, consider using Googles Functional Java. It has its own Either type defined.

  • Just let me know if I understood: you are telling me to use something like the Validator class from sprint (docs.spring.io/spring-framework/docs/2.5.x/api/org/…) and use it to check in the business layer, correct? But if the validation fails, how do I give this feedback to the caller so a message can be shown to the user? – JSBach Jan 20 '15 at 16:54
  • 1
    Not really the one from Spring, just your own custom validator. As it is concerning the business logic it is part of the business layer but is called from the controller (as shown in my code example). And you can just use the validationResult so that the controller can create a meaningfull message to the user if the result is RequestForbidden rather then RequestAllowed. – valenterry Jan 20 '15 at 17:16
  • That is interesting and seems a very nice idea. Would you have an answer to the argument that there is still a business knowledge when the controller knows that he has to call that specific validator in order to call the "save" method after that? – JSBach Jan 20 '15 at 19:29
2

Validating for format validity on single fields, should happen as close to the point of entry into your code as possible. In this case it should be as close to the UI as possible. One reason for this is that this allows you to assume proper values from that point on. Another is that this allows you to check before actually processing anything which brings functional benefits as well.

Validating stuff like, is this account already created is a whole different thing altogether and should reside in the business logic. To elaborate on your concerns here. Never ever use exceptions for logic! Exceptions are for exactly that, exceptions. Something unexpected went wrong so an exception occurs. I personally am no fan of out parameters as well and would go for the response object. Also I would encourage you not to extrapolate functionality like this in a separate set of objects, where you can tailor your classes to closely mimic your functional needs instead of your data model.

HTH.

  • Yes, this is currently our problem. As you said these validations shuold reside in the business logic, but we should neither use exceptions nor out parameters nor an extra object. How shoul I perform the communication from business to view about which validation failed and why? – JSBach Jan 20 '15 at 16:45
  • What I'm saying is that you should use a Model that represents your data in a way you display it (and usually can closely resemble your datamodel) and you should have another model that you use for operations. In this case an operation that creates an account and returns, as a result the validation messages involved. From your controller, you can then call the create account operation and if validation is ok, retrieve the new account through your model. – Jonathan van de Veen Jan 22 '15 at 11:09
  • So I would have a method public OperationModel createAccount() and this class OperationModel would have an attribute validationMessage, right? If I do that, for every model that is used in a method that contains has some sort of validation, I will have to take an approach like this, so operation models would end up with validation information and then in the controller I would have to check for something like an isValid property and errorMessage property. That seems interesting, but I have mixed feelings about have this isValid in a Domain Class, but as more as I write, the better it sounds – JSBach Jan 22 '15 at 14:23
  • Actually you would not need isValid in a domain class. You would have a struct or a class describing an operation result which whould have isValid and errorMessage properties. This would be returned from the operation, instead of a domain class. Reading data is still done by the model that represents your data. – Jonathan van de Veen Jan 27 '15 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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