Friday, April 30, 2010

Context for Comparing DevForce, CSLA, and RIA Services

I recently posted on some important differences between DevForce and RIA Services. Someone posted a comment to the effect that DevForce and CSLA seem to be the same and invited me to comment.

I see the similarities between DevForce and RIA Services. I don’t think DevForce and CSLA are alike at all. Why would someone suggest that they are?

That got me thinking and lead to this post which reframes the question.

It first establishes what we have in common … and how to decide quickly if you should consider any of us … or none of us … for your application project.

Then it articulates fundamental criteria for comparing the three.

Important: These criteria are not evaluative. They are as neutral as I can make them. I feel pretty confident in that neutrality because, as I apply them to the three products, I can not tell which one of them is “better”. They help me organize my thoughts, not decide which one is “right.”

Let's start with the what we have in common.

DevForce, CSLA, and RIA Services target the same problem: building distributed business applications from end to end, server to client.

If you don't think you have this problem, none of us are right for you.

We offer .NET-only products. RIA Services is limited today to Silverlight applications; DevForce and CSLA support most .NET client technologies (I don't think any of us are ready for WP7 .. yet. CSLA may work on the CE; we do not). Your required server and client operating environments may make the choice for you.

We all have the same presumption of a relational database as the primary backing store. Sure we can also persist to other backing stores. But these alternatives appear in supporting roles if they appear at all. None of us are your best choice for building applications that primarily access data through messaging services or persist to one of the NoSql schema-less data stores.

We all attempt to solve your application problem within some flavor of "mobile business objects" paradigm. If you summarily reject a "mobile business object" solution on principle, none of us are right for you.

Finally, we are all framework products. We're not application generators. If you want to drag-and-drop your way to a finished product, we're not for you. If you reject 3rd party frameworks, we are not right for you either.

With me still? Because now we are ready to differentiate the three products.

You have looked at the problem and you've chosen to solve it by allocating some responsibilities to a framework, reserving others for yourself in the expectation that you will be writing custom application code.

Every framework is opinionated. Each says:

  • We will be responsible for these tasks (the A-list).

  • You will write custom code for these other tasks (the B-list).

  • Our architecture and recommend development practices pretty much prescribe that you will write your custom code in manner C.

You look at these opinions and ask yourself

  • Do I want the framework to do the things on the A-list?

  • Do I want to write code for the things on the B-list?

  • Do I want to develop in manner C?

  • How productive will I be if I adopt this framework?  How quickly can I write quality B-list code when I adopt manner C?

  • What items on the A-list do I really have to do myself? Can I take these particular tasks away from the framework with acceptable ease and still, in the main, be using the framework the way it was intended?

  • I wish some of the items on the B-list were handled by the framework. What will it take for me to write them myself or acquire them from someone else?

  • I don't care about some of the items on the A-list; do these items get in my way and if so, will that be a serious problem?

  • Do we have the skills and development culture to use this framework effectively? If not, can we and should we acquire those skills?

  • How do these factors collectively influence my development timeline? Do I have a deadline? If so can I reasonably expect to hit the deadline with the resources I have using this framework?

You will also consider some “non-functional” factors

  • Product quality and maturity
  • Access to source code
  • Support
  • Influence on roadmap and repairs
  • Product release schedule
  • Community (resources, training, etc.)
  • Company stability

I have conspicuously omitted one factor: license costs. CSLA and RIA Services have no license costs. DevForce does. Why doesn’t that matter?

It doesn’t matter because you’re building a custom application that you’ll be living with for years. A few thousand dollars of licensing fees are irrelevant … they are rounding error … compared to the application investment you’re about to make and the risks you are about to assume.

If this is not blindingly obvious to you, you shouldn’t be making this decision. You simply don’t have the requisite business acumen to make the right choice.

When you dissect the products according to these criteria – which you’ve refined and weighted to suit your business environment  and requirements – the differences among CSLA, DevForce, and RIA Services will stand out in sharp relief.  You will have a foundation for choosing among them.

I said the differences will be stark; I didn’t say that the choice will be easy. Even within the same organization people will weigh some differences more heavily than others.

You will at least have arranged matters so you can see more clearly what you’re arguing about.

Wednesday, April 28, 2010

DevForce Or RIA Services?

I’m thrilled RIA Services is out at last.

Developers who are familiar with Forms-over-Data, end-to-end, business application development at last have a Microsoft-sanctioned approach to building such applications in Silverlight.

They’re less inclined to roll-their own data management solution and more inclined to let someone else handle the plumbing.

That choice is not without problems. It’s unnerving to hand the keys over to a framework and say “you drive.” But let’s face it, your home-brew solution is just another framework too. It may be yours … which makes you feel all gnarly and in control. But it’s still a framework that someone is going to have to document, train, maintain, support, and grow … at the probable expense of delivering the end product demanded by the customer.

RIA Services has made it OK to delegate these challenging and time-wasting aspects of the application to a third party.

For me, the usual conversation has shifted from “Why do I need something like DevForce?” to “Why DevForce instead of  RIA Services?”

Here’s how someone put that question on the RIA Services Forum.

DevForce or WCF RIA Services? Both seem to do more or less the same data abstraction for Silverlight, but which would be the better route to go in the end? The price tag for me is the winner with WCF RIA services, but this is not always the right choice. Any thoughts?

Colin Blair, MVP and RIA Services aficionado, invited me to respond to that forum post. Which I was happy to do :-).

