Monday, July 27, 2009

Entity Framework N-Tier Anti-Patterns and DevForce

Danny Simmons, dev manager for Microsoft’s Entity Framework, wrote an article published in the June MSDN Magazine called “Entity Framework: Anti-Patterns To Avoid In N-Tier Applications”. It’s a wonderful place to discover some of the pitfalls of developing your own n-Tier infrastructure. You will learn that such development won’t come cheap. My take-away: “don’t be foolish; don’t write this yourself.” Of course fools abound and you’re welcome to join them.

I arrive at the same conclusion from reading Julie Lerman’s essential book on Programming Entity Framework.

Danny could have shouted: “Don’t do that!”  It would just piss you off. Instead, he begins as if this were something you might do and he’s only going to guide you in doing it: “I will try to set a foundation on which you can build for success in this part of your applications”. Yeah, right.

I encourage you to read his article. Look at the six “anti-patterns” he identifies – the shortcuts that you are likely to take in your naive attempt. See for yourself not only the deep and dangerous traps … but also the sheer difficulty and complexity of avoiding those traps.

Go ahead, read it. I’ll be here when you get back.

So what do you do now? You have an application that crosses tiers. I know you do. If it’s a Silverlight application, you know you do.

My answer … wait for it … is DevForce. We solved this one seven years ago and have been enriching our product over many years. Try it and you will be relieved of all of Danny’s anti-patterns (and all of the gyrations described by Julie too). I’m not suggesting it addresses every n-Tier problem; nothing does. But you won’t succumb to these traps and you won’t waste your time – or your employer’s time – fighting your way through the cross-tier application jungle.

I cannot close without just a bit of criticism. I can’t give all of Danny’s anti-patterns equal weight and I would add some different ones of my own. In one case, I just think he’s wrong. 

Under the heading “Two Tiers Pretending to be Three”, he seems to say that it is imprudent to attempt cross-tier queries and updates.  He is literally saying that he thinks it is improper for the Entity Framework to do so but, in the context of the rest of the article, you are lead to believe that is imprudent for you to do so.

It is certainly difficult. But we still have to do it in some fashion or another. That’s why there is an ADO.NET Data Services and a RIA Services. These technologies, in their somewhat crippled way, facilitate client side queries and updates. DevForce does an even better job. My point is that they fill a need and they are capable of doing so without wrecking your application.

Danny distorts the original question. He mutates from “Why can't you make the Entity Framework serialize queries across tiers?” to “Why not just expose the database directly?” This is not what people are asking for. They want to be able to compose a query on the client – compose it in entity terms, not database terms – and send that query over the wire in the full expectation that they will get entities back.

Of course he is right to caution against “introducing a mid-tier that is simply a thin proxy for the database”? But this warning, like the others, is just more of the same advice: do a good job of writing the middle-tier – don’t hack it together – and it’s going to be hard. Point taken. Use DevForce … or RIA Services or CSLA if you prefer.

Danny tries to predicate his argument on Fowler’s “First Law of Distributed Object”. That won’t fly. Worse, Danny, like many others, misrepresents Fowler’s “law”. Let’s clear that up.

The short statement of the law is “Don’t distribute your objects”. What the heck does that mean? You’ll have to look at the chapter in Patterns of Enterprise Architecture (highly recommended) … or read the article he wrote in Dr. Dobbs that covers the same ground. You will see that it is a jeremiad against calling methods on a remote object.

Fine. I get it. Don’t call Employee.CalculateSalary() and have that be a cross-tier call. Fowler is inveighing against a design which would present the fiction of an object instance that is half on one tier and half on another. It is distributed in the sense that it has one foot on the server and another on the client. Don’t do that. I agree.

But we are interested in an entirely different notion of “distributed objects”. The notion I have in mind is more akin to “mobile objects”. 

When we query across tiers we intend to retrieve persistent state and reconstitute an object with that state on the client. That object can have behavior to go with the state; it should have behavior.

Make no mistake. We are executing locally on the client when we invoke CalculateSalary() on it; there is no ambiguity about this at all. Now it also may be (as it is in DevForce and RIA Services and CSLA) that the same type is available on the middle tier; that means we can reconstitute an instance with persistent state there – on the server – and invoke Calculate Salary() on it there – on the server. There is no ambiguity in this case either. The instance exists on a single tier and the method executes on the same tier as the instance. No instance straddles tiers … or even pretends to straddle tiers. No instance violates Fowler’s “law”.

This is what we expect from a cross-tier query. It is a perfectly reasonable expectation. Danny has announced that Entity Framework will not support that kind of query. That’s ok too. That’s a choice. Let’s not dress it up into some kind of principle.

My rant is over. Please read what Danny has to say … in this article and elsewhere. You will always be glad that you did.

No comments: