Architecture Problem

Posts   
 
    
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 17-Jul-2006 05:15:54   

Architecture Problem

I have spent most of the weekend reading LLBL documentation and running tests. I know you are all jealous. simple_smile

I have come to some conclusions. I am hoping I am wrong and some of these things can be resolved, so here it goes.

Is LLBL a Data Layer or a Business Layer or Both?

To use the full feature set, which is amazing btw, it seems you have to use this product as both the data layer and the business layer. If you want to be able to fully databind your objects that is. This is a problem with my current architecture for the following reasons.

Business Layer Architecture. BaseBusiness - >Object - > Person (Abstract) - > User -> UserSytem1 BaseBusiness - >Object - > Person (Abstract) - > Customer BaseBusiness - >Object - > Product BaseBusiness - >Object - > Product - > Merchandise BaseBusiness - >Object - > Product - > Service

Etc.

A) My Business Layer is constructed differently then my data layer. I have a base object class that all business objects use. This object has a tremendous amount of value when dealing with generics and adding core features to all my business classes. With LBLL I am no longer able to derive my business layer from this object. This is done for me with the Entitybase2 object. I figured I could partial class this object to add what I needed as a fix, but this class is embedded in the runtime dll and is unable to be partial classed. Is there any solution to this? I need to insert base object code into the classes, with having to figure out the template engine or code generator. Also this code would increase you compiled code unnecessarily.

B) Next major issue is classes inherited from the entities that were generated. This might solve the above issue if it worked the way I needed it too. For example, I have an [Object] table which makes ObjectEntity class. I need to make a new object that is inherited from ObjectEntity and call this one ApplicationEntity. The data being stored for this object is not any different from ObjectEntity, but the business layer class is very different. This worked great! Now the problem! Lets say I want to fill an EntityCollection of ApplicationEntity. This wont work! ApplicationEntity does not have a factory and wont work with ObjectFactory. Do you make a new factory? Is there a way to make an Entity from another entity that still works with EntityCollection. I realize there is an option for creating a class that inherits from ObjectEntity called MyObjectEntity, but that still won’t solve this problem. I would need to inherit from that one anyway.

C) Can I separated out and make a business layer that does not have application UI code and does not directly inherit from LLBL and still has the bind-ability that LLBL objects have. Currently we have an application that uses Datasets for the Data Layer, Custom Business Object for the Business Layer, and then the presentation layers. This works great except for one thing. DATASETS! I HATE THEM ? ok that was frustration from working all weekend.

1. Can I insert into this framework my one base classes that I can then add functionality to? Can I partial class anything else? Is there an alternative to this without learning how to use the code generator?

  1. Can I construct a Business Layer, separate from and not inherited from the data layer generated from LLBL and still have the features? Doesn’t look good, I want to use the validation framework and the super and subtype data constructs which are bindable to the presentation layer.

Anyway, I would love some advice help, an extra bullet, anything that can solve the above problems.

Bryan

simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 17-Jul-2006 10:14:07   

Bryan

I've been thinking along similar lines myself for the base class issue. I'm pretty sure there isn't a way of achieving this without modifying the templates but I think the change would be relatively trivial: - Modify the entitybase.template so that instead of "EntityBase" for non-subclassed entities it uses "BusinessEntityBase" or somesuch. - Create a new template for "BusinessEntityBase" that duplicates the constructors of "EntityBase" and just passes through the values. Make this class abstract and partial.

You can then add fixed code into this class and/or add more code to a partial class of the same name.

This should be effectively invisible to the rest of the generated entities and also the framework including factories etc.

I must stress that this is all of the top of my head and I haven't looked at it in any detail as yet, therefore Frans may be along at any moment to show me the error of my thinking!

Cheers Simon

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 17-Jul-2006 15:49:07   

BringerOD wrote:

Architecture Problem

I have spent most of the weekend reading LLBL documentation and running tests. I know you are all jealous. simple_smile

