Ayende @ Rahien

It's a girl

Taking a look at S#arp Lite–final thoughts

This is a review of the S#arp Lite project, the version from Nov 4, 2011.

This project is significantly better than the S#arp Arch project that I reviewed a while ago, but that doesn’t mean that it is good. There is a lot to like, but frankly, the insistence to again abstract the data access behind complex base classes and repositories makes things much harder in the longer run.

If you are writing an application and you find yourself writing abstractions on top of CUD operations, stop, you are doing it wrong.

I quite like S#arp approach for querying, though. You expose things directly, and if it is ugly, you just wrap it in a dedicated query object. That is how you should be handling things.

Finally, whenever possible, push things to the infrastructure, it is usually pretty good and that is the right level of handling things like persistence, validation, etc. And no, you don’t have to write that, it is already there.

A lot of the code in the sample project was simply to manage persistence and validation (in fact, there was an entire project for that) that could be safely deleted in favor of:

public class ValidationListener : NHibernate.Event.IPreUpdateEventListener, NHibernate.Event.IPreInsertEventListener
{
    public bool OnPreUpdate(PreUpdateEvent @event)
    {
        if (!DataAnnotationsValidator.TryValidate(@event.Entity)) 
            throw new InvalidOperationException("Updated entity is in an invalid state");

        return false;
    }

    public bool OnPreInsert(PreInsertEvent @event)
    {
        if (!DataAnnotationsValidator.TryValidate(@event.Entity))
            throw new InvalidOperationException("Updated entity is in an invalid state");

        return false;
    }
}

Register that with NHibernate, and it will do that validation work for you, for example. Don’t try too hard, it should be simple, if it ain’t, you are either doing something very strange or you are doing it wrong, and I am willing to bet on the later.

To be clear, the problems that I had with the codebase were mostly with regards to the data access portions. I didn’t have any issues with the rest of the architecture.

Comments

Wayne M
03/08/2012 01:06 PM by
Wayne M

I find it very interesting that so many developers still abstract away the CRUD functionality even when they don't have to.

I would still like to see more examples/discussion about the "query object" pattern, as I can't seem to find much in the way of concrete samples and it seems like a very good idea to start using.

nick
03/08/2012 01:41 PM by
nick

@Wayen M I believe it is called the specification pattern

nick
03/08/2012 01:42 PM by
nick

Maybe it would have been good to elaborate on a few more of the good points then Ayende?

Moses Fetters
03/08/2012 03:50 PM by
Moses Fetters

I would love to see a discussion about the "query object" pattern and the pros and cons of using it.

I have read Fabio's take on it here http://fabiomaulo.blogspot.com/2010/07/enhanced-query-object.html

magellings
03/08/2012 05:02 PM by
magellings

When's Ayende's framework (or best practice example solution) coming? :) Something that brings together all of what you've been critiquing lately into a concrete example of the "right way" to do things. I'm sure a lot of developers would be inspired by it. It would be a great service to the community and serve the same purpose the S#arp authors are providing. Not just critiquing but a concrete example and valid attempt to make the lives of us developers easier.

Dmitry
03/08/2012 05:14 PM by
Dmitry

@ayende,

Did you find any benefits of using this framework? Querying is something that can easily abstracted using straight NHibernate.

John Farrell
03/08/2012 05:26 PM by
John Farrell

@magelings: https://github.com/ayende

Robert O'Donnell
03/08/2012 07:31 PM by
Robert O'Donnell

I wonder if rather than using a "framework" perhaps having a scaffolding that uses a bunch of libraries would be a better way to go...

Peter
03/08/2012 08:26 PM by
Peter

magelings, he said specifically raccoonblog was built recently with these principles, so go look for that.

Bystrik Jurina
03/08/2012 09:48 PM by
Bystrik Jurina

Your ValidationListener works nice in theory but what about integration in Asp.Net MVC validation pipeline? I also don't like some aspects of SharpArch. For example I don't like Tasks and I prefer Fluent Validation instead validation attributes, but I must defend the Repository pattern. NHibernate Session exposes at least 50 public properties and methods. WTF??? Session has stuff like Connection, Dispose(), ActiveEntityMode and so on. Such API should be used in Controller? I think generic Repository exposing IQueriable, Get adn Remove methods is very cheap pattern and it can be easily extended if neccessary.

magellings
03/08/2012 10:03 PM by
magellings

raccoonblog uses ravendb...a document database. I was leaning more towards a best practice NHibernate example...

Christopher Wright
03/09/2012 01:24 AM by
Christopher Wright

