Friday, October 26, 2007

Thinking of an NHibernate Mapping DSL

Something about Ayende inspires me to build something.  I got to thinking today about how I could create a DSL for NHibernate mapping files.  What's wrong with XML, you say?  Well...

  • It's verbose - XML is known for it's ability to easily validate based on a schema, not for readability.  In other words, XML was designed for computers, not humans.  Since I am a human (are you?) I would prefer something a bit more friendly.
  • Schema Validation takes time - Usually you don't notice, but some recent metrics show that it can account for more than 1/2 of the startup time for NHibernate when there are many mapping files.  If you have an appliaction with 1000 entities, arguably you have bigger problems than XML's readability and schema validation performance, but it IS noticable so hey....
  • Generates runtimes errors for semantic structure - Sure, the syntax is validated, but there are so many things that can go wrong with runtime compilation (that's a weird term) of mappings.
So I got to thinking how we could do better.  Here's what I came up with (with some additions from Ayende) -- it's in Boo:

import flux88.NHibernate.Mapping

mapping Test.Project, Test.Project.Entities

entity Customer,
table: Customers
default_access: "nosetter.camelcase-underscore"entity Customer,
     
        identity "Id",
generator: "native"
       
        property Name,         
column:   "CustomerName",
type:     "String(12)",          
nullable: false

property DateJoined,

property Address,
type: "String(200)"

set _orders,
access: "field",
manyToMany Order,
table: Orders,
pk_column: "customer_id",
fk_column: "order_id",
inverse: true

entity Order,
table: Orders

Note that there isn't a ton of extra fluff, it's meant to be light-weight and easy to write.  Additionally you could set defaults at the top (like default_access) so that you can avoid typing it all over your mappings.

Ayende added the notion of doing this:

for type in assembly.GetTypes():
continue if type.Namespace != "My.Model"
entity type.Name, type.Namespace:
idenity "id"

for prop in type.GetProperties():
property prop.Name

You get the idea.

There could be a number of benefits of doing it like this.  First, you can compile it, so you can get syntax errors notified.  If you use the BooExplorer I'm pretty sure you'd get intellisense for this.  I could also see plugging this into a model validator that would reflect over the model and make sure that all of the properties and access strategies will work with the mapping as defined.

Anyway, I have some reading up on DSL's to do... Ayende, that means I need you to write that book on DSLs with Boo :)  Can I have it next week?

Thoughts?  Suggestions?

Friday, October 26, 2007 4:36:19 PM (Central Standard Time, UTC-06:00)
Why Boo and not C#?
Friday, October 26, 2007 8:37:08 PM (Central Standard Time, UTC-06:00)
Well the whole point is to reduce the noise and friction with XML... I can get some of the way there with c#, but Boo will allow me to leverage some of the more flexible features of the language to avoid so many .'s and ()'s.

It would be a good start though, I can tinker around with it.
Saturday, October 27, 2007 4:16:49 PM (Central Standard Time, UTC-06:00)
cool beans bra'
keep pushing it man, i hate xml.

-d
Sunday, October 28, 2007 3:08:21 PM (Central Standard Time, UTC-06:00)
I'd like to take advantage of having inheritance available to eliminate some noise requied by doing XML mapping; namely identity mappings and common fields like audit fields and so on. With Boo you could have a BaseMapping class that all other mapping classes inherit from and reduce a ton of stuff in mappings and different global defaults (ie, default-lazy or default-access strategies).

Plus, it must be 'boobernate'. Sorry :)
Monday, October 29, 2007 10:57:19 AM (Central Standard Time, UTC-06:00)
I say forget Boo...man up and write your own language from scratch. Just kidding! I've been playing around with ANTLR these days and figure it would be something you would get into (disclaimer: I'm using a lot of Boo myself these days).
Wednesday, October 31, 2007 11:27:40 AM (Central Standard Time, UTC-06:00)
Hey,good idea.

Another feature could be the option of avoid the hardcoding strings at the DSL, in order to prevent errors (very presents at xml), for example "field","nosetter.camelcase-underscore" could be replace by enums. Can be implemented too, classes with public strings fields with the value for the tag, to avoid the enums.

Regards.
Comments are closed.
Remortgages - Renegade motorhomes - Loan - Phoenix Pools