You could read it there. But I’ll spare you the trip and re-post my response here.

I have much more to add… and I’ll elaborate in the coming weeks and months. Meanwhile, it’s a start.

--------------

Yes, RIA Services and DevForce share a common perspective: end-to-end application development, programming against a rich entity model backed (typically) by relational data with validation, concurrency, security, change management, unit-of-work rolled in.

DevForce has been in commercial release since 2002 (long before Silverlight) so it's been dipped rather thoroughly in the acid bath of real world experience.

It supports both 2-tier and n-tier applications (a config change) and all the typical .NET client technologies: Windows Forms, WPF, Silverlight, ASP Web Forms, ASP MVC. You can write one code base and use it across all of them ... not that that is always a great idea. We have versions for .NET 2.0, 3.5 and 4.0.

Let's assume, however, that you are only interested in Silverlight and you don't care about product maturity, track record, or any of that.

If it seems that DevForce and RIA Services are similar ... that's intentional. We have a common perspective and we want DevForce to align with RIA Services APIs and techniques as much as possible ... so that it's easy to move between the two communities.

But DevForce and RIA Services are not clones. We do many things differently and offer capabilities beyond the RIA Services baseline.

Our customers often cite some of the following dozen DevForce differences as their reasons for choosing DevForce:

1) Same model on server and client. The code you write on the server is the same as the code on the client (unless and except where you don't want it to be). Open the Employee class on either side ... it's identical. The physical class file resides on one side (typically a server, full .NET project) and you have a Silverlight model assembly that links to that file. Compilation produces different assemblies (.NET and Silverlight) whose class names, structures, and logic are effectively the same.

2) No code generation magic.  We don't touch your code. We don't generate client code. No surprises.

3) Most DevForce applications use Entity Framework for Object Relational Mapping (ORM) and persistence operation (query, insert, update, delete).

DevForce generates its own (partial) classes from EF's EDMX using T4 templates; we don't need, use, or generate EF's own classes.

Our classes are serializable and designed to support RIA scenarios. We inscribe the UI-hint attributes (e.g., Display) and the obvious validation attributes (e.g., Required) into the generated classes. No separate metadata class files needed (keep reading)

4) You can override our code generation to introduce your own behaviors. You could take over the entire template but it's much easier to override one of the many code generation methods that target the moment of interest to you (e.g., property generation).

5) No service method pollution.  In RIA Services you have CRUD methods for each type in your model. There could be 400 methods in a 100 entity model. We don't generate CRUD methods; like WCF Data Services, we manage CRUD operations dynamically. Of course you CAN write arbitrary service methods if you wish. You can intercept any Query to inspect, limit, adjust the query. You can intercept any Save to inspect, reject, add/subtract/modify the entities in the change set, or perform arbitrary operations (custom logging and auditing).

6) Iterative Development: In demos, you build your model and you're done. In reality, you will add, remove, and rename your properties, entities, and the relationships among them. over the long course of your application's lifespan. Such adjustments are trivial with EF-backed models; update the EF model, compile, and run.

Ok ... maybe you should test too and you made these changes because you wanted to introduce new capabilities. The point is that you'll program to those business concerns; you won't be updating a domain service file and fixing up satellite, entity-related class files.

