|
When building desktop applications that consume data from some external source, be it a Web Service or some messaging middleware pipe or even monitored flat files, a few things commonly happen. The first is that we realize that the format of the information we're consuming is almost never exactly the way we'd like it to be when we rig up our UI. Secondly, we don't want our UI to depend on an external service contract, so we usually decide we're going to build a separate ViewModel that is a binding-friendly, domain-specific representation of exactly what we want our GUI bound to. A few minutes later after scratching our heads a bit, most of us end up realizing, "Hey, I need to build an anti-corruption layer here." We then busily go about writing some semi-reusable code that will perform the task of consuming the service model and translating it into view model, and potentially go the other way as well though that's usually less important.
Let's take a look at a concrete example. Let's say you are writing a very rich, WPF-based desktop application that communicates with a Web Service for virtually all of it's data. The service contract has been split into a shared Assembly containing WCF-attributed interfaces so that you can still have strong typing at the same time as loose coupling. So far so good. The problem is you don't want to bind your GUI directly to the service data and the service data doesn't really lend itself all that well to what you're looking to do.
Let's say your WPF application is consuming market data ticks. Your service model gives you the following properties for a tick (bid ticks):
Your view model is designed to be useful to a WPF developer, not to a service developer. As a result, you've got a generic graphing control that just plots a time series data and only cares about the decimal value, the color of the plotted point, and the time stamp. Using CLINQ, you can just write a CLINQ query that will automatically, and continuously, translate from the service model to the view model any time anything in the service model changes.
ReadOnlyContinousCollection<ViewModelTick> ticks =
from serviceTick in ServiceModel.AllTicks
where serviceTick.TimeStamp >= marketOpenTimeToday
select new ViewModelTick()
{
TimeStamp = serviceTick.TimeStamp,
Value = serviceTick.Price,
Color = serviceTick.Side == TickSide.Buy ? Color.Blue : Color.Red
};
The thing that I like about this is that now ticks can be exposed as a property and bound directly to a WPF GUI. You could rig up a converter that converts a collection of ViewModelTicks into a PointCollection so that you could convert it into a Polyline (something similar to this is done in the CLINQ 2.0 stock monitor demo). You are declaring your intent and then simply letting CLINQ take care of making sure that both models are 100% synchronized in a real-time, asynchronous manner.
What I find surprising is that CLINQ was originally built for one very specific purpose - Continuous LINQ queries... But since then, it has taken on a life of its own and become such an invaluable part of my daily life that I am pretty sure I wouldn't know how to write a WPF application without it.
Hi Kevin, totally agree.
We're eagerly waiting on the v.2 upload to codeplex.
I already uploaded the ZIP file but apparently it didn't go public. I'll
take care of that this weekend.
I think I would like to check out your CLinq library, but I find your
license to restrictive, i.e. this license doesn't allow any use of your
code in any commercial work that I don't want to release with source code.
Can you please think about a BSD license for v2.0?
Maybe I am misunderstanding something but you release using the Common
Development and Distribution License (CDDL)
http://www.codeplex.com/clinq/license
Hi I looked into the issue and it seems that as long as I don't modify any
of your code that I can call into it and can keep my code proprietary
I modified the license and it's now using the "New BSD" license, which is
pretty much as non-restrictive as you can get. About the only thing
necessary is to keep the BSD license in the code.