ProfileWell, I thought it was i...PhotosBlogListsMore Tools Help
September 15

Blog has moved

My blog has now moved over here:
 
August 20

MSDataSetGenerator in VS2008 Beta 2

If you're running VS2008 Beta 2, you might have come across a problem with MSDataSetGenerator (the standard custom tool for generating DataSet code from XSD schema). It manifests itself as an error message that occurs when trying to run against XSD that <include>s other schema. (Note, xsd.exe seems to generate code just fine - it is only the custom tool inside of VS.)

There's a simple fix, though - install the August CTP of Blend 2 on your machine, and all will miraculously become well.

September 29

Two colors red

 If you take a quick look here you’ll have read an interesting article about “well known values” of common types. One example Abhinaba gives is Color.Red and new Color(255,0,0), which he says are “the same”. Moving swiftly over the fact that he meant Color.Red and Color.FromArgb(255,0,0), what about that equivalence claim?

Well, I suppose it depends how you define equivalence. If you use either of those colors to construct a  SolidBrush and paint a nice big rectangle on the screen, then they’ll both look the same. So, in that sense they are “the same”.

But try running this little console application, and examine the output.

using System;

using System.Collections.Generic;

using System.Text;

using System.Drawing;

 

namespace TwoColorsRed

{

    class Program

    {

        static void Main(string[] args)

        {

            Color red1 = Color.Red;

            Color red2 = Color.FromArgb(255, 0, 0);

            //Color red2 = Color.FromName("Red");

 

            if (red1 == red2 )

            {

                Console.WriteLine(

                    String.Format("Red1({0},{1},{2},{3}) and Red2({4},{5},{6},{7}) " +

                                  "are the same...the Universe is safe",

                    red1.A, red1.R, red1.G, red1.B, red2.A, red2.R, red2.G, red2.B)

                    );

            }

            else

            {

                Console.WriteLine(

                    String.Format("Red1({0},{1},{2},{3}) and Red2({4},{5},{6},{7}) " + 

                                  "are not the same...call the ChromaCops",

                    red1.A, red1.R, red1.G, red1.B, red2.A, red2.R, red2.G, red2.B)

                    );

            }

            Console.ReadKey();

        }

    }

}

 

Delve into Color.Equals() or Color.op_Equality() (operator ==) and you’ll find that things are not quite so simple. In fact, both of these methods of determining equivalence also check other properties.

First, there’s the state of the color. Did you know that not all colors are actually useful? If we pass an unknown name to Color.FromName(), then you still get a Color object back – it just isn’t valid.

Then, it checks whether the colors in question are well-known or not, and also compares by Name (which is a read-only property, so you have no real control over this).

So, when it comes to our first example Color.Red is a known color, but Color.FromArgb(255,0,0) is not; and anyway, their names don’t match either.

So, why would I care? Red is red, isn’t it? Well – there are often good reasons for trying to compare two colors – trying to find a match in a fixed palette, or looking for similar pixels in a bitmap region, for example. You need to check the (A)RGB values by hand, rather than using the seemingly-handy comparison functions.

This is a more general issue, both for API designers and consumers.

From the API designer’s point of view it is recommended that, if you are providing equality overrides, that your comparator should perform an identity-like compare. The Color.Red and your Color.FromArgb(255,0,0) are clearly not the same color, in an identity sense – they’ve got different names for a start!

However, from a consumer’s point of view, you often don’t want an “identity” comparison – especially with value types. More often than not, you need a semantic comparison appropriate to your application (like comparing the color values). And you have to write that yourself.

 If it is a very common comparison to perform, then you might be tempted to ask the API designer to roll it into the class concerned (especially if you are the API designer, too), but you should be very careful before deciding to do so. You don’t want to confuse the situation further by adding an army of subtly different comparison functions to a simple class or struct – especially one like Color.

Tricky fellow, equality.

June 01

Pop quiz

What is the output of the following SQL, and why?

IF 'BARRY' = 'BARRY ' BEGIN SELECT 1; END ELSE BEGIN SELECT 0; END IF 'BARRY ' = 'BARRY' BEGIN SELECT 1; END ELSE BEGIN SELECT 0; END IF 'BARRY ' LIKE 'BARRY' BEGIN SELECT 1; END ELSE BEGIN SELECT 0; END IF 'BARRY' LIKE 'BARRY ' BEGIN SELECT 1; END ELSE BEGIN SELECT 0; END

October 25

Name and shame...

Xara have just released the latest verison of their vector graphics package. It still doesn't run at all with standard user privileges.
 
Which is a shame, because it is otherwise a great package...that I don't want to use.

Vacancies

I've got three open vacancies at the moment - one for a C# Dev, one for a Dev/Test and one for a junior SQL Server DBA. Ideally, you've got some smart client experience, and some understanding of real-world problems in highly distributed, multi-enterprise systems. You're probably interested in 2D graphics and imaging, too.
 
If you're interested in coming to Cambridge (England) and working in the healthcare space for a fast-growing, highly motivated team, who are able to make a real difference to people's lives, then I'd love to hear from you.
 
The only proviso is that you'd need a valid working visa for the UK (or you're already an EU citizen, of course).
 
Drop me an email if you're interested, or go via our website (www.digital-healthcare.com).
 

Team System

We've recently moved on from the "experimentation" phase, and we've kicked off a small project to trial Visual Studio Team System properly. This has been up-and-running for a few days, and I thought I'd provide some initial comments.
 
Scoping
The project has a team of 9 devs, 3 QA, a Business Analyst and a PM. Its aim is to produce a shrink-wrap product for a particular vertical, based on a large existing source-code base.
For a team of that size, we picked a single-server solution and specced out a quad-Xeon box with 4Gb RAM and a RAID5 disk array to support it.
 
We decided to stick with our current build and test system (NAnt, Draco, NUnit2) for this particular project, as we are still targetting DotNetFX1.1 and the pain of migration would be too high.
 
