Ayende review of S#arp Lite

333 views
Skip to first unread message

Joe

unread,
Mar 7, 2012, 2:27:42 PM3/7/12
to S#arp Lite
I noticed Ayende had a series of reviews on S#arp Lite.

http://ayende.com/blog/

Can anyone comment on his criticisms? It would be nice to get a
balanced view from some people here. As a beginner some of the stuff
is hard to follow for me. Like his comment on repositories.

Billy McCafferty

unread,
Mar 7, 2012, 3:50:02 PM3/7/12
to S#arp Lite
I was wondering when this would come up. ;)

Here's my quick response: use what works for you and your team. If
you feel that S#arp Lite fits your project's needs and team's
preferences for development, then give it a try on a pilot project.
If it doesn't fit or feels awkward for the team, then don't use it.

Ayende brought up many points which could be argued either way as
being valid.

Here's a good point that Ayende brought up... The MyProject.Tasks/
BaseEntityCudTasks.cs class was added to make it trivially simple to
support the back end of CRUD for very simple objects. But to that
point, the BaseEntityCudTasks.cs class itself is quite complicated in
order to provide generic use capabilities in a number of scenarios.
If you're doing CRUD on such simple objects, perhaps
BaseEntityCudTasks.cs could be dropped in favor of having the
controllers communicate directly with NHibernate for managing the
persistence of very simple objects. But the flipside of this is that
now you've broken separation of concerns between your application
layers and NHibernate and you'll end up with a lot of duplicated CRUD
logic in your controllers. Accordingly, I still feel that
BaseEntityCudTasks.cs carries its weight; with that said, I did not
put it into the SharpLite libraries themselves as I wanted to give
teams the ability to drop it in favor of another approach.

That goes for much of what's in S#arp Lite and Ayende's criticisms.
S#arp Lite, while providing architectural structure to the overall
project, does not force many aspects of implementation. Accordingly,
if you disagree with how an example is implemented in the sample code,
you can work together as a team to decide what is the appropriate
implementation for the various layers of your project. These are
discussions that should take place regardless of the framework being
leveraged.

Here's a point that I disagree with... Ayende suggests having layers
communicate directly with NHibernate, suggesting that NHibernate
provides enough of an abstraction from low-level data access that
there's no need to separate it further. I disagree with this stance.
I believe that a clean separation of concerns needs to be placed
between the application layers (controllers, application-services/
tasks, and domain) and the data access mechanism. S#arp Lite
introduces this separation by including a very light weight
IRepository<YourObject> which exposes Get, SaveOrUpdate, Delete, and
GetAll (which returns IQueryable). The benefits for this include the
following:

* All layers outside of the data-access layer are isolated from any
changes which occur in NHibernate versions. For example, if
NHibernate changes the way it deals with transactions and sessions,
only the data-access layer will likely need to be modified.

* All layers which interact with IRepository are truly data-access
agnostic. For example, you could switch out NHibernate with Entity
Framework and only the data-access layer would need be switched out.
While you would likely never do this after you've begun a project, the
approach gives S#arp Lite the ability to support a wide variety of
data access mechanisms beyond NHibernate. (And now that Entity
Framework is finally starting to look viable, it's nice to have this
flexibility.)

* Along the lines of data-access agnosticism, working with the
IQueryable results of IRepository<>.GetAll allows you to write in pure
LINQ C# for all of your querying needs. This makes it easier for new
developers to understand and maintain the code even if they don't know
NHibernate. Yes, you could talk directly to NHibernate to get
IQueryable, but I don't see the need to introduce dependencies to the
concrete data-access mechanism to do so.

* Introducing IRepository<> as an interface to the underlying data-
access mechanism also makes it trivially simple to unit test your
logic without requiring your database and data-access code to be in
place. Indeed, it's simple to stub or mock IRepository<> in your unit
tests without worrying anything about the data-access mechanism
itself; e.g., NHibernate.

