- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
Business Objects
Joined: 17-Apr-2006
I currently use a .NET application framework that provides a business object based on an ADO.Net table. It works but is restricted by it's "table behind" approach. One business object maps directly to one table and cannot contain other business objects. I like the idea of having objects containing collections of other objects in a true object based approach, rather than a hybrid table based setup.
I cannot quite understand whether LLBL Gen Pro actually creates a "business object" containing collections of other related business objects or whether this isn't an accurate understanding of what is offered.
With my current framework, rules can be coded into the business object's class and there is UI interaction when the BOs are dropped onto framework Winforms.
How does a developer generally integrate LLBL Gen Pro with the UI. Is an additional framework required? I have a new project coming up and I would really like to use a true ORM tool like LLBL Gen Pro.
Sorry to be so "general" but at this stage, I am trying to get an overview at 10,000 feet
Thanks.
Joined: 07-Oct-2005
LLBL creates entities that can contain collections of other entities in your project.
The great thing about it is that the designer lets you create your custom relationships and not be restricted to the design of the database.
I'm a fan of the manager method, where I have a CustomerManager that handles all my business logic and the CustomerEntity is just passed from the BL to the UI for manipulation. When it's time to save, I do CustomerManager.Save(CustomerEntity) and it takes care of all the business logic that way instead of writing the code directly into the CustomerEntity.
I purchased LLBLGen last year and I haven't regretted it one single bit. I'm going to purchase v2.0 next week. Not because we need it, but because I've gotten much more out of it than what we purchased v1.0 for.
You might find a product that seems comparable to LLBLGen, but what you won't get any place else is the wealth of information and support that these forums and the staff offer.
You can have roughly 3 different types of BL rules: 1) field oriented, e.g. Customer.ID > 0 2) multi-field, single entity oriented, e.g. Order.OrderDate <= Order.ShippingDate 3) multi-entity oriented, e.g. a customer is a gold customer if he has purchased more than x orders in the last n months.
Most of the time, 1 and 2 can be done by validation classes, like the ones you can use with llblgen pro and which llblgen pro can generate for you (to which you then add code)
option 3 is often implemented outside entity classes, in stateless manager classes which accept the entities to process and work on them inside a method, eventually calling other managers to do work for them.
Others might say that option 3 is also implementable inside entity classes, and prefer the Domain model. You can do that as well in llblgen pro, simply use partial classes.
Joined: 30-Jun-2005
Gazley wrote:
I currently use a .NET application framework that provides a business object based on an ADO.Net table. It works but is restricted by it's "table behind" approach. One business object maps directly to one table and cannot contain other business objects. I like the idea of having objects containing collections of other objects in a true object based approach, rather than a hybrid table based setup.
I cannot quite understand whether LLBL Gen Pro actually creates a "business object" containing collections of other related business objects or whether this isn't an accurate understanding of what is offered.
With my current framework, rules can be coded into the business object's class and there is UI interaction when the BOs are dropped onto framework Winforms.
How does a developer generally integrate LLBL Gen Pro with the UI. Is an additional framework required? I have a new project coming up and I would really like to use a true ORM tool like LLBL Gen Pro.
Sorry to be so "general" but at this stage, I am trying to get an overview at 10,000 feet
![]()
Thanks.
LLBLGEN generates "Entity" classes for you which you can use directly in your UI (they have lots of databinding functionality), or you can encapsulate the Entity classes in your own custom business objects which may be more useful than tying your UI binding scenarios to your database design, which is what the Entity classes end up representing (one entity class per table, generally).
In our application, we made the decision to couple the UI design with the database design, making Entity classes our UI-bound business objects. Business rules were put directly into the entity classes when it made sense to do so, and in Manager classes (as mentioned by a previous poster) when the scope of the business rule extended beyond the data available to the entity (not directly related data). This is a bit of a strange design, but it seems to have worked out so far!
Joined: 17-Apr-2006
option 3 is often implemented outside entity classes, in stateless manager classes which accept the entities to process and work on them inside a method, eventually calling other managers to do work for them.
Are the "stateless manager classes" generated by LLBL or are they some kind of pattern or just a simple generic term for a class that manages?
Thanks
Joined: 30-Jun-2005
Gazley wrote:
option 3 is often implemented outside entity classes, in stateless manager classes which accept the entities to process and work on them inside a method, eventually calling other managers to do work for them.
Are the "stateless manager classes" generated by LLBL or are they some kind of pattern or just a simple generic term for a class that manages?
Thanks
I think what he's referring to are the manager templates for LLBLGEN, which generate a "domain manager" for each entity. These classes provide CRUD operations for their specific entity type. For example, a CustomerEntity would get a CustomerManager class so you could do:
Dim cust as CustomerEntity
cust = CustomerManager.Fetch("xxxx")
cust.Name = "Bob"
CustomerManager.Save(cust)
I think these are also known as repositories in the domain modelling jargon.
We also use the entity manager approach, however, we do not use stateless managers. We have a base class 'ControllerBase', who contains a great deal of generic functionality and other goodies for our controllers to derive from. For example, We also have an internal constructor who takes in an existing data access adapter object in order to have a transaction span controllers. Another abstraction we use is an IExceptionTranslator object who's responsiblity is to translate database exceptions to our business exceptions.
Me personally, I would recommend designing your business controllers as true objects (not stateless) in order to take full advantage of all the object-oriented features.
Joined: 30-Jun-2005
MarcoP wrote:
We also use the entity manager approach, however, we do not use stateless managers. We have a base class 'ControllerBase', who contains a great deal of generic functionality and other goodies for our controllers to derive from. For example, We also have an internal constructor who takes in an existing data access adapter object in order to have a transaction span controllers. Another abstraction we use is an IExceptionTranslator object who's responsiblity is to translate database exceptions to our business exceptions.
Me personally, I would recommend designing your business controllers as true objects (not stateless) in order to take full advantage of all the object-oriented features.
Are these controllers in the sense of Model-View-Controller?
We use stateless managers that derive from an EntityManagerBase class. They are stateless because they are supposed to just provide services, which shouldn't need state.
mikeg22 wrote:
MarcoP wrote:
We also use the entity manager approach, however, we do not use stateless managers. We have a base class 'ControllerBase', who contains a great deal of generic functionality and other goodies for our controllers to derive from. For example, We also have an internal constructor who takes in an existing data access adapter object in order to have a transaction span controllers. Another abstraction we use is an IExceptionTranslator object who's responsiblity is to translate database exceptions to our business exceptions.
Me personally, I would recommend designing your business controllers as true objects (not stateless) in order to take full advantage of all the object-oriented features.
Are these controllers in the sense of Model-View-Controller?
We use stateless managers that derive from an EntityManagerBase class. They are stateless because they are supposed to just provide services, which shouldn't need state.
No, they are just your typical business components (we do however use the M-V-P, where we have service contracts that wrap our business controllers). For the most part, our controllers are stateless, except we keep around the data access adapter for the life of the controller (we use our own data access factory object to create our adapters via reflection).
I just don't like exposing my behavior via static (shared) methods. Here is where you lose most of the OO benefits.
MarcoP wrote:
I just don't like exposing my behavior via static (shared) methods. Here is where you lose most of the OO benefits.
Thats a valid point for using satefull manager classes but the issue myself and other BL developers face with this type of implementation is the confusion that arises between the data objects (entity class objects) and the manager class objects. In a statfull implementaion, the BL developer HAS to remeber to create an instance of CustomerManager before he can retreive and instance of CustomerEntity. This by iteself does not feel natural as opposed to just "customerManager.get me a customer entity". Also, statefull manager classes run the risk of polluting the "unified data view" model where if you want customer data then its ONLY available in a CustomerEntity not that a CustomerManager has a version of the customerEntity object that is DUFFERENT than a customerEntity object that is freshly fetched from the DB.
omar wrote:
MarcoP wrote:
I just don't like exposing my behavior via static (shared) methods. Here is where you lose most of the OO benefits.
Thats a valid point for using satefull manager classes but the issue myself and other BL developers face with this type of implementation is the confusion that arises between the data objects (entity class objects) and the manager class objects. In a statfull implementaion, the BL developer HAS to remeber to create an instance of CustomerManager before he can retreive and instance of CustomerEntity. This by iteself does not feel natural as opposed to just "customerManager.get me a customer entity". Also, statefull manager classes run the risk of polluting the "unified data view" model where if you want customer data then its ONLY available in a CustomerEntity not that a CustomerManager has a version of the customerEntity object that is DUFFERENT than a customerEntity object that is freshly fetched from the DB.
You have some valid points, but I strongly agree with the notion of 'program to an interface, not an implementation'. In a nutshell, with the UI layer directly talking to the CustomerManager, the two are tighly coupled, thus adding an unwanted dependency, which would make swapping out implementations very difficult, not to mention writing some automated tests (which we all do...right ).
I'm accustomed to using a DI (Dependency Injection) system, where programing to interfaces is vital.
MarcoP wrote:
... I strongly agree with the notion of 'program to an interface, not an implementation'. In a nutshell, with the UI layer directly talking to the CustomerManager, the two are tighly coupled, thus adding an unwanted dependency, which would make swapping out implementations very difficult, not to mention writing some automated tests (which we all do...right
).
I cant argue against the elegance of (Dependcy Injection) but the problem is when you need to build so many applications you have to really present a valid case where you would ever swap a UI's implementation. I am sure there are senarios that an application needed to sawp its implementaion after deployment but I am not sure that this is common when building Line of Business applications where business rules really govern the ongoing maintanance of the application. Balancing ease of development and better tool integration against increasing UI/BL decoupling because MAYBE (if ever) we will need to totally swap-out the BL tier (add to this argument the management pressures for time and cost reduction) and it seems I dont have a reall option for the way to go.
omar wrote:
MarcoP wrote:
... I strongly agree with the notion of 'program to an interface, not an implementation'. In a nutshell, with the UI layer directly talking to the CustomerManager, the two are tighly coupled, thus adding an unwanted dependency, which would make swapping out implementations very difficult, not to mention writing some automated tests (which we all do...right
).
I cant argue against the elegance of (Dependcy Injection) but the problem is when you need to build so many applications you have to really present a valid case where you would ever swap a UI's implementation. I am sure there are senarios that an application needed to sawp its implementaion after deployment but I am not sure that this is common when building Line of Business applications where business rules really govern the ongoing maintanance of the application. Balancing ease of development and better tool integration against increasing UI/BL decoupling because MAYBE (if ever) we will need to totally swap-out the BL tier (add to this argument the management pressures for time and cost reduction) and it seems I dont have a reall option for the way to go.
Yes, but when I say 'swap out', it's more so swapping out test stubs and mocks when running test cases. However, my application needed to support running online and offline, so the interface seperation worked like a charm.
Joined: 28-Oct-2005
Some thoughts about the subject. I feel that in distributed scenario where you are supposed to use llblgen adapter pattern, you have no other choice than going for manager classes. As entities can't do data access (it would not be adapter pattern if they did), you can't implement any multientity oriented business logic inside entities - Unless you make an assumption the graph is always in such a state you can use it inside entities. Which is a dangerous and error prone path really.
One problem with the manager approach, is that the code gets distributed in different places: entities, partial classes, validator classes, manager classes. Also what happens very easily is that manager classes get bloated with code as you end up coding all your business logic in one class (swiss army knife).
I like the idea of using domain model approach where each object has it own responsibilies (and identity, state and action), but I am not sure how llblgen adapter pattern fits there.
sami wrote:
I like the idea of using domain model approach where each object has it own responsibilies (and identity, state and action), but I am not sure how llblgen adapter pattern fits there.
For the domain model approach, you would have to use the self-servicing model where the entities are all encompassing (behavior, state, rules, etc.).
Joined: 28-Oct-2005
MarcoP wrote:
sami wrote:
I like the idea of using domain model approach where each object has it own responsibilies (and identity, state and action), but I am not sure how llblgen adapter pattern fits there.
For the domain model approach, you would have to use the self-servicing model where the entities are all encompassing (behavior, state, rules, etc.).
Correct, but that is not the preferred way in distributed scenario when using llblgen.
Joined: 28-Jul-2005
sami wrote:
Some thoughts about the subject. I feel that in distributed scenario where you are supposed to use llblgen adapter pattern, you have no other choice than going for manager classes. As entities can't do data access (it would not be adapter pattern if they did), you can't implement any multientity oriented business logic inside entities - Unless you make an assumption the graph is always in such a state you can use it inside entities. Which is a dangerous and error prone path really.
Maybe you could add a (static) property to your entities that returns the (full required) prefetchpath to use when fetching. In that case, when it's common in your app to use (at minimum) that prefetchpath, it's more reliable. But ok, it's dangerous because you cannot require the developer to use that property, that's right. Maybe you can solve that by extending the fetching-methods to add that prefetchpath, by implementing the property via an interface that could be used in the fetch-logic to retrieve the prefetchpath.
Joined: 22-Feb-2005
omar wrote:
I cant argue against the elegance of (Dependcy Injection) but the problem is when you need to build so many applications you have to really present a valid case where you would ever swap a UI's implementation. I am sure there are senarios that an application needed to sawp its implementaion after deployment but I am not sure that this is common when building Line of Business applications where business rules really govern the ongoing maintanance of the application. Balancing ease of development and better tool integration against increasing UI/BL decoupling because MAYBE (if ever) we will need to totally swap-out the BL tier (add to this argument the management pressures for time and cost reduction) and it seems I dont have a reall option for the way to go.
Very well said, Omar. This is exactly where I struggle with the concept of DI (and others like mock objects and "real" TDD)--I need a reason to do it before I'm going to invest the time. Is it realistic to spend a lot of time building something where the layers are easily swappable? How many times in my 11 years in IT have I seen a case where only one layer of an application was swapped out (answer: 0).
Like you said, I'm sure there are corner cases, and it's probably a requirement of "real" enterprise development, but that's a long way from starting development on a business application with a decision to implement DI. It all goes to using the right tool for the job, not trying to solve a problem that doesn't exist, YAGNI, etc.
Since we are a consulting organization, providing the most bang for the buck is an important concept for the whole project lifecycle (sales to acceptance). Doing a very vanilla LLBL implementation (with static manager classes) saves us time in development and saves money for the client. The ultimate effect is that we can do more with less.
Phil
Joined: 26-Oct-2003
Gunna jump in here a sec. As MarcoP said above, one of the strong cases for DI is in unit testing. Provide the stub/mock dependency in the tested class's constructor and you've increased your testability quite a bit/lowered the friction.
DI also goes a long way toward maintainability/discovery. I'm a big fan of the Law of Demeter, which basically says that the fewer objects you instantiate from within your class, the better your class will be able to move independently of changes to other objects, the more readable and understandable your code will be, and thus the higher level of maintainability your code will have. Requiring your class's caller to provide the dependencies that are required to make the class work provides immediate information to the maintainer that, at the very least, will keep him from having to hunt through the complete source code of the class trying to determine how it interacts with the rest of the system.
Adding DI principles to your project adds very little time and resources to initial development and lowers the cost of change and maintainability. I would say the only real "cost" is having to create more interfaces than perhaps you might otherwise.
Jeff
Joined: 22-Feb-2005
jeffreygg wrote:
Gunna jump in here a sec. As MarcoP said above, one of the strong cases for DI is in unit testing. Provide the stub/mock dependency in the tested class's constructor and you've increased your testability quite a bit/lowered the friction.
DI also goes a long way toward maintainability/discovery. I'm a big fan of the Law of Demeter, which basically says that the fewer objects you instantiate from within your class, the better your class will be able to move independently of changes to other objects, the more readable and understandable your code will be, and thus the higher level of maintainability your code will have. Requiring your class's caller to provide the dependencies that are required to make the class work provides immediate information to the maintainer that, at the very least, will keep him from having to hunt through the complete source code of the class trying to determine how it interacts with the rest of the system.
Adding DI principles to your project adds very little time and resources to initial development and lowers the cost of change and maintainability. I would say the only real "cost" is having to create more interfaces than perhaps you might otherwise.
I probably need to understand DI better--I've never used it on a real project. It's quite possible that I just don't get it.
Don't you have to create .config files for each object you want to use with DI (and don't you have to code and test these config files by hand?)? To me that seems like it adds complexity to development and deployment. Also, if you have multiple objects to support an interface (mock and real), doesn't that double the amount of classes you have to write? Finally, when you do run into a problem, isn't it more difficult to track down where the problem is, since you have to verify the object that you are actually creating (since you no longer have complete type safety)?
I am not posting this to be disagreeable, I sincerely want to understand why so many OOP developers find DI so exciting. Maybe the light bulb just hasn't gone on for me yet, or maybe the kinds of applications I generally build just wouldn't benefit from DI.
More discussion on this topic would be of great interest to me, as would code samples and/or links to good articles on the "why" as opposed to the "what".
Phil
Joined: 26-Oct-2003
psandler wrote:
I probably need to understand DI better--I've never used it on a real project. It's quite possible that I just don't get it.
Don't you have to create .config files for each object you want to use with DI (and don't you have to code and test these config files by hand?)? To me that seems like it adds complexity to development and deployment.
Not necessarily. Structuremap supports attribute usage which simply identifies to the framework which interfaces are pluggable and which classes are configured to implement them.
It's as easy as:
[PluginFamily("Default")]
public interface IFoo
[Pluggable("Default")]
public class Foo : IFoo
[Pluggable("Test")]
public class TestStubForIFoo : IFoo
The sole argument in the classes there identifies the implementing classes by name, and the use of "Default" on the PluginFamily attribute designates the framework which implementation to use as default. For most uses this is enough. However, yes a config file is supported for more complicated configurations.
Also, if you have multiple objects to support an interface (mock and real), doesn't that double the amount of classes you have to write?
More of a question surrounding testing, right? Because you're going to have as many implementations of IFoo as you need, whether or not you use DI. But, I like to use mock objects versus test stubs. That way I don't have to code a complete implementation for every class under test; the code is reduced; and I get testable behaviors for free, i.e., expectations, predefined return values, etc. So, there's no additional classes required to implement ID, except perhaps the interface that you might not have created otherwise.
Finally, when you do run into a problem, isn't it more difficult to track down where the problem is, since you have to verify the object that you are actually creating (since you no longer have complete type safety)?
I haven't found that to be the case. I'd say the greater issue is the fact that you're using another third party component. In my case, I ran into the problem where StructureMap didn't support nested generics. Otherwise, debugging steps you right into the proper class.
I am not posting this to be disagreeable, I sincerely want to understand why so many OOP developers find DI so exciting. Maybe the light bulb just hasn't gone on for me yet, or maybe the kinds of applications I generally build just wouldn't benefit from DI.
More discussion on this topic would be of great interest to me, as would code samples and/or links to good articles on the "why" as opposed to the "what".
Phil
No problem, I don't mind healthy debate. It helps us all. I really think DI is a great way to refine and add discipline to class construction. There really isn't any difference semantically to not using DI - dependencies are still getting instantiated - the key is where and who has responsibility for instantiating them. DI says that it's better if the person using the class provides what that class needs to operate, rather than the class making those decisions and the programmer losing control over that. "Tell, don't ask" is the idea.
Jeff