A. Where can I place the validation?
Regardless of your design there are two places where validation code goes:
- Near input
- Near use
You put validation near input so that you can show the user the mistake quickly and get a correction timely. Also so that you understand the users context well.
You put validation near use to protect against the many wild and wonderful things that can change data since it was first validated.
In some designs these two places are the same place. That can be fine until the application grows.
Understand that validation is required only when the type system is not specific enough for your needs. If a method can use any int then then no validation beyond the type system is needed. If a method can use any non-negative int then you need validation if your language doesn't have unsigned int.
B. In which layer?And how(design) can I enrich the POCOs defined in CoreLayer with that validatons ?(I guess validation fits better in businesslayer since they represent business rules)
Not all validation is a business rule. Sometimes it's an application rule. For example if the business doesn't care if Car ID is negative but your application does, maybe because of the DB, then it's not the business that created this rule. That's OK. It's still important to validate. But it's not a business rule.
PresentationLayer
Contains all the WinForms to retrieve information=> generating POCOs and ideally I want to validate the user input. These POCOs are latter stored in DB
It looks like the presentation layer generates the Car. We could enforce the ID's are positive rule here simply by never creating a negative or zero ID. However, because Id
has a public setter anything that touches a Car
can mess with it. If you changed that to private, switched to using a constructor to set ID it would be immutable and we'd never have to check it again. If you did that you could put the validation in the Car class itself. It becomes part of the Car type. If you don't then you'll want to check this again before putting it in the DB.
The Name
could have a genuine business rule like "no swear words". This is likely user entered. You'd want to inform the user of the problem on the same screen they entered the swear word. Again you could switch to using using a constructor to set an immutable name and all objects of type Car
would have swear free names. Otherwise you'll want to be sure to check this again before using it to be sure something else hasn't messed with it.
The presentation layer will need to handle validation failures if only to recover from them. Likely by telling the user "that won't work because ___, try again". It may delegate validation logic to a type or a rule that lives elsewhere but here is where it gets fixed.
DataAccessLayer
Custom implementation of IRepositories. For example with SQLServer data access.
If one of the peculiarities of your SQLServer is that it doesn't like negative ID's this would be a good place to double check that you aren't about to send one. If the DB is well behaved and produces its own error nicely you might not even need to check here. If it locks up or takes forever to produce the error you might want to stop trouble here. Now sure, we checked this before but at this point do you know where your Car object has been?
C. Can you show me a design pattern/some design guidelines for including that validations?
My favorite coding style only allows constructors to do two things: set state and validate state. If the object is immutable that's the last time state needs validation. Do that and you can lean on the type system to ensure validation.
Otherwise, just assume things are dirty whether or not they come directly from the end user. Don't assume it's been checked before because the system should be flexible, it should allow change, you're making a rigid system if you only work correctly when you get your Car
objects from the presentation layer.
BusinessLayer:
Businnes logic
I want put the validation of the POCOs data here, but I am not sure if is the right place, or how to deal with it since they are defined in CoreLayer.
This is a good place for the logic to live. This doesn't necessarily represent when the checks should happen since where and when can be decoupled. That will depend on your design.
Validation is extremely important to get right. Miss it and the results can be catastrophic. Push it to far into the wrong places and the system turns into cement. Use it wisely and you'll be on your way to making a flexible system that gracefully handles whatever is thrown at it.