However, we're experimenting with a migration of a snapshot of the source tree from CVS into TeamSystem source control. Some initial experimentation reveals that it is possible to side-by-side these two source control systems without too much pain. Both being merge-based means that you have to pick which system is actually going to do the merge for you - and you can then see if they disagree! You can then commit the results into both.
 
Our build-and-test server lives on another box in the domain, and continues to check out from CVS, which itself lives on another server.
 
For this project, we're going with an out-of-the box MSF Agile process. We want to find out how this differs from our standard processes and documentation, and to determine how much we want to change v. how much we need to change it.
 
Installation
The most important point is that you've *got* to follow the instructions *to the letter*. The installation checklists provided in the TFS Installation CHM are nice and accurate - but you must follow them precisely; it is very sensitive to variation.
 
We ran into a couple of problems during installation - it turned out that the "system healthcheck" can be a bit misleading. Our 4Gb, quad-Xeon box had "insufficient memory" and "insufficient processor speed". Ignore those warnings and carry on... We also dismally failed to install SQL Server on the original x64 edition of Win2k3 we had installed on the box. We repaved with the x86 build, and everything went swimmingly.
The installation instructions will take you right through from "the CD has stopped spinning from my Win2k3 server install". It is better *not* to have performed any of your standard application server configuration and lock-down before installing TFS; it has some particular IIS requirements (no FP Server Ext for example), and if your IT guy has prepped it to some "standard" configuration it might be tricky to get things going. Better to perform post-installation lock-down after you've proven to yourself that the installation is working.
 
I also found that it can be a bit tricky to set up your first administrative user; the TFS instructions are a bit sketchy about where to find the correct places in Reporting Services and SharePoint Services to configure the site admins. It is well worth reading the admin guides for those products too, and familiarize yourself with the infrastructure first, because you *have* to get it right before you try to create your first TFS project.
 
Why is that?
 
Well, it turns out that some irreversible database commits occur in TFS (e.g. source control) before the SharePoint site is created. While it tries to roll-back from most failures, under some circumstances, you can end up with a SharePoint site creation failure that leaves an orphaned, invisible TFS project that the TFS delete tool can't remove (even with the -force option), but which prevents you from reusing that project name again. It is possible to unpick that by hand in the SQL Server - but that's a painful afternoon's work and only marginally better than reinstallation!
 
Setup
Creating the new TFS project is very straightforward, and almost completely automatic. I was working inside VS2k5RC, but any Team Explorer instance will do.
 
Unfortunately, adding team members to a project is mind-numbingly awful; you have to add them to TFS, SharePoint and Reporting Services. The UI is completely different for each of these tasks, and the conceptual models don't exactly map neatly onto one another. On the plus side, there is a handy chart indicating the privileges you need to apply in each of the application servers for each user role, and more-or-less where to apply them. Again, it is useful to understand the admin model for each server before you do this, rather than just blindly following the instructions.
 
For even a 15-person team, this is somewhat manual and therefore error-prone. I'm hoping for some automation in this area by RTM.
 
Having created a project, there are a bunch of Work Items already waiting in the system, and assigned to the project creator. Some of these are around source migration and policy, some are around actual project set-up and inception. These all point you at the project guidance, so it is pretty straightforward to get going.
 
Project Inception
I was slightly disappointed with the Persona and Scenario templates available in this version of MSF Agile, but pleasantly surprised by the Vision document. In our regular process we usually create a "Scope" document which lives alongside the "3 paragraph" Vision and the detailed elaboration of Personas and Scenarios; it helps us keep an eye on policy around what is in- and out-of-scope; this is chiefly to avoid feature creep, which is the dark side of an agile, scenario-orientated project. The Vision template was easily understood by the BA, and the "Persona" document also offered a reasonable template. The scenario templates are a little light on structure, and we will probably want to enhance it a bit for the next project.
 
One quite powerful feature is the ability to create work items with associated "type" information. For example, you can create a "Scenario" work item to have someone elaborate a scenario. This takes a little getting used to for people familiar with a "bugzilla"-type "one-size-fits-all" approach.
 
Out-of-the-box there are a couple of MS Project plans on the SharePoint site - one for test and one for implementation. As a result of a bug in Beta 2 it is unnecessarily tricky to use these - TFS cannot integrate with the Read-Only SharePoint files and throws an exception when you try to push your selected work-items into it.
 
Incidentally, mapping from work items to project plans or Excel spreadsheets is not really mentioned in the getting started guide (you actually have to read the docs properly; what's that all about?), but it is the core of the TFS management process. You just select a bunch of work items in Team Explorer and you can then insert them into a given MS project file. You can then "publish" your changes to TFS (as distinct from publishing the document to SharePoint), or get updates from TFS.
 
To get around the Beta 2 bug, the Known Issues document suggests that you have to Save As... the MPP to a local disk. In fact, I've found that you have to Save As..., quit Project, restart, reload the file and *then* push the docs into it. Obviously, you have to replace the document on the SharePoint server when you're done.
 
You can happily add your own structural elements, milestones etc. to the project plan, which survice round-tripping. You do have to be a bit smart about duration and start time, as these can easily be lost when publishing and updating - I've not quite worked out why that happens yet, as it isn't entirely predictable.
 
Source Control
Source control has moved to a merge-model by default. This is a good thing, in my opinion, as we are used to this from CVS, and we find it very flexible. You can enforce various rules, such as code review, FxCop validation, and one-work-item-per-checkin. All of these are part of our standard process, so we just turned them all on. And then turned the FxCop validation off again when we realized that it didn't really work unless we were using VS2k5.
 
Unfortunately, the source control system still has the same difficulties as Visual SourceSafe when it comes to getting the repository-tree to reflect the file system tree. Because it is integrated with the Solution System, it has a tendency to make up its own folder names, and ignore a more complex, multi-solution on-disk structure. I would have thought that this was common with the kind of large software projects at which TFS is targetted, so this is a bit frustrating.
 
The most important limitation is that you cannot check files in at the root of source control repository - you must create a folder below this to check items that live at a solution root.
 
This is nothing you can't work around, but it is more taxing that it needs to be. An explorer-integrated source control system (like TortoiseCVS/SVN) is, IMHO, superior to an IDE-integrated system, particularly when you move to a merge-based model, and there is no longer a correspondence between touching a source file and "checking it out".
 
Non-developers
It is a shame that there is no easy way of accessing and managing your work items from the SharePoint portal; for non-dev/test team members, that's the only reason for having the Team Explorer - everything else they do is essentially managed through the portal.
 
So far, so good...
September 02

Installing Visual Studio 2005 August CTP

When installing VS.NET 2005 August CTP on a machine with a previous CTP installed, the MSDN download page has a set of instructions listing the components you need to uninstall (and a couple of MSI GUIDs in case of uninstallation difficulties).
 
There's one item they left off the list - don't forget to uninstall the Microsoft Document Explorer 2005 in addition to the rest.
August 08

What does your application runtime model look like Pt II

Some reasons why we might not want to use XML as the basis of our client application runtime model:

5. Our application devs will need to understand at least one of the (various) XML programming models
4. If we reuse our service schemas, structural decisions (e.g. byref/byval) might be imposed on us by our service designers that are inappropriate to our application tier
3. We pay for the runtime XML object model
2. Perf?
1. We're retrofitting our new service back-end to an existing application runtime, and the cost of migration would be too high

August 05

What does your application runtime model look like?

Some reasons why we might consider building application runtime world models as a collection of XML documents, rather than a graph of custom objects:
 
5. Reduces the impedence between our service layer and our application layer
4. The messaging/infrastructure devs and the gui/application devs share a common vocabulary
3. We can still create facade (utility) classes for ease of use, but only pay for them as we use them
2. We can't forget to provide a means of walking the association hierarchy with an XML document
1. We don't get a (choice of) rich query language(s) for free with our custom object model
 
June 17

A year ago...

A year ago, almost to the day, IanG wrote this...

Now, several iterations of Avalon/XAML later, I think that the questions he raises, implicitly and explicitly, are still the pressing questions today - and are, in fact, a more succinct way of expressing the generality behind the specifics I have been trying to raise some debate about over the past week or so.

The difference of opinion implied by different approaches that Chris Sells and I take to harvesting the benefits of Avalon (as exemplified in the comments to this entry) is, frankly, one of nuance by comparison with this more fundamental way of looking at the issue.

Whether you take a markup-ish or a code-ish view of the Avalon world is as much one of personal preference, experience, team composition, as it is a "best practice". And your choice may well be different for different projects, or even different parts of the same project!

Understanding where those choice boundaries lie, and making the "comprehension" step-function as low as possible when transitioning between them, is probably the key to achieving the kind of usability goals I was talking about.

I've tried to explain a few of those "shifts" I've found myself, and I can see others implied in the kinds of questions people are asking on the newsgroups, but I'd be really interested to hear about areas where you're finding it either difficult to make the "code/markup" decision, or where it is unclear what the upsides and downsides of that choice might be.

June 16

Falling in love with complexity

I thought it would be worth a quick post to explain some of the background to a few of my recent entries.

Once upon a time, not so long ago I loved C++. Loved it. The power and beauty of templates in that language (as expressed wonderfully through the STL and things like boost) delighted me. You could build wonderful, wonderful things that were conceptually expressive and simple for other template devotees to use.

In fact, a decade ago, we built a whole image-processing platform using those techniques. My, but it was great - consistent APIs, power, flexibility, customization, performance. You could plug almost anything almost anywhere and it would just work. Assemble components in ways that the original designers hadn't dreamed of to deliver new emergent functionality. Nirvana.

Only it turned out to be something of a dog in the real (commercial) world. For a variety of reasons.

First, you needed super-smart guys to maintain the frameworks. They had to grok the whole C++ template thing, understand the architecture deeply, have the kind of creative mind that allows them to see the patterns, how they could fit together and be repurposed. The kind of developers that I imagine to be reading this, in fact. This isn't a commercially scalable proposition. You guys are few and far between. And expensive (I hope, except when I'm hiring!).

Second, the people consuming the framework just didn't, on the whole, care about this flexibility. They have some specific use cases, and they wanted the SDK we provided to support those use cases, efficiently, and with a minimum of code.

In fact, it was worse than that. To support some (what turned out to be) "edge" cases, there were some relatively complex parts of the infrastructure that our framework team (and that included me) insisted you "had" to understand. (And by "insisted" I mean that the documentation guided you that way, as did the examples etc). So the impression given to the average customer was of some behemoth, even though there were much simpler ways of using the framework.

In the end, we gave them a C-callable wrapper API with about 16 high-level functions in it that 95% of our customers used 99% of the time.

Third, support was expensive. The 5% of customers that used the power given to them in the lower levels of the framework were a royal PITA to the bottom line (even if they were a huge benefit to SW quality). They originated 90% of the support calls - because they had a bright idea that revealed a complex edge-case we hadn't conceived of in our original QA.

This experience of the relationship between power, complexity and business sense has given me a somewhat different view of the world than the C++ loving "me" of a decade ago. I now look at any technology and think "how do we support that in the field?", "how do I explain that to my most junior developer?", "can I get 95% of the benefit for 10% of the work", "is any of that 5% commercially valuable?", "can I do anything to avoid locking myself out of that 5% even if I don't address it now?"

So, I'm coming to Avalon and XAML with the same view. The C++ loving me adores the power and flexibility in the frameworks. The pragmatist - the man who wants to continue to be able to pay the development team every month - thinks "which bits look dangerous, or difficult, or complex to explain or support, or look like they might be subject to change in future?".

The power is really important, but it should live below a serene surface that gets us most of our wins without us really noticing. Avalon is certainly delivering on that goal - but the simple things still need to be simple, and the really simple things, really simple.

June 15

What is structure, what is "look"?

Another dumb question I asked myself today that I couldn't answer in black-and-white terms, so I'm going to post about here, you lucky people. What is essential structure, and what are simply "visuals"?

Ryan Dawson has blogged an excellent summary of how to go about hand-crafting a custom control, and has rightly emphasised that you should seriously think about whether you want/need to build one at all, on the basis that a lot of what demanded a custom control in Windows Forms isn't required in Avalon. Taking Button as an example, you can replace its whole visual tree with something else, and it can still behave like a button. You can still click on it, mouse over it etc.

However, custom controls in Avalon also seem to serve an encapsulation function to permit efficient reuse of common structure and function, similar to a User Control in Windows Forms. 

There isn't really the philosophical distinction between Custom Controls and User Controls that there was back in the "old" days (hoho) - although of course, even then, the primary distinction was in terms of designer support. They both ultimately just derived from existing Control-derived classes (anything you like in the case of a Custom Control, and User Control in the case of a designer-created User Control).

So, what about a real-world example of a custom control? If I were building a clinical imaging application, I might want a common ImageViewer component that I could use in a variety of situations - kind of like a super-Image control.

Of course, I can build everything I want from raw elements every time I want them, and paste them into my XAML / code behind. I might need something to paint my ImageSource, some Layout, a ScrollViewer. I can add a panel which scales with the viewer that I can use as a repository for overlays which transform with the image, and another for overlays which live in the root coordinate space. With that as a basis, I can add decorators for all sorts of things, from annotations to magnifiers to...well...imagine away.

I could even reuse all this by encapsulating it as a resource.

However, if I wrap it up into a custom control, I can add a higher-level interface. I can add some DependencyProperties and some Commands to expose common functionality and state (stuff for zooming and scrolling, for example). There's nothing I couldn't do without wrapping it as a custom control. However, I can abstract away some of those implementation details and expose only what I need the clients to see; i.e. I can make it easier to use.

But - there's intrinsically some "look" to this control. I'll have added some visuals in there that provide the common, aggregate functionality necessary to be an image viewer. If it didn't have some of that "look" it wouldn't be an image viewer. In the same way that a ScrollViewer wouldn't be a ScrollViewer if it didn't have a couple of ScrollBars and some content. Contrast this with Button which can be a button more or less whatever it looks like!

Of course, those ScrollBars still pick up the template appropriate to them from their position in the visual tree - they're still skinnable. But I can't simply replace the visuals of the entire control, or it stops being an image viewer - it loses some of its behavior simply because it doesn't have some of its visuals.

So it seems to me that being "lookless" doesn't necessarily mean not having visual elements intrinsic to the structure of your custom control. It is something much more subtle than that, but I can't quite put my finger on it...

June 14

Comments for Rob Relyea

Rob asks for some particular instances where XAML feels "unclean". First, I want to reiterate the important distinction between Avalon and XAML I mentioned before - I'm talking about XAML syntax, not Avalon APIs. As Rob says, there is still some cruft there, too, but it is already better than Windows Forms 1.x and the Beta1 release was a huge improvement.

The first thing that came to mind is a comparison with the problems of the original Managed C++. What in XAML syntax looks like an implementation wart, which would be better as something which "just works"? What can't you just guess at, with a text editor in front of you (with or without intellisense)? Initially, I was trying to filter out the things I find hard because XAML is "new"; then I decided that that was the wrong approach. It should be possible to work this stuff out precisely because it is new!

Note that I'm not saying "this is wrong", I'm just saying "this smells wrong to me", and I'm interested in the argument!

Anyway, here are my top 5 to get started with.

1. The curly bracket notation. I know that this is a compaction of a more verbose form, but it feels clumsy. The curly brackets are there to indicate to the parser that we're not in Kansas any more, and you shouldn't treat what follows as "just text". But it still feels inconsistent with the XML-ness of the rest of the notation, and makes it difficult to read inline; I can feel my brain doing a context switch, and that is usually a sign that something is up. What if the default was such that if the text could be interpreted as an entity, it is; otherwise it is interpreted text, with a special notation (like the @ symbol for strings in 1.x) for "this looks like a real, parsable entity, but please treat it as a string". That way you'd eliminate the wart for 90% of all uses.

2. Accessing dictionary, or path-like objects without an operator. e.g. {StaticResource Foo} This would seem more natural to me as something like {StaticResources[Foo]}, with a bit of a feel of both C-family languages, and XPath about it.

3. To quote, or not to quote. The text inside the curly brackets looks like it is intended to be congruent with the XML attribute notation, but the systematic absence of ' marks around potentially whitespace containing content (presumably to avoid confusion with the fact that this is actually quoted content of an attribute anyway) again feels odd. Neither way seems a happy compromise, though.

4. Inconsistency of application of the same constructs. There are a few consistency pitfalls around still. I suspect that these are just bugs. (Things like RenderTransform and LayoutTransform not being declartively symmetric, which I mentioned in an earlier post) In particular, I'm interested to know if this is because of the moral equivalent of something  just getting left out of a list somewhere at an implementation level, or whether this is because there's something philosophical I'm not understanding about how this all hangs together.

5. 'Orrible grungy namespaces. The drawback of using XML is that you end with grungy namespace warts throughout your XAML. There's no real XML equivalent of "using".

Oh, and just to say it again; I love this Avalon stuff - it is the presentation model I've been waiting for years! And I also love that MS are engaging with developers this closely over every detail of their next generation platform. If it ends up sucking (which it won't), we'll only have ourselves to blame!

June 13

Avalon, XAML as a discoverable API