7) Client-side LINQ. DevForce supports client-side composition of any LINQ to Entities query, including projections of all kinds, projections into anonymous types, aggregations, grouping and ordering, includes, polymorphic queries (query on a base type). There is NO query you have to compose on the server in a "domain service" method. You don't add OrderBy clauses on server query methods. It is almost unheard of for a DevForce application to have a server-side query method.

8) Client-side caching. Query results are cached as are entities you create, modify, delete ... and have not yet saved. RIA Services does this too.

But DevForce applies your LINQ queries BOTH to the server store and to the cache. Suppose you have queried for all Northwind employees; you change "Nancy Davolio" to "Sally Davolio" and you add a new employee named "Sam". Meanwhile, another user has saved a new employee named "Sherry". What is the result of a query for employees with first name beginning "S"? The DevForce answer includes "Sally (formerly Nancy)", "Sam" and "Sherry".

You can tell DevForce to query ONLY the cache or ONLY the server ... as appropriate.

It's trivial (and recommended) in DevForce for your Silverlight application to prepare the cache with entities you need for a particular user scenario as you enter that workflow. You then would default subsequent query execution to "CacheOnly", and "party on" as if you had an in-memory database. Yes, you can still make remote queries and asynchronously refresh all or part of the cache at will.

The key benefit: you can easily program the user experience in the synchronous style familiar to most business application developers and still exploit the responsiveness of asynchronous data access ... using the same queries.

9) Productivity and Testability. You don't need a database or server to build and test your application. You can populate the DevForce entity cache with test entities - entire object graphs - and run disconnected. You can serialize the cache to file (e.g., Isolated Storage) - in a single method - and restore that cache at will. I often build a development data cache file, include it as a resource, and launch my application "in test mode"; the cache fills with the dev data rather than having to hit the server, and I'm running with no web server at all. I can make and explore UI changes in a fraction of the time it would take if I had to spin up Entity Framework and a server. I can work with colleagues far away who don't have Entity Framework or the database ... because there is no dependence at all.

10) DevForce entity properties are implemented with "property interceptors" that enable you to inject custom behavior into the getters and setter. Without touching the Employee class I can add logic to automatically mask the Social Security number  ... unless the employee is the current user or the user is an HR admin. I could inject logic into a setter to force values to upper case. I have complete, fine-grained control of the DevForce generated properties before and after the actual value access or mutation.

11) DevForce validation supports the same DataAnnotation validation attributes as RIA Services in addition to our own (richer) validation attributes. But you're not limited to attributes. You can add validation rules programmatically to the class and we'll discover them. You can access the list of validation rules for any type and manipulate that list, removing existing rules and adding other rules ... perhaps customer-specific rules determined by metadata. You can do this with logic entirely outside the entity class. And DevForce validation can be applied to any object, not just entities.

12) Navigation properties (Order.OrderDetails, Order.Customer) to related entities work even if the related entities are not in cache. DevForce fetches them asynchronously ... and can notify you when the data arrive. I would be wary of multiple, hidden trips to the database (the N+1 problem with lazy loading); you should consider eagerly loading these entities instead. But lazy loading has its place. Of course you can disable lazy loading of any property at any time.

You can find out more for yourself by visiting our web site, http://www.ideablade.com or write to me at AskWard@ideablade.com.

Friday, April 2, 2010

DevForce Extensibility With MEF InheritedExport

We’ve offered extensibility points in Our DevForce product since the beginning of the century.

Our customers wrote classes that implemented certain of our interfaces. We discovered those classes by examining assemblies named in a configuration file (app.config or web.config). We had our own probing and injection logic because market forces precluded use of a 3rd party IoC.

In DevForce 2010 we’ve switched to the Microsoft Managed Extensibility Framework (MEF) which is baked into the .NET 4 platform.

How hard was that? It wasn’t a big deal. Mostly we had to figure out how it worked and find the best approach for us. Which is the point of this post.

Because we almost made a mistake. We didn’t know about MEF’s InheritedExportAttribute.

DevForce Extensibility

Let me set the stage.

Suppose you want to alter DevForce default behavior by supplying your own way of doing something. Maybe you want to supply a custom “LoginManager” to authenticate users. Maybe you want to supply a class that intercepts all attempts to save data to the database … so you can confirm the user’s right to save or impose some extra server-side validation or add audit records … whatever.