I have come to some conclusions. I am hoping I am wrong and some of these things can be resolved, so here it goes.

Is LLBL a Data Layer or a Business Layer or Both?

You can use the entities as business objects, you can also use the generated code as a pure datalayer, consumed by other BL classes. It's not pinned down to one specific architecture.

To use the full feature set, which is amazing btw, it seems you have to use this product as both the data layer and the business layer. If you want to be able to fully databind your objects that is. This is a problem with my current architecture for the following reasons.

Business Layer Architecture. BaseBusiness - >Object - > Person (Abstract) - > User -> UserSytem1 BaseBusiness - >Object - > Person (Abstract) - > Customer BaseBusiness - >Object - > Product BaseBusiness - >Object - > Product - > Merchandise BaseBusiness - >Object - > Product - > Service

Etc.

A) My Business Layer is constructed differently then my data layer. I have a base object class that all business objects use. This object has a tremendous amount of value when dealing with generics and adding core features to all my business classes. With LBLL I am no longer able to derive my business layer from this object. This is done for me with the Entitybase2 object. I figured I could partial class this object to add what I needed as a fix, but this class is embedded in the runtime dll and is unable to be partial classed. Is there any solution to this? I need to insert base object code into the classes, with having to figure out the template engine or code generator. Also this code would increase you compiled code unnecessarily.

The question is what kind of code do you want to add? If you want to do pure DDD (domain driven design) and store all 'Customer' oriented code into the CustomerEntity, you still can, add a partial class to the customer entity class and add the code there.

For validation code for example or concurrency testing, LLBLGen Pro uses validator classes, which you can plug-in at runtime. You can for example use a generic validator class which validates fields shared by a lot of entities, and derive your validators for the specific classes from that class and use these classes as validators for the entities. Most of the time, the amount of code you REALLY need to store inside the entity classes and which can't be covered by this is pretty small.

Keep in mind that for example code which targets multiple entities can still be placed inside a business component which deals with these entities.

In general it's not a good idea to destroy the whole architecture and rebuild it again with your own architecture in mind: it's more efficient to bend your own ideas to the framework and see what's left AFTER THAT which you have to solve with custom code. It's likely that that won't take a lot of code.

B) Next major issue is classes inherited from the entities that were generated. This might solve the above issue if it worked the way I needed it too. For example, I have an [Object] table which makes ObjectEntity class. I need to make a new object that is inherited from ObjectEntity and call this one ApplicationEntity. The data being stored for this object is not any different from ObjectEntity, but the business layer class is very different. This worked great! Now the problem! Lets say I want to fill an EntityCollection of ApplicationEntity. This wont work! ApplicationEntity does not have a factory and wont work with ObjectFactory. Do you make a new factory? Is there a way to make an Entity from another entity that still works with EntityCollection. I realize there is an option for creating a class that inherits from ObjectEntity called MyObjectEntity, but that still won’t solve this problem. I would need to inherit from that one anyway.

The main problem with inheritance when it comes to entities are hierarchies of object instances: customer contains Orderentities, which contain order detail entities etc.

When you create a subclass of Order, say MyOrder, you then have a problem in Customer: the customer.Orders collection has to contain MyOrder entities from then on, so you likely will create a subtype for customer as well.

Your problem can be solved by creating a factory which derives from ObjectEntityFactory and creates ApplicationEntity instances. The entity collection you want to fetch then gets that factory as its factory and at runtime instances of that type will be created. I used that trick here: http://weblogs.asp.net/fbouma/archive/2006/06/09/LLBLGen-Pro-v2.0-with-ASP.NET-2.0.aspx

C) Can I separated out and make a business layer that does not have application UI code and does not directly inherit from LLBL and still has the bind-ability that LLBL objects have.

Nope. Microsoft decided long ago that their least capable programmers have to be part of the team who cooks up and manages databinding code. (that was sarcasm, for the people who now feel offended) This thus means that if you want to do databinding aware code, you have to write some code INSIDE the object you want to bind. There's no separation in a controller, like in the MVC pattern. This is unfortunate, but it's reality.