Over the past few weeks, I've been looking at the Avalon APIs in terms of their discoverability and "linearity" - how much incremental benefit do we get for incremental effort, and how "grokkable" are they to start with.

If you look at the APIs from a code point of view, then things seem pretty good - at least as good as Windows Forms, at any rate. Avalon's API is actually pretty traditional. There are nice clean control, layout and databinding mechanisms (much simpler than Windows Forms, in fact). The resource mechanism is actually the same one as we have in Windows Forms 2.0 (with a few wrinkles), and then we have, building on top of this, a styling and theming/skinning mechanism that is still in flux, but is pretty straightforward (and is likely to get clearer and simpler before shipping). Things start to get more complex as you dig into the detail of the graphics/drawing APIs as the model has changed - but once you've got over that conceptual hurdle, it is again simpler than the Windows Forms model for most use cases (until you get down to the really low-level hairy stuff). It helps that his new conceptual model is the one people often expect to find when they start out with GDI(+), only to be rudely disappointed when their beautiful drawing vanishes when they drag another window across it!

However, when XAML comes into the equation things seem to change. I'm not quite sure why, but it suddenly seems to be necessary to understand a whole lot more of the richness of the API to get started. Even simple XAML examples start to require an understanding of the resource syntax at the very least, and the inter-dependencies race to overtake one another very quickly, until you realize that you need to understand the whole system just to make incremental advances.

Of course, the whole system isn't all that large, but it is a fairly hefty amount to swallow all in one go - especially when you also factor in the many different ways of expressing the same underlying APIs which are available to the XAML developer. And you will see all the syntactic flavors in any given example, because one flavor is naturally "better" than another for different purposes; the experienced XAML developer wouldn't think twice about it.

However, this means that newbies have to contend with a larger slice of syntactic pie just to examine and understand sample code, let alone the actual APIs.

Also, the things that people are interested in demonstrating (rotating fading buttons with arbitraty non-textual content and gel imagery and on and on and on) are not really the kind of things you can expect to be building in your "real" apps. When this becomes the presentation tier implementation technology of choice, the majority of developer hours will be spent on relatively mundane forms capturing data - and we'll want them to look "standard" (by the standards of the day!) Most developers shouldn't need, or want, to understand these lower levels of detail and complexity. In fact, we probably want our designers to get involved in that complexity, and our developers to more-or-less ignore it.

So, it is important that the "average developer" should be able to cruft up applications quickly and efficiently, from sample "cookbook" code - and should be able to understand what that code is doing. This is how most developers learn today - for good or bad.

This problem is nothing new.

Back in the days of Win32, Petzold and WndProcs, the APIs were too complex for this to happen effectively, and so Visual Basic stepped in to the breach, to become (arguably) the most successful rich-client application technology of all time - whatever you may think of it!

Avalon delivers an API which permits the same ease of use; in fact, I think it is more consistent, simpler and generally easier to use even than VB's API, as well as offering richer functionality even at its surface.

But I don't think XAML quite delivers on that ease-of-use goal as it stands. I'm sure the intention is to build tooling around it for RAD development, and so maybe this doesn't register all that high on the radar, but it still doesn't feel as "clean" as it could, to me. Yet.

June 10

XML Messaging, Indigo, Object Mapping

There seem to be two camps in the world of SOA - those who want to live somewhere near the top of the stack (using ASMX or Indigo's service-level "object mapping"-like technologies), and those who live nearer the XML messages themselves.

I'm firmly in the latter camp - and I've got two justifications.

But first, I'd better make clear a couple of assumptions. I am assuming that the benefits of service-orientated architectures lie fundamentally in the asynchronous exchange of well-defined messages to request well-defined semantic services from providers residing at well-defined end points. Secondly, I am assuming that we are talking about designing and building services, not consuming them.

I'll take each of those italicised points in turn:

  • Asynchronous
    • Addresses the issue of latency in transport and execution
    • Improves scalability
    • Requires consumers to assume that services are not instantaneous, encouraging appropriate design
  • Messages
    • Encapsulate information in a robust, structured fashion
    • Designed for portability - from provider to consumer
    • Define information domain for service providers and consumers
    • Encourage well-bounded design
  • Well-defined semantic services
    • Explicit contract
    • Should be defined by semantics, not by signature or implementation
  • Providers
    • Host services
    • No particular implementation or deployment technology implied
  • End points
    • Well-defined means of exposing hosted services to consumers
    • Abstract details of providers from consumers

None of these points require any particular implementation technology, platform, language or infrastructure, although, in general, we think of the WS-* standards, and stacks like ASMX or WSE over network technology like TCP/IP.

I've recently had to implement a message-passing application based on eBXML (don't ask!). eBXML is largely SOAP based, and requires a stack analagous to the WS-* bits; very similar in many ways, but completely incompatible. But susceptible to a service-oriented analysis nonetheless, and susceptible to the same arguments.

So, on that basis - on with the justifications.

Justification the first

In real-world service-orientated designs, there are two things which are critically important

1a) Getting the granularity of the services right

1b) Getting the granularity of the messages right

"Right" in this case can mean a number of things. Appropriately coupled, appropriate amounts of information being transferred, appropriate for reuse. It has got a lot to do with both the semantics of the service, the expected consumer model and the deployment model.

