These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Application Design best practices with NHibernate
PostPosted: Wed Jan 18, 2006 7:32 am 
Beginner
Beginner

Joined: Tue Jan 17, 2006 12:55 pm
Posts: 49
I am new to NHibernate and am currently designing a new application with a moderately complex domain model which is only going to grow bigger.

I was considering the standard layered architecture with NHibernate straddling the Data Access and business layer and essentially embedding itself into the domain entities.

Over this I want to put a Sevice Layer which implements the business logic components and these are the objects which will need to run the object queries to implement the logic.

A major part of the application is to also be exposed via Web Services, hence the Service Layer.

Finally, I want to seperate the UI and enforce a rule that the UI should not implement any business logic but should delegate this to the Service Layer.

One way I thought of doing this was by passing Data Transfer Objects between the sevice layer and the UI, but I don't want the translation to be an expensive process, nor do I want to have to hand code this everywhere. The other alternative is to allow the UI access to these entities, but I think that could encourage the building of business logic into the UI layer.

Questions:
1)Does this design sound reasonable?
2)Has anyone any comments on this, born out of experience?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 19, 2006 7:55 am 
Newbie

Joined: Thu Jun 02, 2005 6:00 am
Posts: 12
Location: Ostrava, Czech Republic
Are you planning Winforms client or are you going to stick with web?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 19, 2006 8:04 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
I too would love to know the answers to your questions.

Surely there must be a couple of well designed open source applications out there built on NHibernate! I'd love to see some real world examples and bypass learning a few lessons the hard way...


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 19, 2006 4:44 pm 
Beginner
Beginner

Joined: Fri Nov 11, 2005 1:04 pm
Posts: 22
First I would highly recommend that you pick up Martin Fowler's book Patterns of Enterprise Application Architecture. It gives a great overview of the various options with multi-tiered development.

Hibernate helps you implement a rich Domain Model by implementing the Data Mapper and Unit of Work patterns.

Fowler goes on to say that the real power of the Domain Model is that it can be used to implement complex business logic. He also admits that it takes a certain quantum leap in thinking to fully appreciate the power of the Domain Model.

Your Business Logic Layer should not know about NHibernate except when your Domain Model implements the Business Logic but even then there are ways to abstract away the data layer.

YOUR BUSINESS LOGIC LAYER SHOULD KNOW ABOUT NHIBERNATE. It's worth repeating.

Your UI definitely should not know about nhibernate...it shouldn't even know that the data layer exists.

Your UI/Presentation Logic should hit the Business Logic Layer and Domain Layer. (Some people advocate a separate set of DTOs for the UI, I say that is over kill.) In the case of business logic implemented in your Domain Layer, use a package facade and implement the Domain Layer business functions with package visible functions. This expresses your intent that the UI shouldn't call them directly.

I hope what I suggested makes sense. If you have any further questions feel free to PM me.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 21, 2006 10:33 am 
Beginner
Beginner

Joined: Tue Jan 17, 2006 12:55 pm
Posts: 49
I have read and implemented the architecture in Martin Fowler's book.

You say
Quote:
"Your Business Logic Layer should not know about NHibernate except when your Domain Model implements the Business Logic but even then there are ways to abstract away the data layer.

YOUR BUSINESS LOGIC LAYER SHOULD KNOW ABOUT NHIBERNATE. It's worth repeating."


That's what I was asking.. how do you do this? How on earth you can keep NHibernate out of the business logic layer? Typical usage is to create objects, manipulate them then persist back to the database. Surely, to this end Business Logic Components have NHibernate embedded in them and you use these components to tell NHibernate what to do with your Objects and when to go to the database.

So how do you abstract away from NHibernate in a useful and meaningful manner?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 22, 2006 10:16 pm 
Regular
Regular

Joined: Mon May 16, 2005 1:35 am
Posts: 67
Persistence is an orthogonal concern to the logic found in the domain layer. As such, your domain model should not contain any properties or methods of a persistence concern (such as save, load, etc).

You should provide an abstraction layer to encapsulate your NHibernate calls. You can use the DAO or Repository patterns for this.

You can then use this layer directly from your UI layer, or if you wish to abstract this out further (for example if you envisage you will access the system via more than one UI in the future), then you could add a Service Facade layer, which is also a useful place to handle cross-cutting concerns such as security, database transactions and logging. The Service Facade layer then acts as the boundary to your system.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 7:23 am 
Beginner
Beginner

Joined: Tue Jan 17, 2006 12:55 pm
Posts: 49
OK.. I can create a Repository for any data access. The Repository will essentially provide a wrapper over the OR Mapper Layer. I will create an abstract Repository class and create my own concrete Repositories.

Now, the only problem is that I now have to create a new Criteria system or Object Query Language so that I can totally hide any implementation details from the Service Layer! This seems a major task to me! Any way, I'm off to do some more research...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 1:10 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
We "cheated" by creating "generic" Query and QueryParameters classes. So far, the query class takes only text queries, not criteria-based ones. We have a property for the "query language", HQL being one option (the only one we support at this point).

