I'm using Repository pattern combined with Specification Pattern to interact with a service web (i prefer repository over DAO) : as this link suggests : http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/.
The user interface interact with controllers, controllers interact with services, services interact with repositories and specifications to do CRUD operations for service web, you can say this is the global architecture of the application, a layred architecture.
I'm confused alitte, the endpoint of web service accept values, but it doesn't accept negative numbers, and i'm declaring it as int
and there's not unsigned int
in Java, so now is it a good to check for the validity of values inside each specification before that specification make the request (because i already know that it will fail), or only inside services??!!! i think making each specification checks it values its better, because like that i oblige each service which uses this specification to deal with this checking, also like that i can escape from code duplication, if each specification deosn't make a check, and let the service do that for it, the check will be duplicated in each service, which seems to me, a bad for code reuse.
is it a good to place validating inside repository and if the test faillure will raise an exception, the service will not catch it, and let the controller catch it to notify the user about what he entred.
i'm alittle confused about SRP (Single Responsibility Principle), by doing this, does each specification conforms to SRP??!!!! (i always have a problems with SRP, i can't figure exactly what is the responsibilities of each class in the system).
This is an application for Android, and we have the intetion to put it also as web application (so, i want to do it in the right way, to maximize code reuse).
if i'm doing it in falsy way, if there'e another better way or anything, please let me now it :)
You can do validation anywhere you want, however, depending on where you put it the validation aquires a different role:
Controllers are user oriented. Therefore, they should validate user input and render some readable errors. Depending on the framework you are using this could be a task for separate Validators or Binders or whatever, but it's all closely related to Controllers.
In any case, any validation of user data should, in perfect world, be handled before controller forwards the request to the service. If you need to disallow entering of "-1" - it should be here. If person enters "abc" in text field - again here. And so on.
Services are domain oriented. They should validate if the task they are given is possible to complete with given data. However, if not, they should fail fast using some kind of assert call or throw a runtime exception. They should not provide a list of nice errors about why they failed (if only for audit purposes). Any data they are given should already be covered by previous entities (Controllers, Validators, etc.). The only thing services care about - if the operation they are asked for are allowed by business rules.
If a validation fails in service layer (exception is thrown) - that's a signal that you have missed some bit of validation in your controller.
Sometimes, service level validation does not match the validation in controller. Imagine a scenario in some project where regular user is only allowed to enter positive values, while administrator can enter negative ones too. Neither can ever enter "0" for some business logic reason. The validation "is value negative && can current user enter negatives" will reside in Controller. The validation "is value zero" will reside in Controller too. Service will only have "throw exception if value is zero" or just "assert value is not zero", as from it's perspective it can complete the request with both positives and negatives.
Repositories/specifications are data-source oriented. Therefore, these can add some assertions related to sending the request itself. If the data-source is known to not accept zeroes - this layer can prevalidate that and also throw an exception in case it's given a task to query a zero.
If a validation fails in repository layer (exception is thrown) - that's a signal that you have missed some bit of validation in your service or controller.
In other words:
So, whatever is your scenario, think of which constraints are true, and organize your validation appropriately.