Don't get me wrong, I love NHibernate and have no immediate plans to
go towards an alternative data-access mechanism. With that said, I
feel strongly that a clean separation of concerns should be put into
projects between logic layers and "data provider" layers. Along these
lines, I always wrap web services with an interface so that business
logic communicates via the interface instead of the concrete service.
This allows the logic which consumes the service to be cleanly
separated from the service, to be easily tested in isolation of the
service, and to be developed even before the web service is available
(since only the service's interface needs to be agreed upon).

I have other rebuttals, but really it comes down to this: if it fits
the needs of your team and project, use it. If it doesn't, then
don't. ;)

Billy McCafferty

Patrick

unread,
Mar 12, 2012, 1:58:50 PM3/12/12
to sharp...@googlegroups.com

I agree with pretty much everything Billy said but if you are like I was when I started using Sharp Lite, it is still a little confusing.  The architecture probably isn’t appropriate for every project and it is up to the team to determine if it is a good fit, but I knew so little about the architecture or even the technologies it used that it was hard to evaluate whether or not it was appropriate.  My team was coming from the world of classic ASP and didn't really have any experience with nHibernate, MVC, Dependency Injection, or even a good layered architecture.  I've been working on a project using Sharp Lite for a couple of months now though so I'll share my thoughts.

For us, the architecture has been invaluable, primarily because it has allowed us to follow a well thought out pattern and achieve success, while slowly learning about all the technologies used (e.g. nHibernate).  I think we would have had a lot more trouble starting this from scratch.  After using it for a while, I feel pretty confident with most of the techniques and libraries being used, but the architecture allowed me to ease my way into it.

I do agree with Ayende that following the original store example seems to encourage 'walking' the domain model.  This is basically accessing sub-properties of the model that are lazy-loaded, so they cause a call to the database which leads to the n+1 problem Ayende talked about.  The latest CaTS example and Greenfield documentation indicate that a solution will be given to this problem, but I don't think it is there yet.  I'm guessing some sort of ViewModel/Dto that has these items pre-loaded but I'm not sure.  My current application is issuing quite a few calls to the DB but in my situation it is okay.  We have a small group of users and the DB is on the same server as the app so I'm willing to hold off and fix it when it becomes an actual issue.

Ayende's other primary criticism is the abstraction of the data access; I think Billy covered that pretty well so I won't go over it again.  I appreciate having the nHibernate particulars well confined and think it does make things pretty clean and I definitely wouldn't want to shove a bunch of that code in the controllers.  In fact, I'd be tempted to move more of the data access into the tasks and use ViewModels exclusively in the controllers.  This would allow me to only pass the data necessary or eager load more of the data.

In any case, I only have one real disagreement with Billy and that is about the maturity of the nHibernate LINQ provider.  The documentation and sample code say that you should rarely have to move beyond the LINQ provider (e.g. Query<>, HQL, custom stored procedures) but I have had to do just that in multiple spots.  I'm even using the unreleased nHibernate 3.3 because it fixes some issues I'd consider pretty basic, like multistep joins:
https://nhibernate.jira.com/browse/NH-2905
This has also stopped me from solving the lazy-loading issue, since it requires nHibernate specific calls and I haven't figured out how to do that without making the higher levels dependent on nHibernate.  Hopefully Billy will come through with something great (or let me know what I'm missing).

Hopefully this helps.  If you were planning on using some of the technologies used by Sharp Lite (nHibernate, DI, etc.) I don't think you can create too much of a mess by trying it.  You can always modify the parts you don't like after getting some experience under your belt.  If you have any more specific questions, I'd be happy to answer.
-Patrick

Billy McCafferty

unread,
Mar 12, 2012, 2:03:38 PM3/12/12
to S#arp Lite
Patrick,

Thanks for the candid feedback; it's great to hear feedback concerning
its use in the real-world. I could give more of my opinion as well,
but I may be *slightly* biased.

(Instead of hijacking this one, I'm going to respond to your challenge
of accommodating NHibernate-specific calls in a new thread.)

Billy McCafferty

Andrey Kozhyn

unread,
Mar 12, 2012, 2:18:09 PM3/12/12
to sharp...@googlegroups.com
I've had some expirience in abstracting away fetching calls with LINQ to NHibernate. You can see example here.
Maybe it should be included in project template?

2012/3/12 Billy McCafferty <google...@emccafferty.com>

Patrick

unread,
Mar 14, 2012, 9:59:39 PM3/14/12
to sharp...@googlegroups.com
Thanks for the link SlyNet.  I will probably end up doing something like that to allow our pages to selectively eager-load data.

-Patrick


On Monday, March 12, 2012 1:18:09 PM UTC-5, SlyNet wrote:
I've had some expirience in abstracting away fetching calls with LINQ to NHibernate. You can see example here.
Maybe it should be included in project template?

2012/3/12 Billy McCafferty
Patrick,
2012/3/12 Billy McCafferty
Patrick,
Reply all
Reply to author
Forward
0 new messages