Abstracting away from the actual message design makes this much harder to get right, apart - possibly - from the expected consumer model. Unless the message payload is very simple (and the canonical calculator example is not very "real world"), then imposing an object-mapping on service designers seems overly (if not dangerously) restrictive, even if an object-mapping might ultimately be useful to a consumer (although that should be the consumer's decision).

This is not to say, then, that service consumers shouldn't be presented with an object mapping. It's just that providers and consumers rightly have a different view of the world, and the message-level design is more useful to the service builder.

Justification the second

Having got the service design "right", it is important to consider how a message-passing design impacts on the rest of your architecture. You have to assume that messages will get lost in the post, go missing, get routed to the wrong place. You have to assume that messages that you thought were lost will turn up unexpectedly weeks later. You have to assume that malicious individuals will try to route messages unexpectedly.

Not all of this is simply a "plumbing" problem. To sort out the real-world semantic implications of these kinds of async message exchange problems, you often need to involve end-users with domain knowledge to help sort things out; ideally these are not "sysadmin" type people, but real domain users who are prepared to deal with the semantic results of an infrastructure problem.

If you don't actually control or understand the actual message layer of your infrastructure, it is very difficult to come up with a sensible design for that part of your application. This isn't a problem that can be mitigated by a general, horizontal solution - it critically depends on the nature and intent of the messages.

In the eBXML example above, for instance, presenting views on the "missing" or "unexpected" messages, often aggregating several together for presentation to determine what to do (accept some or all of the implied semantics, modify, resend, carry out other function x,y or z...etc...etc...)

If you've lost (or never really understood) the granular nature of the services you define, implement and deploy, it is very hard to get this kind of resolution right. If you don't address these problems, then your applications will be brittle and prone to intermittent, difficult-to-resolve problems.

So, that's why I'm in a "design your messages, think about message interactions, and only provide object-mappings to consumers who need them" camp. Come and join me. I'm toasting marshmallows on a stick over here.

Blog entry editor

OK - I should have searched first. Yes, the editor is horrible in MSDN Spaces, but if you go here... you can find a link which you can stuff into your toolbar, and click when you're in the MSDN spaces blog editor, and it suddenly becomes better. You can mess with font sizes, and even edit the HTML directly.

Acrylic

So, Microsoft have released a beta of a pixel/vector editing package codenamed Acrylic. As a fully paid up user of Xara's vector drawing product, which falls into the "simple but effective" category (as well as being a founder member of the "slightly long in the tooth" team - it betrays a UI vintage Win32s), I was interested to see what MS had to offer in this space.

Unfortunately, at the moment, it really isn't any great shakes. Certainly, not when compared to AI or similar (as, for some reason the press is choosing to do). However, I'm not sure that it is meant to offer competition to that product. It seems to be more in the "hobbyist" category.

I'm assuming that this product has actually been around for a while under some guise or another, as it is at V4.0d according to the About Box, and the UI itself betrays considerable age. And not necessarily from a purely Windows background, either, judging by the status text "Cmd/Ctrl to start twirling..." (I can't find the CMD key on my keyboard right now, but I'm certain I saw one on a Mac somewhere...)

The HCI is a bit messed up (like the draggable rulers but no scrollbars). Innovation is great, but not when it makes the UI difficult to use; with every other app, the instinct is to move to the right and bottom to scroll the window around, but not here; here you have to move to the left and top.

The sluggish performance is mentioned in the release notes as a "beta only" problem. I presume that means they know that in a drawing app sluggish drawing performance is often architectural and not just a case of squeezing a few peephole optimizations in the week before shipment; there's a long way to go there, not just in the actual drawing itself, but a general "java-like" disconnect between my clicking on things in the UI and anything happening. Only a 1/10th of a second or so, but enough to be annoying.

The absence of real-time manipulation facilities (XOR skeletons?! do we still live in caves?) is more of a problem for me. Tweaking is my mode-of-operation in drawing packages. I can't do that "put two strokes on a page and it looks fantastic" thing that proper artists make look so easy, so I mess about until it looks right to me. And it will be kind of OK if I can do that, but if not, I find it hard to achieve what I want.

So all in all, this is a "C" at first look, but I'll definitely invest some time in trying to think of ways to make it better.

Which brings me to the point. There is one vital thing that is missing. Where's my Export to XAML function?

(and don't say..."Export to AI then...")

June 08

PDC and a plea

Gosh. Doesn't time just fly.

This morning I opened my desk drawer, and saw the shiny black PDC 2003 highlights DVD at the top of the pile. Minutes later, I was registering for PDC05 in September.

If you've not been to a PDC before (and I've only been to one, and can therefore speak with great wisdom and sagacity, oh yes), and you're wondering whether you can really justify going - then wonder no more! It really is a must-attend event. Go on, tell your boss I said so.

Although PDC03 was cool - because we got a first look at Avalon and Indigo - it really just hammered home the "you want to think about moving to .NET, and soon" message. There was plenty of groovy stuff, and the vision was exciting, but it wasn't (yet) a coherent story. You were "there at the beginning(tm)" but that didn't perhaps, fully justify the cost of attending in and of itself (although there were plenty of other things that did). So don't beat yourself up that you missed it.

What about 05? I'd be willing to bet that we don't quite have a coherent future story at PDC05, either. But I reckon it will be mostly coherent, and the apps that we build in 2007-8 will recognizably be of the same breed as the technology presented at the conference.

Also, there's important stuff of the "very nearly here and now" that was only touched on at the last PDC. Team System is probably the most significant, but in-depth sessions on .NET 2.0 technologies are going to be as important (if not more important) than the futurology.

And that's only the stuff that we know about. PDCs have always seemed to have a surprise. (Even if it was only the surprise of "What? That's it?!" Hailstorm PDC in Orlando, 2001 ) Oh - and there's every opportunity that you can induce a diabetic coma by partaking of the donuts.

But - what if you don't get to PDC? I really hope that MS UK repeat the fantastic job they did in '03, running a local "Not the PDC". While I get to go and be threatened by bored immigration officials at LAX, the folks in my team in the UK don't, and they benefitted enormously from the "home grown" conf-ette last time around.

PDC'05 - Developer Powered

June 06

Mouse Capture

In Win32 applications, if you wished to continue receiving MouseEvents when the mouse pointer moved outside your window, you needed to use the SetCapture() API. Typically, you'd do this when you depressed the left mouse button and started some kind of dragging/drawing operation, then call ReleaseCapture() when you were done.

Then, dawned the day, and Windows Forms came along. On the whole, you didn't need to do this any more. Although there are still Control.Capture and Control.MouseCaptureChanged, you'll find that mouse events magically get routed "how you'd want them to".

For example, if you build a little winforms applet like this:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            label1.Text = "Mouse down!";
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            label1.Text = "Mouse up!";
        }

//        protected override void OnMouseMove(MouseEventArgs e)
//        {
//            label1.Text = e.X + " " + e.Y;
//        }
    }

(Note, I dropped a label on the design surface called label1)

You'll find that if you click and hold the left button on the main form, the label text will change to "Mouse down!". If you then release the button, it will say "Mouse up!". Now, try again, this time clicking-and-holding inside the window, before moving the mouse outside the window, and then releasing the button. In a Windows Forms app, you'll see that you still get the text "Mouse up".

If you uncomment the mouse move handler, you'll notice that you stop getting mouse events when you move the cursor outside the window - unless you're holding down a mouse button - in which case you get the "magic" mouse capture behavior. This was quite nice - although it hid some "plumbing" from you, it basically worked exactly the way you'd want.

Now, back to Aavlon. We still have the concept of mouse capturing familiar from the previous two generations. However, we're back to the Win32-style behavior, where mouse capture has to be handled explicitly. One slight (but significant) change is that any UIElement can capture the mouse pointer, and the APIs are now called CaptureMouse() and ReleaseMouseCapture(). Otherwise, all the old Win32 principles apply.

By way of illustration, here's a code snippet that you can use in conjunction with a ScrollViewer, to allow the user to click and drag on the viewer's content to scroll it around. (your mileage may vary, use at your own risk etc.)

Point previousPoint;
void scrollViewer_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
 ScrollViewer scrollViewer = (ScrollViewer)sender;
 if (scrollViewer.IsMouseCaptured)
 {
  Point p = e.GetPosition(scrollViewer);
  scrollViewer.HorizontalOffset =
   Math.Max(0,
    scrollViewer.HorizontalOffset - (p.X - previousPoint.X));
  scrollViewer.VerticalOffset =
   Math.Max(0,
    scrollViewer.VerticalOffset - (p.Y - previousPoint.Y));
  previousPoint = p;
 }
}

void scrollViewer_MouseButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
 ScrollViewer scrollViewer = (ScrollViewer)sender;
 if (scrollViewer.IsMouseCaptured)
 {
  scrollViewer.ReleaseMouseCapture();
 }
}

void scrollViewer_MouseButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
 ScrollViewer scrollViewer = (ScrollViewer)sender;
 previousPoint = e.GetPosition(scrollViewer);
 scrollViewer.CaptureMouse();
}

June 05

Bad practice, good practice, what is XAML for?

Did you notice the deviation from recommended API design in my entry on Avalon earlier? There seems to be a drive to replace boolean values with "more descriptive" enumerations, so perhaps I should have used an enumeration for my CentreOnMouse property. I should have renamed the property something like ZoomCentre, typed with an enum like ZoomCentre.CentreOnMouse and ZoomCentre.CentreOnView.

This would allow me to extend the possible centring options in future, without making a breaking change to the API, and might also make it more descriptive and self-documenting. These are good things.

The big downside is that you end up needing to use converters to get databinding to work in a whole host of common scenarios (think of binding a checkbox control's CheckState enum to a tri-state property enum as a simple example). 

Maybe there needs to be some nice expressive syntax available in XAML to do translation between enumeration values to bind between enums of different types, without resorting to code?

This fairly arbitrary divide between "a. what you have to do in code", "b. what you can do in XAML or in code", and "c. what you can do in XAML" has been troubling me over the past couple of weeks.

In general, I'm coming to the conclusion that XAML is "only" really useful for two things:

  1. Large-scale layout, hosting controls in Panels
  2. Creating new chrome to style stylable controls

I say "only" because these are powerful things, and XAML is very expressive, both in the hands of human beings, and in the hands of code-generators. Particularly with (1), it encourages you down the road of best-practice layouts for scalability (as long as you don't abuse "Canvas").

However, I think that when you fall down the gap between a. and b. above - and you do, unless you are building something quite trivial - you end up splitting your efforts between code and XAML, and you frequently have to dodge backwards and forwards between the two files to make changes.

In those cases, you should write everything where you have a choice, in code, in one place.

There is one other place that XAML is useful, of course, and that is as a serialization format for the "drawn" elements of your visuals. But your artists and designers (you? - certainly not me!) are not going to execute those in XAML, are they? They'll use Adobe Illustrator or somesuch and just export to XAML for inclusion as a resource in your project; you'll never actually "see" that XAML as text, unless you are a masochist. Although it is important that it uses the same model in the runtime tree for consistency and manipulation, there's no actual reason for it ever to appear as XAML per se.

So, what's my message here? XAML is a brilliant and powerful innovation, but the story isn't quite straight yet. Just because you can do something with XAML doesn't mean you should. Continue to think in terms of maintainance and readability, and always look for opportunities to re-present chunks of your XAML as custom controls.

June 04

MSDN Spaces

Argh! Can't you guys do something about this horrible text editor?! The mysterious changing font-size, peculiar color picker, weird paragraph behaviors...

DependencyProperty tip

DependencyProperties are your friends. For the sake of a line extra code, you get all the lovely event-raising, data-bindability that requires those slightly ugly hand-coded "well known" events in Windows Forms applications. Here's an example.

public static readonly DependencyProperty CentreOnMouseProperty =
  DependencyProperty.Register(
    "CentreOnMouse",
    typeof(bool),
    typeof(ImageViewer),
    new PropertyMetadata(true) );

/// <summary>
/// Gets / sets a value which determines whether mouse wheel zoom
/// is centred on the mouse
/// </summary>
public bool CentreOnMouse
{
    get
    {
        return (bool)GetValue(CentreOnMouseProperty);
    }
    set
    {
        SetValue(CentreOnMouseProperty, value);
    }
}

Notice that we've got a boilerplate property, plus a static field to hold the dependency property itself. The name this static object registers matches my regular property's name. You also register type information for the property, and the type of the class that owns the property. All this stuff is necessary plumbing for the framework.

Finally, There's an optional PropertyMetadata object. This is basically a bag to hold other gubbins about the property. In this example, I'm using the constructor that allows you to set a default value. Contrast this with the use of attributes in Windows Forms to achieve similar ends.

The PropertyMetadata allows you to do all sorts of stuff with your property. If you read the current documentation, it tells you in the same breath as these basic details a heap of other information about overriding get/set callbacks to cache local versions of the data in your class. You don't really need to bother with any of that - it is plenty fast enough to go through that property accessor for the data (unless you've measured that boxing and unboxing your value-type property is going to be the major performance overhead in your UI, in which case I'm impressed with your optimized drawing algorithms!)

However, there is one particular (common) usage that is quite tricky to find at first glance - how do I tell if my property has changed? You might think that you could just put some code in your "regular" property get/set methods. But they aren't actually called by the infrastructure as a matter of course - only by explicit references in user code. You might also think that the get/set callbacks would be the way to go. But no - you are then compelled to implement the local backing store and this is a terrible waste of effort. (In fact, it also appears not to work quite properly in Beta 1; or I'm misunderstanding something; I appear to lose "multicast" behavior when doing this kind of thing and binding several entities to the property)

The best way I've found to do this is to register a PropertyInvalidatedCallback. There is a convenient constructor on PropertyMetadata which takes both a default value and a callback of this kind. Invalidated?! Sounds a bit hairy! Well, not to worry. In this context, "invalidated" turns out to mean "changed in some way", rather than "no longer in a valid state".

The callback should look something like this:

private static void UpdateScaleFactor(DependencyObject dependency)
{
 ImageViewer viewer = (ImageViewer)dependency;
 viewer.UpdateScaleFactor();
}

First, note that this is a static method - it had to be because we were registering it in a static field (this is class-level metadata, after all). So, to do anything useful, we need to get a reference to the object whose property has actually changed. Fortunately, that DependencyObject parameter is just such a thing. We can upcast to our known type, and then call a non-static (private) method that deals with the fact that the property has changed. Note that this occurs after the property has changed - you don't get access to your previous value this way. If you need that behavior, you'll have to resort to a backing store mechanism (or play with some of the other callbacks, which offer pre-change validation etc).

Go DependencyProperties!

May 28

Avalon Beta1RC1

I've been playing with the Avalon/Indigo Beta1RC1 for much of this week.

The first thing I noticed was how much closer to a product this feels now - certainly by comparison with the previous CTPs. In particular, the perf is really getting there - on my HT desktop machine, anyway. On my laptop (Radeon 9600, Centrino), for some reason, the CPU is pegged to 99% even when the app is just idling, and the thing intermittenly hangs for 30 seconds at a time performing a simple Scale operation.

The API overhaul is bearing fruit - the styling is much more usable. But there are still some inconsistencies with the revamp - for instance, you can't apply a LayoutTransform using the <Entity.LayoutTransform /> notation, only the attribute notation (while you can apply a RenderTransform that way). It is also sometimes tempting to force yourself down the XAML route, where code could actually be more expressive or easily documented. Sometimes it is easy to lose track of what is behavior (which is probably best implemented in code) and what is visual (which is probably best implemented in XAML). Mouse overs, for instance, fall somewhere between the two. The fact that your button glows orange when you move the mouse over it is an artefact of your visuals, and might be different with my button, but feels quite like a behavior.

I am, however, less than devastatingly impressed by the animation facilities. It is a shame to see the local animations stuff heading towards "deprecated" status (code only in this shipment), and the barrier to entry is still too high. For behavioral animations (e.g. mouse click -> kick off a double animation to scale from x to x + dx), you need several lines of code, messing around with clocks and so forth. It needn't be that tricky! I think that it needs another "what code would we want to write" review for some common scenarios.

Bitmap handling is interesting. Memory usage is pretty efficient (without the need for manual Dispose() of your image sources). However, it is still necessary to provide your own ImageSource implementation if you are dealing with lots of big images (e.g. to cache things out to disk when things get too hefty). This is interesting, because the Avalon model encourages the "only talking to the original pixel data occasionally" view of the world, and caching images out to disk in memory-pressure situations would seem to be an obvious optimization, given the general implications of the design of the image sources (it is significant that we have moved from a "these are your pixels" to a "you can get your pixels here" model). It would also seem to be the way to achieve the kind of perf goals the team indicated they had for Aero at PDC (oh so long ago now!).

Anyway; I don't want this to sound like a gripe. Avalon is shaping up to be a major piece of technology. To give you an idea, something that took me 3 months to implement with Winforms and V1.x, and get up to perf (speed and memory usage), took me an afternoon with Avalon Beta1RC1; and it was a much more enjoyable experience.

As with the V1.x framework, we're being offered a richer platform on which to base our applications in future, and we're going to have to be smarter and more creative than ever to add distinctive value for our customers. The competitive environment is going to be very interesting in the next few years!

PS I haven't mentioned Indigo. This is mainly because it doesn't feel like it is at Beta-anything just yet. This is going to be another critical technology, but I'll stick with WSE for the time being.

April 23

The Woe and Beta 2

Well - the woe still exists in VS 2005 Beta 2... And it is still intermittent. The occasional appearance of the classic "open the solution having closed it with a designer window open" problem. You see the (kinda to be expected) error window indicating that some dependencies are missing - but the designer round-tripping still deletes the code referencing the "missing" components.

(Note - I think that VS.NET Beta 2 is otherwise a work of genius. Just the rename-refactoring smart-tag makes it worth the entry price)

 
Photo 1 of 1
More albums (1)