Heretofore, you wrote a MyLoginManager that inherited from IEntityLoginManager and stuffed it in a server-deployed assembly; call it "MyServerStuff". You next identified “MyServerStuff.dll” as a probe assembly in your web.config. We’d look there for a class implementing IEntityLoginManager and, upon finding yours, would instantiate and use your class instead of our default class. Similarly, you wrote a MyEntityServerSaving class that inherited from IEntityServerSaving and we’d find it too.

In MEF, MyLoginManager and MyEntityServerSaving are “parts”. They are parts that you “export” for DevForce to “import”.

The DevForce 2010 difference: we let MEF do the finding and creation of your types instead of doing that ourselves.

Our Initial Mistake

In a beautiful world, you – the developer of MyLoginManager and MyEntityServerSaving – don’t change a thing. Your classes just work.

Actually, it’s better than that. You can throw away the <probeAssembly> tags in the web.config and the app.config. That kruft was a repeated source of confusion and heartache for our customers. It’s gone. No <probeAssembly> needed if you drop your assembly on the server in the \bin directory.

We should have done that long ago. MEF made it obvious.

BUT … it looked like it wouldn’t be quite this easy. How would MEF know to import your MyLoginManager and MyEntityServerSaving?

We couldn’t figure that out. In vanilla MEF, you attach an Export attribute to a component that you want others to import. It seemed you’d have to decorate your custom classes with these attributes like this.

  [Export(typeof(IEntityLoginManager))]
  public class MyLoginManager : IEntityLoginManager { // your code }

Ugh. Why impose this burden on the poor developer? How many support calls would we field that ran something like this?

“Sir? DevForce didn’t find your class? Please open Visual Studio … now look at the class definition. Does it have an Export attribute? Yes an “Export” attribute. What? Oh yeah you’ll need an assembly reference and a using clause too. Sure, I’ll hold why you build, redeploy and run it …”

InheritedExportAttribute

Fortunately, I know how to complain. I wrote a “WTF” email to Glenn who graciously replied as follows:

You might want to look into InheritedExports. If you are not using metadata you can put an [InheritedExport] on an interface which will automatically apply to the exporter.

In other words….

  [InheritedExport]
  public interface IFoo {}

  public class Foo : IFoo { ...}

Foo above automatically exports IFoo since the decoration is on the interface. There are some issues if you are doing this combined with metadata.

How about that!

We added “[InheritedExport]” to all of our extensibility interfaces. Now our customer’s existing custom classes are discovered and work as they did before without modification. No attribute needed.

What if the extensibility point is a base class instead of an interface? That works too. Check this out. In DevForce, we have an EntityServerSaveInterceptor class that intercepts server side saves. It does some work by default … work that you can extend.

Here’s its new MEF’ed signature in DevForce 2010:

    [InheritedExport( typeof(EntityServerSaveInterceptor) )]
    [DefaultExport( typeof(EntityServerSaveInterceptor) )]
    public class EntityServerSaveInterceptor {

Note the “DefaultExport”. That tells MEF to import an instance of this class if you don’t supply your own.

Customers can subclass our default version just as they did before:

    public class MyEntityServerSaveInterceptor : EntityServerSaveInterceptor {

        protected override bool ClientCanSave(Type type) { … }

    }

They can’t MEF up.

Is MEF Legal?

You don’t know about MEF? Where have you been? How could you have missed Glenn “Mr. MEF” Block; the man is everywhere – print, stage, and screen – talking up the MEF magic.

You can read about MEF here and here and here and all over the place. Mike Taulty, who is excellent on any subject, produced some superb MEF screen casts. The once-obscure Dependency Injection technique has gone mainstream with MEF and will be arriving soon in a code base near you. You’ve probably been doing something like it for years and didn’t know it.

Thursday, April 1, 2010

DevForce / UFC Gym Bling On Silverlight TV

We had way too much fun at MIX 2010 in Las Vegas last month. John Papa captured the flavor in a Silverlight TV interview with me featuring the UFC Gym Kiosk.

Watch the episode online by clicking this link or clicking the mage below:

3-31-2010 11-51-04 PM

My buds channeled their inner Elvis (mosaic courtesy John Papa):

Clockwise from top: Brad Abrams, moi, Karen Corby, Dan Wahlin, John Papa, Tim Heuer

This being April 1st and the garb verging on outrageous, you’re excused for doubting the seriousness of the interview.

In fact, we explored many substantive issues:

And I think the demo showed well what you can do in two weeks by concentrating on the User Experience (UX) and leaving the plumbing to us.

Who says business can’t be fun?   We had a blast!   Enjoy.