I quite like having validation wired into your ORM. Like DB constraints but usable. I'll keep that in mind next time I'm using NHibernate (though I presume Hibernate has something similar).

Granted, you need to have some nicer stuff in place in case of bad input, but that style of validation has the advantage of being all-encompassing.

Get Real
03/09/2012 02:14 AM by
Get Real

@magellings

When's Ayende's framework (or best practice example solution) coming?

I hate to say it, but you just inadvertently outed yourself as a newbie. Dont worry though, it happens weekly, if not daily.

This guy is never going to do this. Remember MADCO, or MATCO, or whatever ?? Heck it's been so long I bet he even forgot the name. I few rough screen drawings and he lost interest.

It's much easier to dissect and destroy instead of laying your own footprints in the concrete - lest they be dissected by someone else.

Yawn, smack, smack, Ayende, arent you bored by reviewing other peoples work by now?

Tien Do
03/09/2012 04:24 AM by
Tien Do

I don't know why people keep inventing these frameworks, did they just create these projects for their work and then made them open source later?

@Ayende: They asked you for a review e.g. this project, Ntier architecture from MS Spain etc., did you get their feedback later since there were many negative points?

P.S: I can't login by Goolge, the error is No OpenID endpoint found.

Shaddix
03/09/2012 07:25 AM by
Shaddix

Ayende, I'm quite interested in using validation that way, as well as in another point from your previous post:

Extend the model binder so it would load the entity from NHibernate and bind to that instance directly.

I just opened up RacoonBlog to take a look at an example of those, but there's still

public ActionResult Add(UserInput input) { if (!ModelState.IsValid) return View("Edit", input); var user = new User(); input.MapPropertiesToInstance(user); RavenSession.Store(user); return RedirectToAction("Index"); } Which both uses validation right inside an action and AutoMapper to map user input to db-entity. And that's what I'm used to in my own projects, because view/input models usually differs at least a bit from what I have in DB. Could you please suggest an oss-example where principles that you've mentioned are used?

Shaddix
03/09/2012 07:26 AM by
Shaddix

Sorry for ugly code formatting, it seems parser ate my line-breaks.

Bystrik Jurina
03/09/2012 04:26 PM by
Bystrik Jurina

I think Ayendes post about SharpArch is harmfull. It creates sense that SharpArch is bad framework, but that is far from truth. Maybe it's not perfect, but it's still better than 90% of handroll solutions. And for example RacoonBlog has also code smells. Some controller methods are really fat. Nothing is perfect...

Lev Gorodinski
03/12/2012 03:40 AM by
Lev Gorodinski

"Finally, whenever possible, push things to the infrastructure, it is usually pretty good and that is the right level of handling things like persistence, validation, etc."

I agree. However, one must be weary of creating needless abstractions in this way, as you caution. In fact I believe the repository abstraction and in particular the overly abstract LINQ specification pattern based repository results from an attempt to push things to infrastructure by detecting patterns in data access. Just like validation injected directly into the ORM is a result of the observation that the ORM persists entities, entities must be validated before persistence, so lets inject validation.

dotnetchris
03/15/2012 08:26 PM by
dotnetchris

If they want to separate responsibilities like this, YOU HAVE TO use the DetachedCriteria construct. This would allow you to solve that need to include the child items to avoid the N+1 problem.

Billy McCafferty
03/19/2012 08:03 PM by
Billy McCafferty

@dotnetchris, actually, you don't have to use the DetachedCriteria. In fact, you can still use NHibernate directly if you find LINQ to NHibernate to be inadequate for any specific scenarios.

This provides as good as any opportunity to provide a couple of links to specifically address dotnetchris' concern, as well as discussion concerning my response to Ayende's series of posts on S#arp Lite:

  • Encapsulating NHibernate-specific calls within a custom repository - http://groups.google.com/group/sharp-lite/browse_thread/thread/c653325f5f61e46c

  • Why have a task layer? - http://groups.google.com/group/sharp-lite/browse_thread/thread/692c4baf1454cc

  • A direct response to the Ayende's review - http://groups.google.com/group/sharp-lite/browse_thread/thread/77a4ed0b857427b0

When it comes down to it; if S#arp Lite jives with the way you/your-team wants to develop, then consider using it. If it doesn't, then don't. ;)

Rovanpiera
03/21/2012 05:07 PM by
Rovanpiera

What is the difference between repositories and queries? As I understand they are both use NHibernate in this sample. So they are both abstraction over abstraction.

Comments have been closed on this topic.