Comments on concerns requested

Posts   
 
    
ianvink
User
Posts: 393
Joined: 15-Dec-2006
# Posted on: 02-Nov-2007 18:24:13   

I have received the following concerns on using LLBL as an OR mapper / Business layer from some of our developers who favour another OR mapper (NHibernate) and writing their own business layer on top of it. (We are considering the Adapter pattern.)

Could I have a few comments on these 3 concerns:

"LLBLGen does not lend to test driven development well. As code is generated from database tables, the evolution of the domain independent of the database which is key to a good domain design is lost."

"Since the vision of the architecture is to use a Rich Domain to solve complex business problems, a table driven domain does not evolve naturally. It is highly constrained by the underlying tables and will restrict creative thinking and natural evolution of the domain."

“Refactoring” and “Redesign” which is a very natural programming practice to iteratively improve your solution as the complexity evolves, takes the back seat with the limitations imposed by the generated model. Renaming properties and moving objects around to change the relationships and interactions will be hugely constrained causing the developers to slow down.

Thanks in advance.

JimFoye avatar
JimFoye
User
Posts: 656
Joined: 22-Jun-2004
# Posted on: 03-Nov-2007 19:37:17   

LLBLGen does not lend to test driven development well. As code is generated from database tables, the evolution of the domain independent of the database which is key to a good domain design is lost.

This is actually two statements, neither of which I believe to be true. 1) You can't do test driven development. But the code that is generated from database tables is your data access layer. And it's pretty well battle tested. Any tests you write are going to target your business layer and above. You can test a save operation - but that is higher level than what you think. Why might it fail? Lots of reasons, like violation of foreign key restraints, or bad configuration (database connection). But not because the generated DAL doesn't know how to carry out the save operation. 2) good domain design not possible - see my comments below.

Since the vision of the architecture is to use a Rich Domain to solve complex business problems, a table driven domain does not evolve naturally. It is highly constrained by the underlying tables and will restrict creative thinking and natural evolution of the domain.

This one seems almost too ridiculous to comment on. So everybody currently using LLBLGenPro is unable to solve complex business problems? Because the data access layer is generated from a database schema, instead of the other way around? Clearly whoever said that has not looked at anything I've written. And actually, you could apply this statement to anybody who is creating their data access code using any tool to go against a SQL database, other than an ORM that is domain-driven and controls the db. In other words, it's offensive to 98% of everybody out there.

"Refactoring” and “Redesign” which is a very natural programming practice to iteratively improve your solution as the complexity evolves, takes the back seat with the limitations imposed by the generated model. Renaming properties and moving objects around to change the relationships and interactions will be hugely constrained causing the developers to slow down.

This just isn't true. Believe me, "Refactor"is my middle name.

When you have to refactor your database design, then you will have to modify the schema, and regenerate your DAL, which is easy and straightforward, not time consuming at all. The problem here is that someone wants to completely drive things from the domain model, and not know anything about what's going on in the database design, which will ideally become a black box. I don't think we live in that world, at least not yet, anyway. I, for one, want complete control over every single table, field, index, constraint, and how it's all named. Maybe in another 10 or 20 years, that will not be necessary. But right now I don't trust any software to take a domain model I create and produce the same db that I would by scripting it manually. Call me "old school". But I do realize that that could change sometime in the future.

BTW, I don't want to knock NHibernate too much, but you get what you pay for. NHibernate is free, but LLBLGenPro is evolving constantly, thanks to the tireless efforts of Frans, and a great user base.

Hope this helps.

stefcl
User
Posts: 210
Joined: 23-Jun-2007
# Posted on: 04-Nov-2007 10:27:10   

I agree with JimFoye,

My database tables evolve a lot because I'm constantly improving my application. (Most of the changes are based on customers' feedback). Like JimFoye said, After having done the change in my db, I just regenerate the code and, thanks to the typed query system, all the breaking changes are shown in red at compile-time... I wonder how refactoring could be so much simpler than that.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 04-Nov-2007 13:24:59   

I Agree with Jim, and I'd like to elaborate a bit into details about a couple of things as well.

ianvink wrote:

I have received the following concerns on using LLBL as an OR mapper / Business layer from some of our developers who favour another OR mapper (NHibernate) and writing their own business layer on top of it. (We are considering the Adapter pattern.)

Could I have a few comments on these 3 concerns:

"LLBLGen does not lend to test driven development well. As code is generated from database tables, the evolution of the domain independent of the database which is key to a good domain design is lost."

