First of all, i'm not talking about validation in the sense of the nullability or length of a field like in this and this questions where we can use isValid() methods in business classes or an external Validator. However, my question is related to validate or not in business classes. I'm using a layered architecture style with services consuming the datasource layer and interacting with the domain model.
Simplyfing the domain requirements, suppose I have Movies and Reviews, and Users can make only one Review per Movie. So, a second Review is a valid object but the business rules should not allow the review to be completed.
So, i could do:
ReviewService >> addReview(review,movie) loggedUser = getLoggedUser() review = reviewRepository.searchReviewFrom(loggedUser,movie) if (review == null) reviewRepository.save(review) else // some mechanism to inform the error, it could be NotificationPattern
Movie >> addReview(review) for r in this.reviews if r.user = review.user throw ReviewAlreadyUploaded // if no expcetion is thrown this.reviews.add(review)
I think this oneReviewPerUser validation is a pure business rule, and should go in the business classes, in this case the Movie class. Thus the business rules are contained whitin the domain and no scattered between the layers. However, if the lists of Reviews of the Movies are big in almost every case, this option implies query and instantiate a big number of Review object and iterate over all elements.
So assume that I choose option 1, I have to assure that every client that wants to create a review for a Movie must use the Service, because it may break the business constraint of 1 review per user if, for example, use directly the ReviewRepository. This starts to sound like a layer of Services with all the business logic and an AnemicModel with Domain Classes being bags of attributes for carry data to and from the database.
Where is the line that separates the business logic that should be on Services from the one that should be on Domain Classes.