So, query requests currently are in HQL, but the query classes aren't HQL-specific. We hope to clean this up by creating our own "named query" registry, so that code that executes queries won't know that a given query is implemented as HQL or whatever else.

We're not looking forward to providing an entire abstraction layer over the entire NHibernate criteria API, though ...


Top
 Profile  
 
 Post subject: Business logic in entity & service layer drives Persiste
PostPosted: Tue Jan 24, 2006 11:43 am 
Newbie

Joined: Mon Jan 23, 2006 11:44 pm
Posts: 15
Location: New Jersey, US
Hi dircums,

Maybe my concept of layer is not the same as the correct ones. Business Logic layer, to me, is not a flat layer on top persistence logic and drive it. What I found that works for me is treat buisness logic as a subsystem that rely on nobody else. To me, business logic layer is entity class with all possible logic in them.

My service layer, invoked by function calls from UI layer, drives all actions in the system. For example:

Code:
class AccountService
{
....
public void UpdateBillingContact(int accountId, string name, string address)
{
//Service layer get hold of business layer by call persistence layer
Account account = _da.GetAccount(accountId);

//Apply business logic. [b]Here is the trick.[/b] Lets say that a business rule says
//if an account's contact is updated and if the account was closed for solicitation
//we will turn the account on, we will put such logic in the Contact class instead of the AccountService class.
account.Contact.Name = name;
account.Contact.Address = address;

//_da.CurrentSession.Save(account) in a transaction
}


Hope this helps
Hongze[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 6:11 pm 
Beginner
Beginner

Joined: Tue Dec 20, 2005 9:40 pm
Posts: 20
I have a couple questions regarding using a Repository with NHibernate. One, Evans says that a Repository shouldn't be given the responsibility for handling transactions. Rather, the client will be better suited to know the transaction boundary. In most of the example apps I see transactional stuff within Repository methods like Save(), which I presume to be wrong (at least according to Evans.) How do other's handle this?

My initial thought is something like this:

MyReopsitory r = new MyRepository();
Transaction t = r.BeginTransaction();
r.Save(someObject);
t.commit();

Some problems I see with this are:

1. I have to duplicate try... catch all over the place in my client code if I want to rollback the transaction if something goes wrong. It is nice to have it all in the Save() method.

2. I am not explicitly attaching the transaction to the session which is saving. Of course, since I'm using a singleton to get the session I know this is the case, but I'd feel more comfortable if I actually saw it done in the code.

I suppose one solution for issue 1 is to have two Save methods:

Save()
SaveAndCommit()

SaveAndCommit would include all transactional stuff within it and could be used whenever I had a simple Save which didn't have to include anything else in the transaction.

Anyway, thoughts on this? How do others deal with this?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 10:11 pm 
Regular
Regular

Joined: Mon May 16, 2005 1:35 am
Posts: 67
We have found the ideal scenario is to implement a transaction enrolment mechanism. Each repository class should be able to operate correctly on its own, but the client should also have control over the database transaction.

This also extends to services. If you have a service that takes advantage of another service within the service layer, then you would want the child service to work within the transaction defined by the parent service.

We use a pattern similar to the TransactionScope class in .NET 2.0. The scope object (which we call PersistenceScope) encapsulates an NHibernate session with automatic transaction enrolment. The NH session is transparently stored in the call context (thread local storage) and is thus available from anywhere.

So from anywhere in the system where a transaction boundary needs to be defined:

using( PersistenceScope scope = new PersistenceScope( TransactionOption.Required )
{
// Do your work here...
IQuery query = scope.Session.GetNamedQuery( "myQuery" );
...

// Okay to commit
scope.IsConsistent = true;
}

This kind of structure is found within many of our service layer methods and repository methods.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 1:53 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Baggins, I looked briefly at the new TransactionScope class in .NET 2.0 and it (and your PersistenceScope pattern) appear to be a very elegant solution. However, implementing something similar to TransactionScope doesn't appear to be trivial. Can you describe this pattern more thoroughly, so that others can implement it also?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 3:02 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Baggins, I looked briefly at the new TransactionScope class in .NET 2.0 and it (and your PersistenceScope pattern) appear to be a very elegant solution. However, implementing something similar to TransactionScope doesn't appear to be trivial. Can you describe this pattern more thoroughly, so that others can implement it also?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 6:45 pm 
Expert
Expert

Joined: Tue Aug 23, 2005 5:52 am
Posts: 335
I'd like to second that request - the solution I've been using is not nearly so elegant.

Symon.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 4:31 am 
Regular
Regular

Joined: Tue Mar 15, 2005 12:38 pm
Posts: 73
Location: Bucharest
If I'm not mistaking, such an implementation is done in Active Record of CastleProject:

http://www.castleproject.org/index.php/Main_Page

There are lots of other interesting stuff there..


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.