Friday, July 02, 2010

ViewModel in .NET

[Changed very little from a sizeable post to PADNUG today:]

For observable objects like view models, I usually have a base class
that provides INotifyPropertyChanged and IDisposable. Change-tracked
properties are held in a PropertyBag, which is a souped-up Dictionary
that maps properties to backing values. It detects changes, so can invoke PropertyChanged intelligently.

Indeed, if you want to get elaborate, and are comfortable with generics, there's quite a bit that the base class can do for you. A nice pattern is

abstract class ViewModel<TViewModel> where TDerived : ViewModel<TViewModel>
{}

class ConcreteViewModel: ViewModel<ConcreteViewModel>
{}


This lets your base ViewModel class know the type of its subclass. Once it has that, it can do slick things with lambdas, like

protected TProperty Get<TProperty>(Expression<Func<TViewModel, TProperty>> propertyLambda)
{
return mPropertyBag.Get(propertyLambda);
}


and

// the return value is true iff the property changed
protected bool Set<TProperty>(Expression<Func<TViewModel, TProperty>> propertyLambda, TProperty value)
{
return mPropertyBag.Set(propertyLambda, value);
}


That's quite a mouthful, but when you use it, the generic parameters become implicit, so the syntax is just:

public IValueConverter EventDateConverter
{
get { return Get(x => x.EventDateConverter); }
private set { Set(x => x.EventDateConverter, value); }
}


It's not quite as simple as automatic properties, but it's the same number of lines; you don't have to declare a backing variable for each property. And, you get change tracking, lazy loading, and INotifyPropertyChanged. It's (reasonably) safe from problems if you rename your properties, because the lambda are compile-time checked. I say "reasonably" safe b/c you can still screw it up if you do something like:

public IValueConverter QuantityConverter
{
get { return Get(x => x.EventDateConverter); } // oops, now the lambda points to the wrong property
private set { Set(x => x.EventDateConverter, value); }
}


There's a dozen little tweaks you can do. For example, I've overloaded the Set() to accept a MethodBase, which allows the syntax

public IValueConverter QuantityConverter
{
get { return Get(x => x.EventDateConverter); }
private set { Set(MethodBase.GetCurrentMethod(), value); }
}


In other words, you never get copy and paste errors from the setter. 50% reduction in risk surface area.

Other things:
* Make PropertyBag smart enough to notice when it's got an IList<> or IEnumerable<>; in that case, the default values are empty collections, not null ones. For assemblies involve in UI, I've got an ObservablePropertyBag specialization that knows to initialize ObservableCollections, too.
* Give the base class two generic parameters: one for the concrete subclass, and one for an interface that the subclass implements. If you define the lambda expressions for Get() and Set() in terms of the interface, the lambdas in your properties won't compile until you put the properties on the interface. In other words, the compiler will force you to keep your interfaces up to date. It's not for everyone, but I figure if I'm going to work in a statically typed language (haven't moved to C#4 yet), I might as well make the compiler work for me.
* I don't show an example here, but since Set() returns a boolean indicating whether the value changed, you can call it as an argument to an if statement and do additional processing. Note that by the time Set() returns, the INotifyPropertyChanged event has been raised. If you want to do pre-processing before an event, you can register the pre-processor during construction. (That's kinda hacky; AFAIK, there's no contract that the framework will maintain the first-registered, first-notified order on event subscribers. But it's been true so far.)

Using generics this heavily isn't for everyone. My actual ViewModel base looks like

public abstract class ViewModelBase<TInstance, TViewModel, TView> : ViewModelBase, IViewModel<TViewModel, TView>
where TInstance : ViewModelBase<TInstance, TViewModel, TView>, TViewModel
where TViewModel : class, IViewModel<TViewModel, TView>
where TView : class, IView<TViewModel>


before you get to the opening bracket!

In sum, this can be a moderately deep topic if you want it to. I didn't even touch on keeping the PropertyBag threadsafe...

Patenting business methods: Bilski v. Kappos

Just started following Stephen Forte when I ran into his take on the Supreme Court decision re business method patents.

> I could go and patent my implementation of Scrum since it is a business process and then turn around an sue all of you since I think you are using it.

This is a common misperception. There are some important hurdles to clear before you can patent something; they keep 99% (though clearly not all) of the frivolous stuff out. You can't hold a valid patent on something you didn't invent yourself (or in collaboration with all named inventors), and you have to conceive of it (and then claim it) before others had already begun practicing your invention.  In fact, once you've been practicing your invention in public for a year, even YOU can't patent it.  That's the US; in many countries, the moment you go public, you've lost your chance to patent.

Thus, even if you manage to find a Scrum style you can claim as yours, and patent it, and go to court, if the party you're suing demonstrates that they were already practicing your method before your "claim date", then not only do you lose the suit, but your patent gets invalidated.  An invalid patent is worthless.  You can't collect license fees on it, and you can't sue anyone else ever again with it.

So, there are some reasonable limits to the system, and that's one of my favorites.  Every time you take your patent to court, there's a risk you might blow it up.

> [Bilski] did not invent anything, just a creative way to hedge commodities.

Well, the case turned on the fact that he did not invent any thing.  Methods of doing things are entirely patentable, if they have a tangible output.  The problem with a business method is that its components and output are too "meta": it's a way of organizing and running an abstraction (which is basically what a business, certainly a corporation, is).  Bilski apparently had a new, useful, and original method, since all of those are required to obtain a patent; but there was no physical component, so it was not patentable. 

Patent law is historically all about tangible products, or methods of doing things to tangible products.  Software was considered unpatentable until someone hit on the idea of claiming them as instructions coded for a tangible machine to perform.  In other words, you don't claim the algorithm; you claim the execution of the algorithm by a machine.  Business methods are still trying to find their breakthrough angle into the realm of the patentable.  The Bilski decision was a setback, and a moment of sanity, but it hasn't really settled much.