You can use the projection facility of course and project entities onto datatables or custom classes and bind to that or transport them up to the GUI, however the road back is difficult, because what will happen with change tracking?

Currently we have an application that uses Datasets for the Data Layer, Custom Business Object for the Business Layer, and then the presentation layers. This works great except for one thing. DATASETS! I HATE THEM ? ok that was frustration from working all weekend.

1. Can I insert into this framework my one base classes that I can then add functionality to? Can I partial class anything else? Is there an alternative to this without learning how to use the code generator?

You have to use the base classes defined. That's a requirement for working with LLBLGen Pro, if you want to utilize the features of the framework. You can project entity data onto other classes, however you then lose change tracking.

You can add partial classes to the generated entity classes of course, but you then still work with the entity classes.

One thing which I would suggest is to look at adapter instead of selfservicing. With adapter, you don't have persistence logic in the entities, and therefore your gui code is forced to call BL components / BL tier classes for example.

Now, why would you go through all that trouble? In the end you will end up with a layer of business classes which likely derive from a central base class too and which will contain a lot of the code now stored in the entity base classes. So what will you gain? IMHO Not a lot.

The thing is that the 'freedom' to add custom code to the base class is not that great: what kind of code do you really need in there that's not in the entity base classes?

And if nothing else helps: every customer gets access to the runtime lib sourcecode, which is BSD2 licensed. This means that you can add a partial class to EntityBase2 for example and add code there which you compile directly into the ormsupportclasses.

  1. Can I construct a Business Layer, separate from and not inherited from the data layer generated from LLBL and still have the features? Doesn’t look good, I want to use the validation framework and the super and subtype data constructs which are bindable to the presentation layer.

Anyway, I would love some advice help, an extra bullet, anything that can solve the above problems.

Sure you can. This forum uses that architecture too. It just uses entity consumers as BL classes, not the entity classes themselves. So the gui works with entity classes (or typedlists) and works with the BL classes to get the data/save the data. The BL classes do validation and other code and fetch the data for the GUI or perform actions for the GUI.

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 17-Jul-2006 19:10:11   

The question is what kind of code do you want to add? If you want to do pure DDD (domain driven design) and store all 'Customer' oriented code into the CustomerEntity, you still can, add a partial class to the customer entity class and add the code there.

There is quite a bit that can be placed below many of the business objects.

BusinessBase Object That all objects relate from. It’s LLBL EntityBase 1) Custom security code. 2) Non LLBL validation code support. 3) Functions and methods each object needs to support for our own Generics.

We would even use abstract classes that are non data objects as well.

BusinessBase - >Object - > Person (Abstract) - > User -> UserSytem1 BusinessBase - >Object - > Person (Abstract) - > Customer

1) The person class could support the user and customer classes.

I can come up with more. Either way, I understand your point, but not all developers’ developer the same.

Maybe like Simon said, we could do this with the framework. Can we? Can you make it available to have our own partial class that is below all Business objects and above all the EntityBase(2) objects. This would make life a lot easier. We would be no longer forced to generate common code on the Entities, we could if possible code them into that object.

All that would need to happen is be able to insert some abstract classes in a few, user selected spots.

One class below all objects, and a non data abstract class user selectable below other object.

So what will you gain? IMHO Not a lot.

Beauty is in the eye of the beholder. But seriously, you sound like an incredible developer, but you can see how there are other needs that people have. So “not a lot” to you is different for me.

Nice to see I can extend the Factory class to add a class that is basically the same as the ObjectFactory. That will help. We have many objects that are the store the same data, but are actually different objects in the system. We are using some things from the domain model, but its not the domain model.

It just uses entity consumers as BL classes, not the entity classes themselves

I basically understand what you are saying with this statement, but is there a place that has more documentation on the consumer architecture. Maybe some examples using the LLBL code. Heck maybe a consumer and example from this forum.

Thanks for all your help. It is much appreciated.

Bryan

simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 18-Jul-2006 07:40:37   

BringerOD wrote:

The question is what kind of code do you want to add? If you want to do pure DDD (domain driven design) and store all 'Customer' oriented code into the CustomerEntity, you still can, add a partial class to the customer entity class and add the code there.

There is quite a bit that can be placed below many of the business objects.

BusinessBase Object That all objects relate from. It’s LLBL EntityBase 1) Custom security code. 2) Non LLBL validation code support. 3) Functions and methods each object needs to support for our own Generics.

I had a play with this last night, my first play with templates: I had a sample app from "LLBLGenPro: The Book" using SelfServicing two-class and managed to insert a custom business base class without modifying any of the SD-supplied templates and without making any mods to the project configuration (apart from moving the binding to the top of course). I ended up with two new template files (one a direct copy of the EntityBase original with its base class set to the name of the class in the other template file which was empty apart from two pass through constructors and the user-defined regions), a new template binding file and a new task file to generate a single output file in the BaseEntityClasses folder. The latter had to go in Tasks and the rest went in Additional Templates. (Incidentally Frans, any chance of an AdditionalTasks folder that is automatically searched in the same way as AdditionalTemplates?)

I wrote down some notes of what I did - let me know if you want me to post them here (I'll test it again first using sensible class names - ie without 'Simon' prefixed to my changes so that I could see what was happening!)

With regard to inserting abstract classes elsewhere in the chain- I don't think thats possible without support from the framework and Frans doesn't sound too keen. I also think there might be issues about potentially different primary keys and constructors etc.

Cheers Simon

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 18-Jul-2006 09:44:54   

simmotech wrote:

(Incidentally Frans, any chance of an AdditionalTasks folder that is automatically searched in the same way as AdditionalTemplates?)

See project properties wink

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 18-Jul-2006 10:55:31   

BringerOD wrote:

The question is what kind of code do you want to add? If you want to do pure DDD (domain driven design) and store all 'Customer' oriented code into the CustomerEntity, you still can, add a partial class to the customer entity class and add the code there.

There is quite a bit that can be placed below many of the business objects.

BusinessBase Object That all objects relate from. It’s LLBL EntityBase 1) Custom security code.

could you give an example?

2) Non LLBL validation code support.

You can add that to the validation logic in your validator as well. And as this has to be generic code (otherwise why put it in the general base class) the validation has to be generic by nature, so could be well placed in the validator classes, which operate on an entity, so you can do whatever you want in there.

3) Functions and methods each object needs to support for our own Generics.

Could you give an example?

We would even use abstract classes that are non data objects as well.

BusinessBase - >Object - > Person (Abstract) - > User -> UserSytem1 BusinessBase - >Object - > Person (Abstract) - > Customer

1) The person class could support the user and customer classes.

true, but you don't need inheritance for that per se to support that. As I said: inheritance is great for polymorphism etc. but it also creates hierarchies which can be cumbersome to convert (co-variance) to a different type hierarchy

I can come up with more. Either way, I understand your point, but not all developers’ developer the same.

true. Though every given architecture has its limits and benefits. Choosing a POCO based architecture means you have freedom but it also comes at a high price: you have to do a lot yourself too, as there's no multiple-implementation inheritance in .NET.

I wont argue that POCO sucks, because it doesn't, however I also don't see why NOT using POCO would be bad, because it also has severe advantages, namely in productivity. The disadvantage, that you have to live with the central base class, is a given by nature in .NET anyway and in the end of a POCO project, the central base classes won't be that much different from what you get in the entity base classes anyway.

Maybe like Simon said, we could do this with the framework. Can we? Can you make it available to have our own partial class that is below all Business objects and above all the EntityBase(2) objects. This would make life a lot easier. We would be no longer forced to generate common code on the Entities, we could if possible code them into that object.

