- Home
- LLBLGen Pro
- Architecture
LLBLGen Examples to include a Business Logic Layer
Joined: 27-Feb-2005
Hi Everyone,
I'm pretty new to the world of both OOP and LLBLGen Pro so please bear with my rambling on at first. The question is somewhere down there.
You see I have programmed for years in 4GL's, Delphi, VB as well as just starting to learn C# but i've always been one of those coders that just whack out code to get it done. Not a very good approach I know and I think this boils down to being a self taught programmer.
Just whacking out code has often left me with writing complete new versions of systems over the years instead of expanding on a well designed version because I am finding some concepts hard to understand without first seeing it in code. I know its funny but its true; I can follow code and understand exactly what it is doing but if somebody is discussing Business Logic, Manager Classes, Facades, OOP and Widgets; I can follow along and generally understand what is being said but I have trouble turning that into code inside my head and connecting the pieces together. Very frustrating and maybe I was born to be a dustbin man but I must keep on going, it's my destiny.
I don't regard myself as being a complete newbie because I have coded in VB.NET for the last 2-3 years and launched 5 ecommerce websites which have been very successful indeed. I think my problem is that I am not separating the layers and this is almost certainly why I am spending a considerable amount of time maintaining the sites when new functionality is needed. Hence probably violating nearly every rule of OOP, low coupling and high cohesion as so to speak.
I'm okay with the concept of coding the DAL and building a UI that can consume it. This is basically what I have been doing for the websites I have implemented. I suppose what I am finding difficult is learning how to interact with the LLBLGen Pro generated code as well as trying to consume a BL. Something which is relatively new to me.
What would be really nice to see is the Northwind examples expanded on with a BL layer both in adapter and selfserving scenarios. I think this would really help me (and maybe others) put into context what you guys have been discussing when talking about 'Receiving collections or receiving datatables from the BL layer' or 'Hiding LLBLGen code from the UI' layer.
So my question is, are there any volunteers out there who could add a BL layer to the Norhwind examples both in Adapter and Selfservicing scenarios? VB.NET is preferred but hell i'll take C# no problem.
Also, if there are comments, tips or trade secrets that you guys could pass on. I would love to read them. It is my intention that I will be shouting 'EUREKA' along with you.
Thanks in advance,
Geoff.
Ps. I do hope others out there want this but were afraid to ask
Joined: 17-Aug-2003
davisg wrote:
Just whacking out code has often left me with writing complete new versions of systems over the years instead of expanding on a well designed version because I am finding some concepts hard to understand without first seeing it in code. I know its funny but its true; I can follow code and understand exactly what it is doing but if somebody is discussing Business Logic, Manager Classes, Facades, OOP and Widgets; I can follow along and generally understand what is being said but I have trouble turning that into code inside my head and connecting the pieces together. Very frustrating and maybe I was born to be a dustbin man but I must keep on going, it's my destiny.
Oh, don't feel frustrated, I have a hard time understanding what people talking about also in a lot of occasions (and they even gave me a B.sc in CS years ago! ) , as there are so many acronyms and terms invented every day and often for things I know and use already for years.
I don't regard myself as being a complete newbie because I have coded in VB.NET for the last 2-3 years and launched 5 ecommerce websites which have been very successful indeed. I think my problem is that I am not separating the layers and this is almost certainly why I am spending a considerable amount of time maintaining the sites when new functionality is needed. Hence probably violating nearly every rule of OOP, low coupling and high cohesion as so to speak.
There is one rule: there are no rules. Don't get offended by theory-freaks who want to slam you on the head with their 1200 rules of conduct you have to obey if you want to call yourself a true 'OO' developer, 'Domain model specialist', 'n-tier guru' or what have you. I recently got flamed my ass off in the microsoft csharp newsgroup by a person who claimed to be writing O/R mappers for years and said (literarly): "You really haven't worked with OPFs, have you ?" (OPF==Object persistence frameworks, yeah I had to look it up too ) and I was a RDBMS zealot and I hated OO. Of course! In an MVP newsgroup some VB.NET mvp (McCarthy) told me I really didn't understand interfaces, indexers and enums. uhuh.
You see, the thing is: you probably know all these things already, but not the terms, the buzzwords some marketing bozo cooked up (SOA!). However, is that really important? Not that important IMHO. I never saw the relevance of learning term/buzzword definitions, I more recommend learning theory than buzzwords. 'OOP' is a buzzword, 'Pattern' is too. It's more important why the strategy pattern works than that you can write down its definition in OO rethoric, as knowing 'why' can help you solve similar problems in the future, knowing a definition probably won't.
So, what's important is theory, plain old theory, which is the answer to the question 'why'. Why does something work? Why do you need a facade tier? You give the example in which you have to alter code when some new feature has to be added. Well, even if you would have followed every OO model rule in the book, this might still be the case. A rule of thumb says that iteration 3 of an OO model is probably the model you wanted to have in iteration 1, though no matter how hard you try or know that rule, it will always be iteration 3.
In the documentation I've tried to explain some of the concepts behind techniques used by LLBLGen Pro or techniques which I consider proper plain old theory which can answer a lot of 'why' questions. Take for example the n-tier discussion in the concepts section. This isn't there for nothing, it tries to explain what n-tier is (not a set of rules, but a way of thinking) and gives examples how to apply it to your system design and how LLBLGen Pro fits into this. This doesnt' mean you have to follow this, of course not. Often it's easier to have 2 tiers as code reuse is not that common: adding a 3rd tier will then just add overhead for example.
I'm okay with the concept of coding the DAL and building a UI that can consume it. This is basically what I have been doing for the websites I have implemented. I suppose what I am finding difficult is learning how to interact with the LLBLGen Pro generated code as well as trying to consume a BL. Something which is relatively new to me.
I think you should take a step back and look at the theory behind creating a software system. I think you know all this but you don't realize it: you gather specs of what you have to implement. This is the start of the functional description of what functionality the system has to expose/embed. This is the most important phase of the project, as it gives you insight what you will (have to) build later on. Skipping this will give you problems, guaranteed, if not sooner than later. Keep the functional descriptions as functional as possible and avoid any technical detail.
If you'll look closely at what you've described as functionality, you'll recognize processes. These are the processes you'll model into code, and it is recommended that you keep your executable form of functionality (i.e. the code ) as close to the functional design as possible, i.e.: if you have defined an 'order processing system' you also have to have that in your code structure.
This is important because when you have to alter functionality after the system is in production, you should start with altering the functional descriptions you've made. After you're done, you see what you've altered and you can then start altering code and to find back WHICH code to alter, you don't have to look very far: the functionality defined is easily tracked back into the code (and vice versa: 'what does this routine/class do?' -> look it up in the functionality description and you'll find back its place in the bigger picture)
What would be really nice to see is the Northwind examples expanded on with a BL layer both in adapter and selfserving scenarios. I think this would really help me (and maybe others) put into context what you guys have been discussing when talking about 'Receiving collections or receiving datatables from the BL layer' or 'Hiding LLBLGen code from the UI' layer.
This isn't done for a reason: the examples aren't meant for teaching n-tier development, they're there to illustrate how the functionality works. What I want to avoid is that you will look at the example and see that as 'proper software structuring' because it isn't, that's clearly stated in the example. You should learn theory first, and then apply it to practical things, not the other way around, because if you look solely at practical applications of theory, you'll see the specific implementation of a piece of theory as THE theory, which is IMHO not the way to go.
So my question is, are there any volunteers out there who could add a BL layer to the Norhwind examples both in Adapter and Selfservicing scenarios? VB.NET is preferred but hell i'll take C# no problem.
I'll guarantee you, if I write such a layer for you, you won't learn a thing from it. That's not because you lack any skills, or that the layer will be badly written, but because it's theory applied to a given situation and the only thing which is important is WHY it is implemented that way so you can learn that reasoning and apply it yourself later on.
Don't just add a BL tier because someone says so, apply it because you can answer the "Why is that BL tier implemented" with a solid answer. I know this is the answer you really didn't want, but it's the best advice I can give you, IMHO.
Also, if there are comments, tips or trade secrets that you guys could pass on. I would love to read them. It is my intention that I will be shouting 'EUREKA' along with you.
Buy an old book: Structured Analysis by Edward Yourdon. it's high level theory for system design and software engineering, though it will give you the necessary theory to understand what software development is all about. Not that you don't know that now, IMHO you need some help with connecting the dots, and I promisse you, it's time well spend.
After reading that book, you'll understand that you have data consumers, data producers, data flow, logic applied to data etc. and how to analyze these first. You'll notice that when you've created some DFD(data flow diagrams) or data transition diagrams or even data structure diagrams for a system you're creating, you've way more insight what happens where and more importantly: WHY. So if someone comes up to your desk and asks: Why is that subsystem implemented there and not in these 3 classes, you can answer it without having to show 1000 lines of code, but can answer it with theoretic approved models. The fun thing is: because you create these models, you know that you've thought things through before writing code and you can spot problems ahead of writing code. Also when new functionality has to be added you know how it will affect your system and where.
Joined: 26-Oct-2003
Hey, guys. Thought I'd interject here, if you don't mind.
Geoff: Frans is the smartest guy I don't know. The guy can code; he's got the experience; and he's been through the ringer in the community so you know his viewpoints on the discipline of software development have been war-tested. Moreover, I appreciate his ability to stay "on point" regarding theory and to wade through the superfluous and expose what's important in a given situation; if you listen to him you will do better in your career. I personally have benefited immensely just by reading him and by asking questions - which he so generously answers.
That being said:
Otis wrote:
This isn't done for a reason: the examples aren't meant for teaching n-tier development, they're there to illustrate how the functionality works. What I want to avoid is that you will look at the example and see that as 'proper software structuring' because it isn't, that's clearly stated in the example. You should learn theory first, and then apply it to practical things, not the other way around, because if you look solely at practical applications of theory, you'll see the specific implementation of a piece of theory as THE theory, which is IMHO not the way to go.
<snip>
I'll guarantee you, if I write such a layer for you, you won't learn a thing from it. That's not because you lack any skills, or that the layer will be badly written, but because it's theory applied to a given situation and the only thing which is important is WHY it is implemented that way so you can learn that reasoning and apply it yourself later on.
This is where I disagree with you, Frans. Not that your sentiment about the importance of understanding the theory behind the issue isn't spot-on, but I think you underestimate the value an example has to the learning mind.
I find it very easy to teach in concepts and principles; I'm a theoretical kind of a guy. When I'm done speaking, I'm usually convinced that I've revealed the heart of the issue, defined the parameters of whats important, and taught the guy to fish. However, I rarely leave feeling like the theory has been truly grasped.
I think the problem is that it's easy to grasp the theory - and communicate it - once the context is understood. But without the context the theory is meaningless. I don't think the mind has what it needs to process the concept without it.
I think that, at this level, while we would instinctively like to teach from an inductive model, all of the "mojo" that would connect the listener to the theory lies in the deductive model.
Take design patterns. How many people - especially young developers - would you feel comfortable just dropping the GoF book on them? There's a certain percentage, to be sure, that would feel right at home reading it for the first time. My assumption is that this percentage goes up based on their relative experience level. However, for those who don't have the experience to put those design patterns in context, there's books like "Head First Design Patterns". "Head First Design Patterns" takes the major design patterns, gives "real world" (or not so real world) examples, walks you through it, then gives you the principle that's being worked with. Very effective.
I agree that using examples as a method of teaching concepts assumes the danger of limiting the learner's understanding of the theory to the given example or context, but that's not as important, IMHO, as the risk of the learner not grasping the concept at all. I would rather the learner grasp the concept only partially in terms of the example given than risk him missing the concept completely. I believe it's then his responsibility to take what he's learned and apply it to his environment - as long as the theory isn't sacrificed for the example.
Of course, explaining these concepts to your customers isn't your responsibility. But if you choose to, an example now and then would help.
Jeff...
Joined: 17-Aug-2003
jeffreygg wrote:
Geoff: Frans is the smartest guy I don't know. The guy can code; he's got the experience; and he's been through the ringer in the community so you know his viewpoints on the discipline of software development have been war-tested. Moreover, I appreciate his ability to stay "on point" regarding theory and to wade through the superfluous and expose what's important in a given situation; if you listen to him you will do better in your career. I personally have benefited immensely just by reading him and by asking questions - which he so generously answers.
Thanks for the compliments!
That being said:
Otis wrote:
This isn't done for a reason: the examples aren't meant for teaching n-tier development, they're there to illustrate how the functionality works. What I want to avoid is that you will look at the example and see that as 'proper software structuring' because it isn't, that's clearly stated in the example. You should learn theory first, and then apply it to practical things, not the other way around, because if you look solely at practical applications of theory, you'll see the specific implementation of a piece of theory as THE theory, which is IMHO not the way to go.
<snip>
I'll guarantee you, if I write such a layer for you, you won't learn a thing from it. That's not because you lack any skills, or that the layer will be badly written, but because it's theory applied to a given situation and the only thing which is important is WHY it is implemented that way so you can learn that reasoning and apply it yourself later on.
This is where I disagree with you, Frans. Not that your sentiment about the importance of understanding the theory behind the issue isn't spot-on, but I think you underestimate the value an example has to the learning mind.
Oh I do understand that an example is valuable, but without context, it's just that: 'an' example, but it's unclear what it is an example of (IMHO). So with a BL tier in the example, a document explaining the theory behind it also has to be added.
I find it very easy to teach in concepts and principles; I'm a theoretical kind of a guy. When I'm done speaking, I'm usually convinced that I've revealed the heart of the issue, defined the parameters of whats important, and taught the guy to fish. However, I rarely leave feeling like the theory has been truly grasped.
I think the problem is that it's easy to grasp the theory - and communicate it - once the context is understood. But without the context the theory is meaningless. I don't think the mind has what it needs to process the concept without it.
I think that, at this level, while we would instinctively like to teach from an inductive model, all of the "mojo" that would connect the listener to the theory lies in the deductive model.
Take design patterns. How many people - especially young developers - would you feel comfortable just dropping the GoF book on them? There's a certain percentage, to be sure, that would feel right at home reading it for the first time. My assumption is that this percentage goes up based on their relative experience level. However, for those who don't have the experience to put those design patterns in context, there's books like "Head First Design Patterns". "Head First Design Patterns" takes the major design patterns, gives "real world" (or not so real world) examples, walks you through it, then gives you the principle that's being worked with. Very effective.
Agreed. So what you're suggesting is an example WITH explanation of n-tier development and showing the code in an n-tier application? I think that can only work if my explanation of n-tier development is solid, but I'm a bit reluctant to do that, as I don't see it as my job to educate developers what n-tier development is. I like the idea, don't get me wrong, it's just that I don't want that developers are going to see the examples as 'how it should be done', because that's the least thing I want. What I want is that they read the manual, and use the examples as an implementation example of the various features. I know that placing the code in a bigger picture can be a problem, but IMHO, that's mostly caused by the fact that the developer is new to the design of a larger system. I mean: if you're designing a larger system, you don't start with 'I have this dal here, let's build the system around it', no you need at some point in time, the generated code functionality to make the data consumers be able to consume the data in the system.
I agree that using examples as a method of teaching concepts assumes the danger of limiting the learner's understanding of the theory to the given example or context, but that's not as important, IMHO, as the risk of the learner not grasping the concept at all. I would rather the learner grasp the concept only partially in terms of the example given than risk him missing the concept completely. I believe it's then his responsibility to take what he's learned and apply it to his environment - as long as the theory isn't sacrificed for the example.
I'm unsure where to draw the line what to explain and what not. IF an example about n-tier development is made (I still have planned to build the petshop application, which would be a good example for that), it has to come with solid explanation as well. The thing is though that I'm a sucker at drawing lines when it comes to "from here on you are on your own", I always try to tell a little more, which is often leading to long(er) texts than initially anticipated .
That's why I wrote the example applications to just illustrate the raw functionality, in an application that is hardly usable as an application by itself, to avoid having to deal with people who claim that the structure of teh overall application sucks because it is not well designed in their eyes. .
As I'm in the process of creating more depth into the application for (potential) customers, examples are part of that, and I know more examples are wanted (e.g. webapplication). I'll see what I can do in the 'application design' department when writing that application.
Of course, explaining these concepts to your customers isn't your responsibility. But if you choose to, an example now and then would help. Jeff...
. In a way it is my responsibility of course. If customers or potential customers can't find information how to properly embed the generated code into their systems, the code is of no use. With 'how' I mean semantically.
Joined: 17-Aug-2003
JimFoye wrote:
Structured Analysis by Edward Yourdon
Ok, I've heard you recommend this enough times I just ordered from Amazon!
Cool! Now, the book is not new, the things explained in it may look dated, but the theory in the book is IMHO very useful today as well. It's a great way to teach yourself a way of thinking to get insight in what really has to be done etc. IMHO too much computer science related material is taught through technical details. System design doesn't start with .NET, it ends with .NET, for example
Joined: 26-Oct-2003
Otis wrote:
Agreed. So what you're suggesting is an example WITH explanation of n-tier development and showing the code in an n-tier application? I think that can only work if my explanation of n-tier development is solid, but I'm a bit reluctant to do that, as I don't see it as my job to educate developers what n-tier development is.
Understood.
I like the idea, don't get me wrong, it's just that I don't want that developers are going to see the examples as 'how it should be done', because that's the least thing I want. What I want is that they read the manual, and use the examples as an implementation example of the various features.
Understood.
I know that placing the code in a bigger picture can be a problem, but IMHO, that's mostly caused by the fact that the developer is new to the design of a larger system. I mean: if you're designing a larger system, you don't start with 'I have this dal here, let's build the system around it', no you need at some point in time, the generated code functionality to make the data consumers be able to consume the data in the system.
Yep. However, this is the goal of the education process, to help them understand how to place the concept into the bigger picture. Depends on who your audience is as to whether they already have within themselves the context against which they can apply the lesson. If they don't they have nothing unless that context is given to them.
That's why I wrote the example applications to just illustrate the raw functionality, in an application that is hardly usable as an application by itself, to avoid having to deal with people who claim that the structure of teh overall application sucks because it is not well designed in their eyes. .
Yea, I understand that. That's probably a pretty large liability with what I know of the community at large. I have no problem if you choose not to give example code for personal, time, marketing, or financial reasons; but I don't necessarily agree with the choice not to give example code because it's not important or would "get in the way" of the principle behind the lesson.
As I'm in the process of creating more depth into the application for (potential) customers, examples are part of that, and I know more examples are wanted (e.g. webapplication). I'll see what I can do in the 'application design' department when writing that application.
Again, I'm not nearly implying that I think you have a responsibility to teach. But you've chosen to make this a very personal product for a lot of people and have volunteered your time so generously to improve not only our understanding of the product, but of the software development discipline in general. I wanted you to know that I think if you gave more practical examples to show applicability the lessons would go a lot farther.
I would even recommend leaving these kinds of lessons out of the documentation (except, of course, as it pertains to the product in general), as that might somehow lead people to the expectation that it is your responsibility to teach them. The older I get the more I'm impressed by peoples' sense of entitlement. Maybe that's just a USA thing.
Jeff...
Joined: 27-Feb-2005
Guys,
First off thank you very much for the comments and guidence. It helps tremendously knowing how people position themselves when trying to learn something with so much depth.
Frans: I understand perfectly what you are saying and you are correct as I do really need to understand more about the theory. I found an online updated, consolidated version of 'Modern Structured Analysis' called 'Just Enough Structured Analysis' by Edward Yourdon here:
[http://www.yourdon.com/books/msa2e/](http://www.yourdon.com/books/msa2e/) - Link now deleted, sorry!
Sorry Jim, you maybe could of saved a few bucks
I am still in the early stages of reading this but it is a good read and I am starting to put things into a better perspective so thanks for the tip.
Jeff: What can I say, I couldn't have put it better myself. As the saying goes a picture is a thousand words and I think code fits into the same analogy when you put a program into the same perspective as a picture IMHO. I also think that people learn by example or by examples of others. IMHO.
I suppose for me I am wanting to learn how to use LLBLGenPro the right way for any given n-tier scenario. Sure I don't have to have a BL layer but I don't have enough knowledge to go about implementing LLBLGenPro if I do need one so without an example of how it fits I think that I would make a complete mess of it. In fact it doesn't have to be a full blown example, a little code here would help tremendously in bridging the gap. i.e.
UI Layer
BL.GetCustomers()
BL Layer
???
LLBLGenPro
Customer Generated Entities
Thanks in advance.
Geoff.
Joined: 12-Jul-2004
This document helped me sorted out the question: When to Use N-Tier Designs? http://www.ftponline.com/archives/premier/mgznarch/vbpj/2001/09sep01/bp0109/bp0109.asp Plus Lhotka has some great books on the topic, you'll find them if you google it.
Joined: 17-Aug-2003
davisg wrote:
Frans: I understand perfectly what you are saying and you are correct as I do really need to understand more about the theory. I found an online updated, consolidated version of 'Modern Structured Analysis' called 'Just Enough Structured Analysis' by Edward Yourdon here:
http://www.yourdon.com/books/msa2e/
Sorry Jim, you maybe could of saved a few bucks
I didn't know this was online, thanks for the link! Sorry Jim, if I'd known this, I'd have passed you the URL. Though I don't think the original book is 'outdated', as the principles taught are still usable today, heck, Rational XDE is founded on it.
I am still in the early stages of reading this but it is a good read and I am starting to put things into a better perspective so thanks for the tip.
Great!
About the examples: As 1.0.2004.2 introduces some new concepts, (you'll see shortly), I also have to test these out in real life scenario's so I understand more if the design of the interfaces is ok or that it is cumbersome and I have to change it. As I already wanted to re-implement the petshop system with LLBLGen Pro, I think I'll do that next week and will do that with a 3-tier layer, so a proper example for that is build into that example, and at the same time I hope to testdrive some of my new concepts to see if they work.
Joined: 17-Aug-2003
jeffreygg wrote:
As I'm in the process of creating more depth into the application for (potential) customers, examples are part of that, and I know more examples are wanted (e.g. webapplication). I'll see what I can do in the 'application design' department when writing that application.
Again, I'm not nearly implying that I think you have a responsibility to teach. But you've chosen to make this a very personal product for a lot of people and have volunteered your time so generously to improve not only our understanding of the product, but of the software development discipline in general. I wanted you to know that I think if you gave more practical examples to show applicability the lessons would go a lot farther.
I would even recommend leaving these kinds of lessons out of the documentation (except, of course, as it pertains to the product in general), as that might somehow lead people to the expectation that it is your responsibility to teach them. The older I get the more I'm impressed by peoples' sense of entitlement. Maybe that's just a USA thing.
Well, an example is of course always welcome, and I'll take your advice and will try to write a more n-tier like example (with webcode) next week, using the petshop code.
Joined: 26-Oct-2003
davisg wrote:
I suppose for me I am wanting to learn how to use LLBLGenPro the right way for any given n-tier scenario. Sure I don't have to have a BL layer but I don't have enough knowledge to go about implementing LLBLGenPro if I do need one so without an example of how it fits I think that I would make a complete mess of it. In fact it doesn't have to be a full blown example, a little code here would help tremendously in bridging the gap. i.e.
UI Layer
BL.GetCustomers()
BL Layer
???
LLBLGenPro
Customer Generated Entities
Thanks in advance.
Geoff.
Hi, Geoff. In lieu of the now-famed examples Frans will be adding to the documentation , here's my take on some code snippets to give you a feel for how I design my tiered applications:
UI Layer Nothing goes in here but presenting data (meaning you aren't fetching it, persisting it, or acting on it). Anything else requires a call to the BL.
PopulateGrid(BL.GetCustomers)
cmdSave_Click {BL.Save}
Databindings.Add("Text", BL.Invoice, "InvoiceNumber")
BL Layer No presentation or persistence logic goes in here. Meaning I do not raise message boxes or directly interface with the user here. I tell the UI the result of the last request it made, and let the UI decide how to present it. In the same vein, I do not directly interface with the data source. I tell the DAL that I need data or need to persist it, and I let the DAL decide exactly how to do it. I am 100% presentation implementation and persistence implementation agnostic.
I tend to allow my BL layer to have both stateful and stateless properties. A common pattern you'll see in these forums is the Manager pattern. The idea is to dumb down the data objects themselves and place the business logic in classes on a per process basis. This has the benefit of a strong mapping of the functional requirements of the project to the technical implementation as well as providing for centralized access to common functionality.
Oh yea; examples. Instead of having a rich SalesOrder object, you have a dumb one that is sent to (consumed by) a SalesOrderManager class. This is your BL class. It represents, perhaps, the taking of a new SalesOrder. But as the SalesOrder process spans many different entities (Orders, OrderDetails, Inventory, etc), you don't have to worry about where or on which entity the necessary methods are located; they're all located on the class that represents what you're doing: the SalesOrderManager class. Also, since one of the functional requirements is to be able to take Sales Orders, you know exactly where that functional requirement was technically implemented.
Anyway, I use stateful methods for functionality that directly represents the process I'm working on, and stateless methods for "service-like" functionality, ie, data fetches, etc.
BL.GetOrders (shared/static)
BL.GetCustomersByRegionID (shared/static)
BL.Save (instance)
BL.Validate (instance)
Data Access Layer Contains everything needed to fetch from and persist data to the data store. No more, no less. This layer may be superfluous in certain environments, but I would say you should assume you need it and come up with good reasons why you shouldn't in any given scenario.
In the LLBLGen Framework, you must use the Adapter scenario in order to achieve a true abstraction of the DAL. Self-servicing, while (nice) and easy to use, has, for example, a save method built in that allows anyone in any tier to persist the data. Not good, depending on your requirements and time restrictions.
Having a generic data layer is nice and results in very clean, manageable code. It's been a joy using Adapter after I switched from Self-Servicing, even with the additional typing required.
DAL.GetEntityCollection(entityType, filter)
DAL.GetEntity(id)
DAL.SaveEntityCollection(collection)
DAL.SaveEntity(entity)
Hope this helps. You'll find that there seems to be some redundancies and/or common patterns in the BL. Someone (can't remember who off the top of my head, sorry) has written a BL generator template that Frans has made available in the third-party section. Some have found it very useful, but know that it won't do everything you need. In fact I recommend that you don't look at what code it generates at first and instead start building your own as a learning tool, and to put the example itself in context. Heh, I guess I don't disagree with Frans that much.
Jeff...
Joined: 08-Apr-2004
Thanks guys for some interesting reading. I remember coming into LLBLGen with exaclty the same questions, and wondering how I shoudl set up the tiers of my app.
Jeff, can you clear something up for me here. Are you saying that you believe a DAL is required which will then use LLBLGenerated code, or that LLBLGen is the DAL. IMHO, the latter is nearly always the case. I haven't come accross any situations where an extra layer is required to act as the DAL. Using the adaptor model, the BL is free to call directly to the generated code, and this has worked well for us. Do you store things like common predicate expressions in your DAL? Maybe I am missing some reuse potential in my model, I'm interested to know what you think.
Also something I never managed to clear up: Is it better to transport LLBL entities up to the UI layer, or does that "tightly couple" too much and remove a lot of flexibility? I was worried about "data shaping", and wanted a solution that would allow me to create my own entitties quite easily and send these up to the UI very easily, so thats the path I went down (plus using DataTables for collections). I don't know for our application if it was the right thing to do, but it seems to work pretty well. But... it does mean extra overhead for us - when we get an entity out of the database we have to "transform" it into our custom entity before passing it back up to the client, and vice versa when we pass it back. Has anybody else done this?
Joined: 26-Oct-2003
Hi, Matt.
MattWoberts wrote:
Thanks guys for some interesting reading. I remember coming into LLBLGen with exaclty the same questions, and wondering how I shoudl set up the tiers of my app.
Jeff, can you clear something up for me here. Are you saying that you believe a DAL is required which will then use LLBLGenerated code, or that LLBLGen is the DAL. IMHO, the latter is nearly always the case. I haven't come accross any situations where an extra layer is required to act as the DAL. Using the adaptor model, the BL is free to call directly to the generated code, and this has worked well for us. Do you store things like common predicate expressions in your DAL? Maybe I am missing some reuse potential in my model, I'm interested to know what you think.
I wrap the DataAccessAdapter in my own DAL. Is it necessary in absolutely every situation? Not even close . And it's not very fun to do as there are a lot of methods on the DataAccessAdapter and a lot of overloads. That being said, however, there are some circumstances where it has some value or is even required.
The one piece of the DataAccessAdapter that isn't abstracted is the communications method. By placing one more layer of abstraction between the DataAccessAdapter and the business layer I'm able to control how data is coming and going from the DataAccessLayer. Perhaps this technically isn't an abstracted DAL, but functionally it works like that.
A specific use for this comes in eventing. I have a requirement in my current project that requires that every time certain entities are saved, I must notify all users who've registered. However, I'm also using remoting so two-way channels are out. And what if I wanted to use web services? I need control over the commnunications method.
Also something I never managed to clear up: Is it better to transport LLBL entities up to the UI layer, or does that "tightly couple" too much and remove a lot of flexibility? I was worried about "data shaping", and wanted a solution that would allow me to create my own entitties quite easily and send these up to the UI very easily, so thats the path I went down (plus using DataTables for collections). I don't know for our application if it was the right thing to do, but it seems to work pretty well. But... it does mean extra overhead for us - when we get an entity out of the database we have to "transform" it into our custom entity before passing it back up to the client, and vice versa when we pass it back. Has anybody else done this?
I personally use LLBL entities in all layers. I don't have a problem with that. If you're going to strongly couple the BL to LLBLGenPro, why not the UI? The entities (at least the Adapter entities) are perfect data transport objects and since they're already being used in the BL, just send them up the PL.
That being said, the entities aren't sufficient in many cases. The major drawback to them is that they aren't able to easily represent data from many different tables. The new 1:1 mapping functionality Frans is adding to the next version will help quite a bit with this, but it won't hande all of the edge cases.
Since I wanted a consistent mechanism to work with, for most of my grids and sub-collection requirements I use the Dynamic Typed List functionality and datatables. I built a system where the datatables are created automatically, and a system to get those datatables back into entity collections. Works flawlessly. So now, instead of BL.GetPurchaseOrderCollection, it's BL.GetPurchaseOrderData, and I really don't have to worry too much at the BL level about getting the data back into entities and collections. It's handled automatically with a "transform" method. Let me know if you'd like to see the code. I promised Frans I would give him a sanitized version for the third party area but I haven't delivered yet.
Jeff...
Joined: 14-Sep-2004
jeffreygg wrote:
Hi, Matt.
MattWoberts wrote:
Thanks guys for some interesting reading. I remember coming into LLBLGen with exaclty the same questions, and wondering how I shoudl set up the tiers of my app.
Jeff, can you clear something up for me here. Are you saying that you believe a DAL is required which will then use LLBLGenerated code, or that LLBLGen is the DAL. IMHO, the latter is nearly always the case. I haven't come accross any situations where an extra layer is required to act as the DAL. Using the adaptor model, the BL is free to call directly to the generated code, and this has worked well for us. Do you store things like common predicate expressions in your DAL? Maybe I am missing some reuse potential in my model, I'm interested to know what you think.
I wrap the DataAccessAdapter in my own DAL. Is it necessary in absolutely every situation? Not even close . And it's not very fun to do as there are a lot of methods on the DataAccessAdapter and a lot of overloads. That being said, however, there are some circumstances where it has some value or is even required.
The one piece of the DataAccessAdapter that isn't abstracted is the communications method. By placing one more layer of abstraction between the DataAccessAdapter and the business layer I'm able to control how data is coming and going from the DataAccessLayer. Perhaps this technically isn't an abstracted DAL, but functionally it works like that.
A specific use for this comes in eventing. I have a requirement in my current project that requires that every time certain entities are saved, I must notify all users who've registered. However, I'm also using remoting so two-way channels are out. And what if I wanted to use web services? I need control over the commnunications method.
Also something I never managed to clear up: Is it better to transport LLBL entities up to the UI layer, or does that "tightly couple" too much and remove a lot of flexibility? I was worried about "data shaping", and wanted a solution that would allow me to create my own entitties quite easily and send these up to the UI very easily, so thats the path I went down (plus using DataTables for collections). I don't know for our application if it was the right thing to do, but it seems to work pretty well. But... it does mean extra overhead for us - when we get an entity out of the database we have to "transform" it into our custom entity before passing it back up to the client, and vice versa when we pass it back. Has anybody else done this?
I personally use LLBL entities in all layers. I don't have a problem with that. If you're going to strongly couple the BL to LLBLGenPro, why not the UI? The entities (at least the Adapter entities) are perfect data transport objects and since they're already being used in the BL, just send them up the PL.
That being said, the entities aren't sufficient in many cases. The major drawback to them is that they aren't able to easily represent data from many different tables. The new 1:1 mapping functionality Frans is adding to the next version will help quite a bit with this, but it won't hande all of the edge cases.
Since I wanted a consistent mechanism to work with, for most of my grids and sub-collection requirements I use the Dynamic Typed List functionality and datatables. I built a system where the datatables are created automatically, and a system to get those datatables back into entity collections. Works flawlessly. So now, instead of BL.GetPurchaseOrderCollection, it's BL.GetPurchaseOrderData, and I really don't have to worry too much at the BL level about getting the data back into entities and collections. It's handled automatically with a "transform" method. Let me know if you'd like to see the code. I promised Frans I would give him a sanitized version for the third party area but I haven't delivered yet.
Jeff...
Jeff, I would love to see your datatable to EntityCollection code. Thanks in advance.
Lyndon
Joined: 08-Apr-2004
Hi Jeff,
Thanks for taking the time for a thorough reply
The one piece of the DataAccessAdapter that isn't abstracted is the communications method. By placing one more layer of abstraction between the DataAccessAdapter and the business layer I'm able to control how data is coming and going from the DataAccessLayer. Perhaps this technically isn't an abstracted DAL, but functionally it works like that.
I getcha. Now you put it into context, I see exactly why you would do this and the benefits you gain from it. In our situation, we dont need this kind of functionality so thats why LLBLGen code IS our data layer.
I personally use LLBL entities in all layers. I don't have a problem with that. If you're going to strongly couple the BL to LLBLGenPro, why not the UI? The entities (at least the Adapter entities) are perfect data transport objects and since they're already being used in the BL, just send them up the PL.
You're right in that not wanting to tightly couple layers is NOT a reason to avoid the use the LLBLGen entity consumption at the PL. Only a tier purist would go to all the extra work of custom entities just for that...its you're next point that prompted me to use our own...
That being said, the entities aren't sufficient in many cases. The major drawback to them is that they aren't able to easily represent data from many different tables. The new 1:1 mapping functionality Frans is adding to the next version will help quite a bit with this, but it won't hande all of the edge cases.
Exactly! They're not sufficient for a lot of our cases. They map the data table, not the business information relevent. We want to expand our entities, to include reference data or perhaps to create custom fields etc. I mulled over the best way to do this, and decided to create a template that generates our custom entities as welll as the LLBLGen ones - ours are very simple structs with properties for the field.s. We can then use a central method to copy a "custom entity" into a LLBLGen entity and vice versa (they have the same property names so this is easy using reflection). Its worked well in some cases, but does create some overhead and has some limitations.
It's handled automatically with a "transform" method. Let me know if you'd like to see the code. I promised Frans I would give him a sanitized version for the third party area but I haven't delivered yet.
We also use datatables, although we dont transer them from entity collections into datatables - I'd be very interested to see this code - thanks!
Joined: 26-Oct-2003
MattWoberts wrote:
We also use datatables, although we dont transer them from entity collections into datatables - I'd be very interested to see this code - thanks!
Actually, it's vice versa; getting datatables back into entity collections is the hard part. I started working on "sanitizing" the code for public consumption. I'll post it as soon as it's done.
Jeff...
Joined: 27-Feb-2005
Otis wrote:
davisg wrote:
Frans: I understand perfectly what you are saying and you are correct as I do really need to understand more about the theory. I found an online updated, consolidated version of 'Modern Structured Analysis' called 'Just Enough Structured Analysis' by Edward Yourdon here:
http://www.yourdon.com/books/msa2e/
Sorry Jim, you maybe could of saved a few bucks
I didn't know this was online, thanks for the link! Sorry Jim, if I'd known this, I'd have passed you the URL. Though I don't think the original book is 'outdated', as the principles taught are still usable today, heck, Rational XDE is founded on it.
I am still in the early stages of reading this but it is a good read and I am starting to put things into a better perspective so thanks for the tip.
Great!
About the examples: As 1.0.2004.2 introduces some new concepts, (you'll see shortly), I also have to test these out in real life scenario's so I understand more if the design of the interfaces is ok or that it is cumbersome and I have to change it. As I already wanted to re-implement the petshop system with LLBLGen Pro, I think I'll do that next week and will do that with a 3-tier layer, so a proper example for that is build into that example, and at the same time I hope to testdrive some of my new concepts to see if they work.
Thanks Frans. I think the petshop system in LLBLGenPro would be absolutely fantastic.
Joined: 27-Feb-2005
jeffreygg wrote:
davisg wrote:
I suppose for me I am wanting to learn how to use LLBLGenPro the right way for any given n-tier scenario. Sure I don't have to have a BL layer but I don't have enough knowledge to go about implementing LLBLGenPro if I do need one so without an example of how it fits I think that I would make a complete mess of it. In fact it doesn't have to be a full blown example, a little code here would help tremendously in bridging the gap. i.e.
UI Layer
BL.GetCustomers()
BL Layer
???
LLBLGenPro
Customer Generated Entities
Thanks in advance.
Geoff.
Hi, Geoff. In lieu of the now-famed examples Frans will be adding to the documentation , here's my take on some code snippets to give you a feel for how I design my tiered applications:
UI Layer Nothing goes in here but presenting data (meaning you aren't fetching it, persisting it, or acting on it). Anything else requires a call to the BL.
PopulateGrid(BL.GetCustomers) cmdSave_Click {BL.Save} Databindings.Add("Text", BL.Invoice, "InvoiceNumber")
BL Layer No presentation or persistence logic goes in here. Meaning I do not raise message boxes or directly interface with the user here. I tell the UI the result of the last request it made, and let the UI decide how to present it. In the same vein, I do not directly interface with the data source. I tell the DAL that I need data or need to persist it, and I let the DAL decide exactly how to do it. I am 100% presentation implementation and persistence implementation agnostic.
I tend to allow my BL layer to have both stateful and stateless properties. A common pattern you'll see in these forums is the Manager pattern. The idea is to dumb down the data objects themselves and place the business logic in classes on a per process basis. This has the benefit of a strong mapping of the functional requirements of the project to the technical implementation as well as providing for centralized access to common functionality.
Oh yea; examples. Instead of having a rich SalesOrder object, you have a dumb one that is sent to (consumed by) a SalesOrderManager class. This is your BL class. It represents, perhaps, the taking of a new SalesOrder. But as the SalesOrder process spans many different entities (Orders, OrderDetails, Inventory, etc), you don't have to worry about where or on which entity the necessary methods are located; they're all located on the class that represents what you're doing: the SalesOrderManager class. Also, since one of the functional requirements is to be able to take Sales Orders, you know exactly where that functional requirement was technically implemented.
Anyway, I use stateful methods for functionality that directly represents the process I'm working on, and stateless methods for "service-like" functionality, ie, data fetches, etc.
BL.GetOrders (shared/static) BL.GetCustomersByRegionID (shared/static) BL.Save (instance) BL.Validate (instance)
Data Access Layer Contains everything needed to fetch from and persist data to the data store. No more, no less. This layer may be superfluous in certain environments, but I would say you should assume you need it and come up with good reasons why you shouldn't in any given scenario.
In the LLBLGen Framework, you must use the Adapter scenario in order to achieve a true abstraction of the DAL. Self-servicing, while (nice) and easy to use, has, for example, a save method built in that allows anyone in any tier to persist the data. Not good, depending on your requirements and time restrictions.
Having a generic data layer is nice and results in very clean, manageable code. It's been a joy using Adapter after I switched from Self-Servicing, even with the additional typing required.
DAL.GetEntityCollection(entityType, filter) DAL.GetEntity(id) DAL.SaveEntityCollection(collection) DAL.SaveEntity(entity)
Hope this helps. You'll find that there seems to be some redundancies and/or common patterns in the BL. Someone (can't remember who off the top of my head, sorry) has written a BL generator template that Frans has made available in the third-party section. Some have found it very useful, but know that it won't do everything you need. In fact I recommend that you don't look at what code it generates at first and instead start building your own as a learning tool, and to put the example itself in context. Heh, I guess I don't disagree with Frans that much.
Jeff...
Jeff, thanks for this and taking the time to explain. I have learned a lot from this thread.
Geoff.
Joined: 17-Aug-2003
davisg wrote:
Otis wrote:
davisg wrote:
Frans: I understand perfectly what you are saying and you are correct as I do really need to understand more about the theory. I found an online updated, consolidated version of 'Modern Structured Analysis' called 'Just Enough Structured Analysis' by Edward Yourdon here:
http://www.yourdon.com/books/msa2e/
Sorry Jim, you maybe could of saved a few bucks
I didn't know this was online, thanks for the link! Sorry Jim, if I'd known this, I'd have passed you the URL. Though I don't think the original book is 'outdated', as the principles taught are still usable today, heck, Rational XDE is founded on it.
I am still in the early stages of reading this but it is a good read and I am starting to put things into a better perspective so thanks for the tip.
Great!
About the examples: As 1.0.2004.2 introduces some new concepts, (you'll see shortly), I also have to test these out in real life scenario's so I understand more if the design of the interfaces is ok or that it is cumbersome and I have to change it. As I already wanted to re-implement the petshop system with LLBLGen Pro, I think I'll do that next week and will do that with a 3-tier layer, so a proper example for that is build into that example, and at the same time I hope to testdrive some of my new concepts to see if they work.
Thanks Frans. I think the petshop system in LLBLGenPro would be absolutely fantastic.
I think so too The only drawback is that I can't find a decent implementation on Oracle from Sun. It has to be there, but I can't find it. The reason I want it is to build an example with oracle and sqlserver in one app. Oh well, I'll try to port the horrible MS implementation to oracle then . It's good dogfooding I think. I'll start on it tomorrow.
Joined: 17-Aug-2003
davisg wrote:
Hi Frans,
Did we get anywhere with the Petshop application? Not pushing or anything as I know you are well busy with the Beta but just wanted to mention it Geoff.
I've ported the DAL and BL tier, I'm currently busy with the PL tier. I've ported MSPetshop v3.2, and it's so incredibly horrible, porting is harder than I thought (as in: 1:1 porting would be bad, as the horrible code structure would stay in tact). I very much understand how mad Sun was after seeing MS ruin their design. The whole app is setup just to perform as fast as it can, which is a point you should never try to accomplish in an example. It's also horrible programmed, with code like:
cartItem.InStock = (GetInStock(ItemId) - cartItem.Quantity) >= 0 ? true : false;
Not only is '? :' a statement you shouldn't use, this is also written as cryptic as possible by a person who didn't have a clue, because : cartItem.InStock =( (GetInStock(ItemId) - cartItem.Quantity) >= 0);
does the same.
Different ways the code is written: KR style of curly brackets (method header { /// }) vs. normal style of curly brackets: (method header { /// })
this is fundamental, there is no programmer on earth who uses them both in one application.
this: Item item = new Item(); is against MS rules of naming classes and parameters. It might sound like nittpicking, but this IS an example after all, however if you take a look at it, it's an example all right, a BAD example... how not to write your code
The search query builder is a classic. It can be on thedailywtf.com tomorrow: as soon as some table changes this falls apart in a brilliant way. Needless to say, my eyes hurt after a while.
I hope to finish the port into a beta app later this week. The example is kind of nice as it shows multiple catalog support as well
Joined: 27-Feb-2005
Hi Frans,
Wow, heh. And I thought MS had a really good argument on the PetShop port, NOT !
Thanks for the update thought, appreciated and look forward to looking through the code when it is finished. Could be a very important example for everybody to learn from I think.
Geoff.