Validation and Business Logic

Posts   
 
    
GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 27-Feb-2007 17:01:34   

Hello,

I have a question regarding separation of business logic and the db generic.

I have created a vb manager template based on the c# one that is floating around, and I finally have time to update it to 2.0.

In my 1.X version every time an Entity, or EntityCollection instance was created i would set the EntityValidatorToUse, additionally in saves and update i would make sure that the validator was set. This wasn't ideal, but it worked. The biggest problem is recursive saves, and making sure the entire tree has the validator set.

So in 2.0 i am happy to see that the validation is combined into 1 class. Also I am happy to see the Overridable CreateValidator in the Entity, which will ensure that i have the validator set every time. (I'm happy about a lot of 2.0 stuff, I could go on all day, thanks Frans.)

So here is my problem I think that validation is business logic and should be in my manager project, with the other business logic. The extreme case for this argument is when during validation on an entity you need to look up something in the db, possibly other entities in order to determine if the entity being validated is valid. For example when validating orderdetail you need to confirm the price that was specified, or some other business logic stored in the db.

Please let me know if anyone feels i am out of line here, maybe validation shouldn't go this far. Maybe the db look up validation stuff should be in my manager save, but what about recursive saves, where the save is performed implicitly w/o using my manager save, I think that is the elegance of the built in validator.

Ok, no problem just inherit from ValidatorBase and put classes in the business/manager layer. I agree, however generic doesn't have a reference to business. so i can't just say in CreateValidator use Business.SomeValidator, I have to do something like create a global/application dll that can act as the middleman so generic doesn't need to see business.

I'm sure others have come up with good solutions for validation, let me know if you have questions or ideas. I appreciate any input.

Thanks,

Gabe

jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 27-Feb-2007 18:23:33   

why not move the validation logic in your manger objects into the validation objects? this way all of your logic is in one place. You can still make all your db validation calls from the validation object.

If your validation are class/objects within the manger, just move the reference to the db generic project and call them within the validator functions.

I guess this all depends on your definations of the db generic objects though. I tend to think of db generic as business objects since I use the adapter model. Maybe in a SS configuration they are more like high level crud objects.

GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 27-Feb-2007 22:21:05   

Jason,

Thanks for the reply, I really appreciate your help, here is a little background of my project for clarification

I am using the out of box adapter model (dbspecific, dbgeneric), and i add a business layer which contains my manager classes(business). I will use the items in parens to refer to projects. business reference dbspecific and dbgeneric, and the ui would reference dbgeneric and business.

why not move the validation logic in your manger objects into the validation objects?

To try and understand what you are saying are you assuming there are validation objects in dbgeneric or in business

If your validation are class/objects within the manger, just move the reference to the db generic project and call them within the validator functions.

Are you suggesting moving my validation classes into the dbgeneric project?

I guess this all depends on your definations of the db generic objects though. I tend to think of db generic as business objects since I use the adapter model. Maybe in a SS configuration they are more like high level crud objects.

I guess we have a different view here, if i understand what you are saying, I always thought the opposite. If you are doing self service model, i think it makes sense to put business logic with the entities because they are data aware.

With the adapter model I don't want dbgeneric to have any knowledge of the database, they are for the most part containers for data, I don't want someone with access to a container class to be able to save or update, unless they use manager classes. I want my business layer to make all of the business decisions, and i think this includes validation.

I'm just not sure, I have some thoughts that the core field level validation should be performed in the dbgeneric, like when you set a string longer than the length of the field. But I can't see putting in rules to validate an entity where large amounts of business logic or trips to the db are necessary. Maybe I am thinking too much in theory and not enough in the real world.

Let me know.

Thanks, Gabe

jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 27-Feb-2007 22:47:29   

GabNodland wrote:

To try and understand what you are saying are you assuming there are validation objects in dbgeneric or in business

you can overload the Validation functions within the entity, or you can overload createvalidator and define your validation within the validation object. I opt for the later to seperate my validation from my data container.

GabNodland wrote:

Are you suggesting moving my validation classes into the dbgeneric project?

yes, see previous comment for implementation options.

One thought is to define the validation in a seperate object ([MyEntity]Validator). In your manager class you could assign the validator to the entity.

//within manager function
myEntity.Validator = new MyEntityValidator();
try
{
     using(dataaccessadapter adapter = new dataaccessadapter())
     {
           adapter.saveentity(myEntity);
     }
}
catch (ORMEntityException ormEx)
{
      //handle
}

then your manager would preform work (save, delete, load). and the entity would fire the appropiate validation method.

in this model, technically, the validation is outside the entity and the entity doesn't even define the validation, it only calls the validator object before preforming work (or afterloading if that event is defined). all you need to do is activate the 'generate validators' task in the OR Mapper. then use partial classes/user defined regions to code your logic

GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 28-Feb-2007 05:29:29   

Jason,

I think we are in tune here, the biggest problem I am dealing with is how to make sure that the validator is set before saves, which can be tricky, with large recursive saves.

Thanks a lot for your ideas.

Gabe

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 28-Feb-2007 07:48:13   

The following is copied from the manual:

Validation logic inside validator classes It can be that you don't want to add validation logic to the generated classes but want to store this validation logic in a separate class, a validator class and of which you can plug an instance of into an entity object. LLBLGen Pro supports this through validator classes. Validator classes are derived from the base class ValidatorBase, which implements the interface IValidator. Please consult the LLBLGen Pro reference manual for details about this base class and the interface.

... // some omitted lines

Entity classes don't get a validator instance by default, even if you generate them through LLBLGen Pro. To automate the creation of an entity's validator object when you instantiate an entity, you should override the method CreateValidator in the entity class, either through a partial class, include template or by adding code to the custom code user code region of the generated entity classes.

GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 28-Feb-2007 15:58:02   

Walaa,

Thanks for the reply.

I am not disputing that this is the best way to do it. It is mainly the logistics of how to do this. The manager classes are in a separate project that the dbgeneric has no reference to. So it is a little tricky.

I think i either have to create a global middleman dll, like described in my first post, or set the validators recursively each time i do a save.

I was just hoping for something more elegant, oh well I will figure something out.

Thanks,

Gabe

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 28-Feb-2007 16:44:31   

Validator classes are a way to perform IoC programming: the validation and the object validated are decoupled as the implementation is separated.

To automatically create validator objects, you could override CreateValidator() in a partial class.

In v2.1 we'll introduce a dependency injection framework which takes care of this automatically, so you then just write validator classes, store them in a separate assembly if you want and through 3 different configuration mechanisms (attributes, config file or scope declarations in code simple_smile ) they're injected at runtime into the entities specified.

Frans Bouma | Lead developer LLBLGen Pro
GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 01-Mar-2007 07:53:45   

Frans,

This sounds good. When will I be able to get my hands on the LLBLDIF (2.1 beta).

Dependency injection, isn't a pattern i knew the name of, but I like it and think I have done something similar. Do you have more information about how it will work in LLBLGen?

If I am thinking about this correctly, I could just use a reflection/createinstance and maybe a configfile within the CreateValidator(). Maybe call a validator factory via reflection, or use reflection to look through my businesslayer to find the validator, or attributes. Ok this is the more elegant solution i was looking for.

This is the answer to my first post use DI. Frans, you are always 1 step ahead, you must follow java or something. wink

Thanks,

Gabe

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 01-Mar-2007 10:02:36   

GabeNodland wrote:

Frans,

This sounds good. When will I be able to get my hands on the LLBLDIF (2.1 beta).

Somewhere in april 2007

Dependency injection, isn't a pattern i knew the name of, but I like it and think I have done something similar. Do you have more information about how it will work in LLBLGen?

I'll have more info soon in the features discussion forum simple_smile Basicly it comes down to: - you annotate a class to inject with an attribute which defines in which type(s) instances of that annotated class have to be injected in OR - you define injections in config files which can be embedded as resource OR - you define injections in a scope, which is then used like: using(DependencyInjectionScope scope = new DependencyInjectionScope()) { // your code which will use the scope's DI info }

If I am thinking about this correctly, I could just use a reflection/createinstance and maybe a configfile within the CreateValidator(). Maybe call a validator factory via reflection, or use reflection to look through my businesslayer to find the validator, or attributes. Ok this is the more elegant solution i was looking for.

This is the answer to my first post use DI. Frans, you are always 1 step ahead, you must follow java or something. wink

haha simple_smile Yes I do follow java actually, though DI isn't a java pattern per se, it's more of a way to decouple concerns. What people are after really is decoupling of code so they can maintain it better.

Frans Bouma | Lead developer LLBLGen Pro