If you really want to, you can. You can first of all decide to add a partial class to the runtime libs, as the sourcecode is at your disposal (customers only). then compile the runtime libs yourself and you're set.

You can also use a template change, where you add a small template which is your real base class to the templates, a task to generate the class and you alter the entity template's header a bit so it will choose that class as the base class instead of EntityBase(2). Some constructors have to be present of course but that's it.

It's not a big deal per se, however in the end you will likely not need it that much.

All that would need to happen is be able to insert some abstract classes in a few, user selected spots.

One class below all objects, and a non data abstract class user selectable below other object.

It's template based code generation, so you can make the changes you want. The real question is, do you want to go through THAT trouble and bend the framework to the way you think it is better or do you want to spend that time in using the framework's extensibility features instead and bend your way how it should be to the framework? Trust me, it's not worth the effort. I only would suggest to proceed with this if you have a GUI framework which has to use a new BL / DAL tier combination and which must not be changed, which results in the fact that you need to use the same classes as before, however it then begs the question if that's the real way to go.

So what will you gain? IMHO Not a lot.

Beauty is in the eye of the beholder. But seriously, you sound like an incredible developer, but you can see how there are other needs that people have. So “not a lot” to you is different for me.

The discussion is largely academic. In the past 3-4 years no-one has come up with an example where POCO would do the job and the central base class approach would be impossible. It in general boils down to taste, something which I find hard to argue with wink

It just uses entity consumers as BL classes, not the entity classes themselves

I basically understand what you are saying with this statement, but is there a place that has more documentation on the consumer architecture. Maybe some examples using the LLBL code. Heck maybe a consumer and example from this forum.

It's pretty straight forward. GUI has no clue where the data comes from or goes to. Gui calls BL class' method to get data for a given operation. BL class knows where to get the data from, e.g. 2 sources or 3, makes the data ready for the GUI and returns it. Similar the other way around: Gui collects actions in UoW, e.g. multiple screens of actions, have to be committed in 1 go. Gui calls BL method to commit it. BL method checks which database the user is connected to (for example), like oracle or sqlserver, asks a factory to get a DataAccessAdapter instance and commits the uow on that db.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 18-Jul-2006 22:32:56   

I'm toying with the idea of creating a small extra template and 2 different entity templates which derive from a common base class instead of directly from entitybase(2). Together with own templatebindings file and a couple of presets, it should be easy to deploy and could help some people out.

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 19-Jul-2006 00:14:20   

Otis wrote:

I'm toying with the idea of creating a small extra template and 2 different entity templates which derive from a common base class instead of directly from entitybase(2). Together with own templatebindings file and a couple of presets, it should be easy to deploy and could help some people out.

simple_smile That sounds great!

simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 19-Jul-2006 21:24:10   

Otis wrote:

I'm toying with the idea of creating a small extra template and 2 different entity templates which derive from a common base class instead of directly from entitybase(2). Together with own templatebindings file and a couple of presets, it should be easy to deploy and could help some people out.

Frans

I always knew you put a great deal of time and effort into LLBLGen Pro but my respect for the work you do has gone through the roof after my attempting to duplicate the relatively trivial addition discussed in this thread.

I managed it for one (twoclass self servicing, c#, 2005) and thought I would do the same for some of the other combinations but I've gone absolutely cross-eyed writing lists of templates/schemes/bindings/languages/tasks etc. frowning I'm afraid my brain isn't up to the parallel processing required to maintain code for all the platforms you do.

I can't see an upload button but I'll email a zip of what I did manage, which may (or may not!) give you a start on this. I am another who would be grateful for this additional feature.

Cheers Simon

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 19-Jul-2006 22:27:43   

Thanks Simon! smile

I received your email, but the attachment didn't arrive (perhaps stripped off at your side, or you didn't attach it by accident). Could you retry?

Frans Bouma | Lead developer LLBLGen Pro