Well, as Jim explained, it depends on what you are focussing on. As LLBLGen Pro already frees you from the data access stuff, you can focus on building the stuff you want to build, and you can do that in an Agile/userstories/tdd way. The only thing people run into is pure a technical issue: they want to include the data-access elements into their TDD stuff as well, but that's pretty odd, as it's already well tested stuff. So using LLBLGen Pro, frees you from the hassle of going through all that.

LLBLGen Pro's entities are at the same level as a TDD practising developer has to design them on. If a TDD using developer cooks up entities behind the keyboard directly into code, the project is doomed to fail, simply after a while there's no overview which entity classes there are, which real-life abstract entity they represent and WHY they are the way they are.

A solid relational model is created from an abstract entity model. So are the classes in a TDD's domain model. So, if LLBLGen Pro then reverse engineers the tables to that level, what's the difference? Not much, oh of course, there's one: the developer didn't have to type in all the code by hand, and therefore might think the code is 'bad' or 'not optimal'.

Well, all I can say: it's their loss. The thing is that when they leave the project to move on to another project, the poor sods who take over the project to maintain it for years to come, do they have a solid piece of information (i.e. the abstract entity model) onto which the classes are based? NO, that's not the set of tests you have.

So, i.o.w.: it's a different way of how you end up with both classes and tables which are tied together by the fact that they're both a projection of the abstract entity model onto a physical representation: class, table.

It doesn't matter if you write a 'customer' class and generate via nhibernate a table called 'customer' from it, or create a table called 'customer' and generate a class called 'customer' from it, BOTH represent the entity 'customer' defined in the abstract entity model

The abstract entity model is necessary to be able to do transformations on the model when changes are needed. The thing is: if you dont have the model, you're doomed to make transformations in the projection results (code, tables) without the theoretical base WHY you made that change and not another one (e.g. why you added 2 columns or 2 fields and didn't split it up in another table/class).

To make things easier, we've decided to take that extra step and offer a way to express that abstract entity model in a DSL. that DSL is then usable as the source for your domain model in TDD with for example nhibernate or llblgen pro, and it can also be reverse engineered from a schema as LLBLGen Pro already does today.

With that model, you then see that if you make a transformation from it to a new version, the model is the true source for the code and tables you're using. Otherwise, the reasoning behind why you use 1 customer class and not 2 or why you use 2 customer classes in a hierarchy and not 1 with a role enum, is clear.

"Since the vision of the architecture is to use a Rich Domain to solve complex business problems, a table driven domain does not evolve naturally. It is highly constrained by the underlying tables and will restrict creative thinking and natural evolution of the domain."

One who speaks remarks like that, has no clue why tables are the way they are. Let the person have a look at http://www.orm.net and come back and explain why an abstract NIAM/ORM model (the level onto which llblgen pro entities are located) isn't capable of expressing an enterprise model. wink

Good relational model practises dictate that you don't just jump in and start writing CREATE TABLE statements, you start by designing a relational model and then project it onto a SQL dialect.

Now, how is that different with thinking what domains there are and projecting them onto a programming language dialect? wink

“Refactoring” and “Redesign” which is a very natural programming practice to iteratively improve your solution as the complexity evolves, takes the back seat with the limitations imposed by the generated model. Renaming properties and moving objects around to change the relationships and interactions will be hugely constrained causing the developers to slow down.

The idea is: abstract entity model gets changes -> changes are projected onto relational model, relational model gets migrated to new version to reflect the changes -> llblgen pro picks up changes and migrates entities to the new version -> generate code -> recompile project -> fix mismatches in your own code.

THis is essentially the same as: abstract entity mdoel gets changes -> changes are projected onto domain classes -> domain class changes are fed to the o/r mapper which generates a new relational model -> recompiling project -> fix mismatches in your own code.

One of the main design goals of llblgen pro was that it could fulfil this path, this task, so that it can migrate entities to the changes in the relational model, that a user can recompile the project and simply fix the mismatches and that's it. No string based queries which lead to problems at runtime, no 'throw away model, start over with new model' -crap.

Please read my essay The Datamodel is the domain model, which is also part of Jimmy Nilsson's excellent book 'Applying DDD and Patterns'.

Jimmy also had his concerns at first, but after a while he understood that it was all the same, just a different starting point of where one decided to handle the problems at hand.

Frans Bouma | Lead developer LLBLGen Pro