And another personal viewpoint - in our circumstances (writing WebAPI-based single-page apps using AngularJS), my preference is for an anaemic domain model with very little business logic beyond basic validation. The 'natural' pattern for me is to split things as follows:
- WebAPI controllers: Form the system's public API, and get reusuable 'services' injected by an IoC container (including a UnitOfWork, NHibernate ISession[Factory], business rule implementations, etc) - WebAPI models: Contain logic to synchronize their state with the matching entity(s) using the services supplied to the controller through IoC. - UnitOfWork component: Manages the NHibernate ISession / Transaction, provides context services for error handling Like RP & Oskar, I prefer to keep the domain entities blissfully ignorant of NHibernate's existence; however, I completely loathe the "repository exposing IQueryable" which IMO is an abstraction leak - like Gunnar, I regard it as being completely out of the question. Frankly, as far as I'm concerned, the domain entities are merely a representation of data in the same way as the WebAPI models, AutoMapper DTO's, JSON-on-the-wire and JavaScript classes; very anti-OO, I know, but then I've never fully subscribed to OO-philosophy either as I think that whilst there are a lot of 'good concepts' in it they don't apply to every situation and in some cases are positively harmful. The really big issue is that no matter how much we'd like to pretend differently, under most circumstances we pass _data representations_ over wires, not behaviour; the OO 'data & behaviour together' philosophy simply doesn't work for e.g. bytes-in-a-file (SQL DB!) --> bytes-in-RAM (domain entity) or different-bytes-in-different-RAM (some other process, possibly on a different machine using a different language and even a different CPU instruction set). CORBA was the closest anyone came to achieving the OO dream, and we all know how well that worked out!! /Pete From: [email protected] [mailto:[email protected]] On Behalf Of Ricardo Peres Sent: 30 September 2013 10:13 To: [email protected] Subject: Re: [nhusers] Design pattern - where to put business logic I agree with Oskar: I never have references to NHibernate in my domain (and I will soon get rid of Iesi.Collections as well, when NHibernate 4 is released in NuGet). Another totally different thing is having business methods and calculated properties, which is OK, provided they respect the Law of Demeter and only touch public properties and methods of the class' own properties, otherwise you end up with an anemic model. Just my 5 cents. RP On Sunday, September 29, 2013 6:01:31 PM UTC+1, Gunnar Liljas wrote: And just to add to the confusion, I disagree. I've rarely found it to be of any significant advantage to make my domain model unaware of the persistence mechanism, and quite often it's a major, major disadvantage. A repository which is queryable in any other way than using explicit methods or query objects (in other words, a repository exposing IQueryable) is completely out of the question. Passing ISession into the business methods may not be necessary (the session can be contextual), but there's nothing really wrong with. /G 2013/9/29 Angel Java Lopez <[email protected] <javascript:> > +1 On Sun, Sep 29, 2013 at 11:01 AM, Oskar Berggren <[email protected] <javascript:> > wrote: To give short and quick answer: Ususally I would expect my domain model to be unaware oh NHibernate or any other persistence mechanism. Instead of passing the ISession, it's better to pass the required repository interfaces to a domain class, since the repository interfaces in my view are part of the domain model (but not the repository implementation). For logic that won't fit nicely inside a domain model class, I would normally use a domain service class to orchestrate the algorithm between the involved model classes. The repository implementation itself should not contain logic beyond that of simple store/retrieve/query (and for complex queries it might be better to use a query object). /Oskar 2013/9/28 mg <[email protected] <javascript:> > Hi, What is the proper place to put business some more complex business logic which requires access to other Models, not only the one on which the operation is being executed? Are there any open-source projects which uses a bit of business logic and could be a good example? To make myself clear: all the examples of business logic I've found are very simple ones, like class Person with calculated property FullName which is just a getter: FirstName + " " + LastName, or calculating Person's Age by theirs BirthDate field. Now I need some more complex logic, for example to calculate the Invoice amount based on today's PricingPlan model which is separate model. Where should I implement methods like this? Is the Repository pattern supposed to be place for this methods? Or is it OK to implement these methods in the class it is logically related to, just passing the ISession instance to the method, like so: class Invoice { // ... public void CalculatePrice(ISession dbSess) { var pricePlan = dbSess.Get<PricingPlan>(...); // } } I come from python/django background, and there's no such problem, since the db connection/session management is hidden away from user. Best regards MG -- You received this message because you are subscribed to the Google Groups "nhusers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <javascript:> . To post to this group, send email to [email protected] <javascript:> . Visit this group at http://groups.google.com/group/nhusers. For more options, visit https://groups.google.com/groups/opt_out. -- You received this message because you are subscribed to the Google Groups "nhusers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <javascript:> . To post to this group, send email to [email protected] <javascript:> . Visit this group at http://groups.google.com/group/nhusers. For more options, visit https://groups.google.com/groups/opt_out. -- You received this message because you are subscribed to the Google Groups "nhusers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected] <javascript:> . To post to this group, send email to [email protected] <javascript:> . Visit this group at http://groups.google.com/group/nhusers. For more options, visit https://groups.google.com/groups/opt_out. -- You received this message because you are subscribed to the Google Groups "nhusers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/nhusers. For more options, visit https://groups.google.com/groups/opt_out. -- You received this message because you are subscribed to the Google Groups "nhusers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/nhusers. For more options, visit https://groups.google.com/groups/opt_out.
