conceptual help and "best practices"

Posts   
 
    
jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 02-Mar-2007 17:37:10   

in theory I somewhat understand seperation of duties, decoupling objects, MVP pattern and stuff like that. (thanks to the LLBL architecture, Ent Lib 2.0 & David Hayden.) So the best way to apply theory is to put it into a real life scenario.

I use the 1 class, adatper, 2.0, sql server model with entity specific validator objects. currently my projects are intranet based web applications.

I use the LLBLDataSource2 objects and do most of my business logic within the code behind file. The more I learn about agile programming, maintainability and unit testing the more I could benifit from moving these logical opertation into a seperate class/assembly/project (much like DBGeneric and DBSpecific LLBL projects).

This would also assit me if I ever venture into desktop apps, or need a quick console/nUnit app to test logic. MS WCSF looks promising, but I dont' fully understand all the implications with .Net 3.0 upgrade. It appears WCSF is still in beta as well.

Now for my real life example: I have a commission rate table. A rate can be active for a period of time. When a new rate is activated the previous rate is deactivated. If the current rate's active date is edited the previous commission rate's deactive date is adjusted to prevent overlap. (I guess this could be considered row versioning. I saw a thread in v2.1 about row versioning).

so within my LLBLDataSource2 object I check if the active date changed. If so I: 1. determine if a previous rate exists 2. update the deactive date if the previous rate exists 3. then update the current rate, what the user orginally set out to accomplish

All this works, but if I want to preform this logic on another screen, or in another type of appication I would have to re-create all the logic.

What are the pros/cons of 1. Creating a BLL (I guess manager objects?) which I could pass arguments too and get my results. 2. Extending the DataAccessAdapter to handle this business logic. 3. Overriding events like SaveEntity, DeleteEntity, UpdateEntity in the existing DataAccessAdapter to handle the logic.

I realize there's no right answer but here are my thoughts so far. Option 1: Seperate BLL * Pros * I have a clear distinction between PAL, BLL, and DAL. * logic is transferable to other PALs * logic is distributed to seperate classes/functions with a specific purpose * Cons * large amount of manual coding on my part * need to determine if I transfer entities or DTO's modeled on entities * depending on the complexity of the BLL my PAL may need to be aware of the ORMSupport assembiels, thus still having access to the DataAccessAdapter objectOption 2: Extending the DataAccessAdapter

  • Pros
  • logic is transferable to other PALs
  • moderate manual coding
  • Cons
  • muddies the distinction between BLL and DAL
  • or redefines what physical objects represent the BLL and DAL. now the DataAccessAdapter represents the BLL and the LLBL.DQE is the DAL.
  • would want to mark the DataAccessAdapter as abstract, so you couldn't bypass the extended classes
  • all the logic would be contained within one object -or- the logic would be broken out into seperate extended adapters. In the later I would need to somehow restrict/control as to which adapters are used for different types of logicOption 3: Ovrride functions in exsting DataAccessAdapter

  • Pros

  • logic is transferable to other PALs
  • minimal manual coding envolved to extend the DataAccessAdapter
  • Cons
  • muddies the distinction between BLL and DAL
  • or redefines what physical objects represent the BLL and DAL. now the DataAccessAdapter represents the BLL and the LLBL.DQE is the DAL.
  • all the logic would be contained within one object. could become difficult to manage all the logic. To overcome this I could create classes for specific logical functions and depending on the perstiance action and the entity type I could pass the work along accordingly. (switch statements or factories)ultimately I know this comes down to what are my requirements and how do I use the data. I would like to use the entity objects in the PAL. I think DTO's would be overkill, but then again for consistancy I could project entities, typedlists and views into DTO's which would always standardize the interface. Then i have to find a way to bubble up validation errors. I don't quite understand bubbling of events. or at least i don't think i do.

if I use the entities in my PAL then i would need to expose the ORMSupport classes. theorically this is a "bad" thing as now the PAL is dependent on the DAL.

It wouldn't be an issue to re-define my understanding of the dbGeneric and dbSpecific projects to repersent the BLL and have the DQE represent the DAL.

now that all of this has been said... what are your thoughts?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 04-Mar-2007 20:45:37   

Hi Jason. I feel your pain. Here are my thoughts about your post:

I want focus on your 1st solution as for me is the best in this case.

  1. Creating a BLL (I guess manager objects?) which I could pass arguments too and get my results.

I think it's a general good solution, (always depends upon your project requests). This way you can reuse your logic in every PAL (ASP, WinForms, ConsoleApp, WS, etc.) you create. Now you are using a LLBLDataSource and you wish to move your logic to a BLLayer and still using the benefits of this control. I think it's possible thanks to the "LivePersistance = false" of LLBLDataSource and the Unit of Work (UoW). I found a good thread about that: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=6975&HighLight=1

At your MVC thinking, the Controller must be in charge of manage the PAL requests and accommodate those to call your BL methods.

Cons

* large amount of manual coding on my part
* need to determine if I transfer entities or DTO's modeled on entities
* depending on the complexity of the BLL my PAL may need to be aware of the ORMSupport assembiels, thus still having access to the DataAccessAdapter object

Large amount of manual coding: I think you need write logic code in any scenario, so in this case you write only once. Its a Pro (no Cons)!

Need to determine if you transfer Entity or DTO. Well, thats a Architecture decision. Though referencing ORMSupport assemblies doesn't mean to referencing DataAccessAdapter (Adapter TemplateSet case) I think (in this case) your PAL should depends upon: 1. your Manager Domain Classes (like OrdersManager): It is a Service Deliver. 2. Your Entity Structure (Database Generic. f.e.: OrderEntity): This provide a "standard" (scope dependent) way to share the structure. 3. ORMSupport classes: needed for sorting, filtering, etc. 4. Other GUI related classes...

So, your BLL (Manager Domain Classes) depends upon 2, 3, and DAL (Database Specific) for Data Access actions.

Then

if I use the entities in my PAL then i would need to expose the ORMSupport classes. theorically this is a "bad" thing as now the PAL is dependent on the DAL.

Not really. PAL is dependent on the DAL via BLL, but not directly.

What about this article http://davidhayden.com/blog/dave/archive/2005/06/15/1482.aspx (David Hayden)

David Elizondo | LLBLGen Support Team
jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 05-Mar-2007 01:43:37   

daelmo wrote:

At your MVC thinking, the Controller must be in charge of manage the PAL requests and accommodate those to call your BL methods.

so the controler would only wire up PAL to BLL? it wouldn't contain the business logic? I guess this would make sense as I want the bll to be moble across PAL's. but then again the controlers are decoupled, so the control could be passed to a different PAL too. utlimately this determines how complicated I want the project to be.

daelmo wrote:

I think (in this case) your PAL should depends upon: 1. your Manager Domain Classes (like OrdersManager): It is a Service Deliver. 2. Your Entity Structure (Database Generic. f.e.: OrderEntity): This provide a "standard" (scope dependent) way to share the structure. 3. ORMSupport classes: needed for sorting, filtering, etc. 4. Other GUI related classes...

good point, DataAccessAdapter would never be present in the PAL since [namespace].DatabaseSpecific would never be present in the PAL. For that matter the PAL project wouldn't reference the DBSpecific project, only the DBGeneric and ORMSupport assemblies.

thank you for your insight.