Thursday, October 15, 2009

Let StyleCop Emancipate you from Source Code Micromanagement

My current project has stringent requirements across the board, including that of a highly consistent coding style. This is completely understandable because the client will be taking over maintenance and long-term support sometime after we’ve shipped. As such, they want to feel comfortable that their developers won’t be handed a steaming pile of code poo to polish.

One of the tools I thought might help us with this problem is StyleCop. This tool can analyze your code and flag any issues related to style. My initial suspicion was that StyleCop would annoy the heck out of me in about 10 seconds flat. It would whinge about missing file headers, the number of blank lines between code blocks, and even missing API documentation on private members. And it did do just that.

But something strange happened after a while: I stopped caring.

But not in a bad way. I just let the tool make these micro-decisions for me and instead concentrated on more important things like – you know – making the product actually work. If it told me I needed a blank line between my property getter and setter, I just did it – no questions asked. There was no nagging worry that I would do it differently elsewhere, or that some future developer on the project would, because the tool simply wouldn’t allow you to.

I’ve been able to get StyleCop integrated to an extent that I am very happy with:

  • It runs every time I build, whether it’s on my machine or the build machine. And it does not need to be installed on the developer’s machine (or the build server)
  • Any problems StyleCop reports prevent the build from succeeding (i.e. any problems are errors, not warnings)
  • Less important projects are excluded from StyleCop altogether, or have relaxed rules (such as for unit test projects, which don’t need API documentation)
  • Modifications to StyleCop settings are stored in central settings files and shared across projects. For example, I have a TestProjectSettings.StyleCop file, which contains settings for unit and integration test projects. If I disable a rule for one test project, it is disabled for all of them

The intent of this post is not to help you set StyleCop up with MSBuild. There are other resources out there that show you how to do that. I’m more interested in encouraging people to try this tool out. The more people that use it, the more it will be improved. And there is plenty of scope for improvement, as I’ll discuss shortly. If you’ve held off trying out this tool because you had bad experiences with it earlier in its short history, or because you think it has little to offer, perhaps it’s time to rethink.

So, what are the problems I’ve had using StyleCop? The biggest problem is that it’s lazy. It will happily report style problems to you any day of the week – even Sunday – but it refuses to lift a finger when it comes to rectifying said problems. This can be very irritating at first, but over time I have found myself preemptively and reflexively avoiding StyleCop’s wrath by writing code that conforms more and more to the default rule set.

The next problem is that of the default rule set. In adopting StyleCop I made it quite clear to my client that doing so implies either accepting the default rules, or spending a significant amount of time writing custom ones (time I don’t have). I can almost guarantee you won’t like all the default rules. Some of them will make you cringe, whilst others may make you downright furious. Of course, you can disable or tweak those rules that really get your goat.

Finally, StyleCop is particularly frustrating when you’re just wanting to try out a piece of code quickly in your project. There’s no built-in mechanism to demarcate a block of code as temporary and exempt it from style checks. Undef’ing the CODE_ANALYSIS symbol seems to do nothing, and SuppressMessage does not have any wildcard support. Therefore, you either need to move your scratch code into a temporary project, or waste time placating StyleCop.

UPDATE: As noted by wekempf in the comment below, you can wrap experimental code in a region with “generated code” in its name. This works even when you have the disallow all regions StyleCop rule enabled!

But for all its warts, I still feel somewhat liberated by StyleCop. No longer do I worry about whether I have the correct spacing, line breaks, or bracket placement in my source. I let the tool worry about that for me. And I feel as though spending the extra brain cycles on more important concerns is a win for both myself and my client.

Note that I am the only .NET developer on my project at the moment, so I can’t really comment on how well this would work with a team. I can’t really see it being an issue if everyone agrees that no rules should be disabled or suppressed without due justification and discussion. Some developers are sure to balk at the idea of having to conform to a particular style, but that’s only because it’s not their style. Heck, I was hesitant at first to make dramatic changes to my style (I prefer tabs, for example), but I quickly adjusted when I saw the benefits of the tool.

So next time you’re embarking on a new project, consider integrating StyleCop right from the get-go. The short term may be painful, but I think you’ll appreciate the decision in the long term.

Tuesday, September 22, 2009

VM Keyboard Rate Limited by Host

Seems obvious when you think about it, but I thought it worth pointing out all the same. If you’re trying to up the ante on your keyboard settings inside a VM, be aware that their effect will be limited by the the keyboard settings on the host.

So if you set your VM’s keyboard to repeat crazy fast:

image

But your host is set to crazy slow:

image

The effective result in your VM is crazy slow. That’s because the host will only be passing on keyboard events to the VM in crazy slow mode, so the keyboard settings in the VM are essentially moot.

Monday, August 24, 2009

Ubuntu, SSH, and Remote Support

Having a job in IT can sometimes be a curse. To mere mortals, the whole world of things that go beep is lumped together in a box labelled “voodoo”. Any issue even remotely related to computers can be directed your way. The typical geek probably finds themselves having to deal with document formatting problems, faulty mobile phones, and friends who can’t remember their email address. Can you imagine asking a cardiologist to examine your foot? No? Me neither.

My Mum – who runs Ubuntu – asked me for some help with her webcam the other day and I felt compelled to help her because:

  1. She’s my Mum.
  2. I got her onto Ubuntu in the first place and set it all up for her.
  3. She’s my Mum.

The problem is that she lives in the sleepy town of Adelaide whilst I live in London, some 16,000 kilometres away.

Now, if we were using Windows I’d have used a service like CrossLoop to remote onto her machine. I’ve used it in the past to help my sister with her machine, and it was very good. Basically, CrossLoop works by acting as a middle-man between the two machines, so instead of connecting directly to each other, they connect to a CrossLoop server. This helps get around all the issues with firewalls and ports that the average computer user shouldn’t have to understand. Of course, it implies that you trust CrossLoop not to snoop on any data exchanged between the machines.

Alas, CrossLoop is Windows and Mac only – no love for the world of Linux. Moreover, I couldn’t find an alternative service at all for Ubuntu. To that end, I set about looking for something that would allow me to help my Mum. My requirements were simple enough:

  1. Must be secure.
  2. Must require no effort by my Mum except running a script. And when I say “no effort” I really mean that. Requiring any kind of router configuration or software configuration, for example, would be a deal-breaker. If I asked my Mum to open a port, she’d tell me it was too early in the day to drink (yes, even if it was 9PM).

After some reading and testing on my end, I settled on a solution using the most excellent SSH protocol. The key for me was SSH’s ability to set up a reverse connection. This allowed me to set up the SSH server and configure my router to do the port forwarding. Then I provided my Mum with a script that simply:

  1. Kills any resident VNC session.
  2. Starts up a new VNC session.
  3. Sets up a reverse SSH tunnel to my machine, forwarding traffic on my port 9999 to the relevant VNC port on her side (5901). Having your own DNS entry helps here, but isn’t strictly required if you don’t mind validating the port in the script every time you use it (again, not an option for my Mum).

Once she runs that script, I can run a VNC client and connect to port 9999 on my local machine. By virtue of the SSH tunnel, I’m actually connecting to port 5901 on her machine, which is the VNC session. Magic!

The whole setup can be depicted graphically as follows (click to enlarge):

imageSo there you have it. When my Mum has issues, she double-clicks a file on her desktop, enters a password (although you can use keys instead), and I can then connect to her desktop and hopefully sort it out. Now you, too, can provide remote support for your Mum’s Ubuntu installation.

Now all I have to do is fix her foot – I mean, webcam!

OK, OK, Linux haters – perhaps if my Mum was using Windows the webcam would be working just fine and this whole post would be moot. Instead I might be posting about how I had to rescue her machine from the clutches of malware.

OK, OK, Linux and Windows haters – perhaps if my Mum was using a Mac I’d be able to use CrossLoop and this whole post would be moot. Instead I might be posting about how I had to loan my Mum some money so she could buy milk and bread.

Addendum: I had an issue with the keyboard mappings with VNC. Basically, I would type “abcd” and would get “asdf” on the remote machine. Turns out this is a known issue and I found this blog post on the subject. It was a comment by dcatdemon on that post that helped me:

  1. Edit your $HOME/.vnc/xstartup
  2. Put the line "export XKL_XMODMAP_DISABLE=1" before your gnome-session
  3. Restart vncserver

Note to Self: regarding the actual webcam, I had to recompile and reinstall the driver. When I set up Ubuntu originally for Mum I had to manually compile the driver because there was no built-in support for her webcam. Presumably, the latest kernel update had somehow broken backwards compatibility and the driver was no longer successfully being loaded. So I removed the old .ko driver binary from /lib/modules/kernel*/drivers/media/video/usbvideo/ and then recompiled and reinstalled according to here.

I suppose this may happen after future kernel updates, too. Lucky I have that support script all set up!

Saturday, June 20, 2009

Truss V1.0.0.0 Released

Abstract Bindings.Single Source Bindings I have just released version 1 of Truss, a binding framework for POCOs. Truss allows you to bind together arbitrary .NET objects regardless of your choice of UI platform, or in the absence of a UI altogether.

Amongst its features, it provides support for bindings that use “magic strings” to specify property paths, as well as lambda expressions for compile-time checked bindings. Here’s a very simple example to whet your appetite:

var parent = new Person();
var child = new Person();
var bm = new BindingManager();

//bind the parent's savings to the child's inheritance
bm.Bindings.Add(new TypedBinding<Person, Person>(parent, p => p.Savings, child, c => c.Inheritance));

There are a number of scenarios I intend Truss to address, both now and with future enhancements:

  • Keeping related view models POCOs in sync with each other
  • Keeping related business objects in sync with each other
  • Provide a strong alternative to the limited binding support in Winforms, thus facilitating clean MVVM development in Winforms

You can download Truss source, binaries, and comprehensive documentation from here. Please direct any feedback my way.

Thursday, June 11, 2009

Search and Highlight Text in an Arbitrary Visual Tree

Download Example Project

image A while back I answered this question on stackoverflow and have been meaning to elaborate on my answer ever since with a more comprehensive blog post. The question is about how to highlight some text in the UI when the user enters some search text. I thought I’d extend the concept into a clean, generic solution as far as I could and share it here.

My requirements are pretty straightforward:

  1. Provide a search box in which the user can enter some text.
  2. Highlight all matching text in the window, regardless of where it appears in the visual tree.

imageI was able to pull this off to an extent I am satisfied with. See the screenshot to the left. The user can enter some text in the top-right search text box, and then hit enter (or click the magnifying glass). Then all matching text is highlighted anywhere in the visual tree.

After an initial approach that relied on reflection in order to highlight content elements (ugh!), Marlon Grech kindly passed my question about how to do this more cleanly onto Dr. WPF and Jamie Rodriguez, who pointed me in the right direction (thanks guys!).

The basic approach I ended up using is:

  1. Traverse the visual tree recursively, looking for IContentHosts and DocumentViewerBases. For DocumentViewerBases, extract the IContentHosts corresponding to each page.
  2. For each IContentHost, search through its HostedElements collection to find any Runs.
  3. For each Run, inspect its Text to determine whether the search term matches.
  4. If the search term matches, use some TextPointer trickery to determine the bounding rectangle of the text.
  5. Use a Canvas to lay out all semi-transparent rectangles on top of the application window, thus highlighting the matches.

There are a few problems that I’m aware of:

  1. If the matching text spans multiple lines, the bounding rectangle isn’t correctly calculated. You could use IContentHost.GetRectangles to calculate all bounding rectangles correctly, but I just haven’t bothered to do so for the purposes of this post.
  2. It doesn’t work for all content element hosts, such as FlowDocumentScrollViewer, because they don’t inherit from DocumentViewerBase. I suspect it’s probably not too hard to add support for them, but again I haven’t bothered to do so for this example.
  3. It’s quite slow when the search term is short and frequently matched (as an example, try searching for “a”).

So the approach isn’t perfect, but this was an experiment more than anything else. I think a real application would want search support more intrinsic rather than relying on a generic mechanism like this. That said, there are bound to be some practical applications of the general technique used here.

PS. You may have noticed a lack of TMNT-related material in my sample this post. Unfortunately, my Windows Home Server recently died, which has prevented me from continuing to watch the series and has let my obsession waver somewhat. A replacement server is due next week, so expect more green reptile-based content soon!

Download Example Project

Thursday, May 07, 2009

MVVM Infrastructure: ActiveAwareCommand

Download Example Project

This post is part of a short series I am doing on MVVM infrastructure. In this series, I will share some thinking and code that has helped to produce cleaner, simpler MVVM code in my applications.

Related posts:

  1. POCOs versus DependencyObjects
  2. ViewModel
  3. DelegateCommand
  4. ActiveAwareCommand

In my last post I discussed the DelegateCommand, which allows you to associate a WPF command directly with logic in your view model. In this post I am going to talk about the ActiveAwareCommand, which does exactly the same thing, but it enables you to widen the scope from which the command is used.

The DelegateCommand works great when the command source (such as a Button) has a one-to-one relationship with the view model. For example, recall the customers example from the previous post (see right). The Add and Delete buttons are defined in the CustomersView. Since the CustomersView has a one-to-one relationship with the CustomersViewModel, the Buttons also have a one-to-one relationship.

But suppose we wanted to change the Add and Delete buttons to MenuItems, and re-use those MenuItems across multiple views. Essentially, we want to change the one-to-one relationship between command source and view model to a one-to-many relationship. With DelegateCommands, the MenuItems would be intimately tied to a particular view. Therefore, the best effort would result with multiple Add and Delete entries in the Menu – one for each view that supports adding and deleting items. We’d have to distinguish the MenuItems with unique headers, such as “Add Customer” and “Add Order”. Obviously, that would result in a horrible user experience.

ActiveAwareCommand provides a solution to this little dilemma by maintaining a list of potential targets for the command, and only interacting with the active target (if there is one). Each potential target is an implementation of IActiveAware, and the ActiveAwareCommand uses the IsActiveChanged event on this interface to track the active target. The ActiveAwareCommand belongs to a single view model but maps to any number of command sources, thus fulfilling the one-to-many relationship we seek.

The IActiveAware interface gives you the freedom to use whatever logic you like to determine whether the potential target is active. However, it is likely that you will most often use focus to activate an item. To that end, the FocusActiveAwareAdapter wraps a FrameworkElement and gives you an implementation of IActiveAware whose IsActive property is changed to true when the FrameworkElement gets focus, and false when it loses focus.

Generally speaking, the steps for using an ActiveAwareCommand are:

  1. Construct an instance of ActiveAwareCommand, usually as a public static readonly member of a view model class.
  2. In your view model class, expose a property that allows the view to provide an IActiveAware implementation to monitor. This property should register and unregister the IActiveAware implementation with the ActiveAwareCommand.
  3. In your view, pass an implementation of IActiveAware to the view model when the view loads. Usually this will involve constructing an instance of FocusActiveAwareAdapter that wraps the view.
  4. Bind to the ActiveAwareCommand from a shared piece of screen real estate, such as the main menu or application ribbon.

To demonstrate the use of ActiveAwareCommand, I put together another TMNT-related sample project (I’m totally scoping the 2003 era series, like, start to finish at the moment, dudes). In it, the user is able to edit the details of any number of characters in separate tabs. Each character can be saved independently of the others from both the main menu and a tool bar button. Since an ActiveAwareCommand is used for the save functionality, the command is correctly routed to the active tab without any need for manual redirection by the views.

I may have gone a bit overboard with the sample project. I initially started out writing a simpler example, but I found myself wanting something a bit more substantial and real-world. Anyway, feel free to ignore most of the code and just concentrate on the parts pertinent to this post.

I think that about wraps up my series on MVVM infrastructure – for now at least. I hope it has been of some use. I’ve got some other things in mind that I want to blog about, but I’m on leave in Australia through to June. Until then…

† Prism has a similar interface, but it is used for different purposes. Same goes for Prism’s CompositeCommand, which is used to broadcast a command to multiple handlers, as opposed to unicasting only to the active handler.

Download Example Project

Sunday, April 19, 2009

MVVM Infrastructure: DelegateCommand

Download Command.cs
Download DelegateCommand.cs
Download DelegateCommandExample.zip

This post is part of a short series I am doing on MVVM infrastructure. In this series, I will share some thinking and code that has helped to produce cleaner, simpler MVVM code in my applications.

Related posts:

  1. POCOs versus DependencyObjects
  2. ViewModel
  3. DelegateCommand
  4. ActiveAwareCommand

In my last post I discussed my ViewModel base class. In this post I’m going to start showing you some infrastructure around commanding.

WPF's commanding support enables you to hook up UI interactions with code without tightly coupling the two. User actions are abstracted into implementations of WPF’s ICommand interface, which are then associated with controls that implement ICommandSource. Essentially, it's a layer of indirection. The controls in the UI aren't intimately aware of the command logic they are connected with, and the command logic isn't aware of the controls it will be associated with.

When starting out with WPF commanding, you will soon come across the RoutedCommand class. This particular command is yet another layer of indirection, in that its execution logic involves finding something to execute and calling that! Starting with the focused element, it searches up the visual tree for an element that has a matching CommandBinding in its CommandBindings collection. If the RoutedCommand finds a matching CommandBinding, it executes that CommandBinding's Executed delegate.

Routed commands work great in certain scenarios, and are prevalent in WPF. Indeed, the only concrete ICommand implementation that comes with WPF is the RoutedCommand (and its subclass, RoutedUICommand). Unfortunately, this has caused WPF commanding to become somewhat synonymous with RoutedCommands, which is not at all accurate.

image The thing is, routed commands are not always a great fit for MVVM development. Typically the logic for your command execution belongs in the view model. For example, suppose you have a CustomersViewModel that maintains a list of CustomerViewModels, and you want to expose a command that deletes the selected customer. The logic for that command should reside in the CustomersViewModel, since it knows best what to do when a deletion is requested.

If you were to use a RoutedCommand, you would then need a CommandBinding somewhere in the UI in order to connect a visual element to the DeleteCustomerCommand. In our example, we would likely stick a CommandBinding in the CustomersView and associate it with the deletion command and methods on the view model. Without the CommandBinding, the RoutedCommand won't find a handler for the command and the Delete button will be forever disabled.

Using routed commands with MVVM ends up being messy, sub-optimal, and requires the view be more tightly coupled to the view model. And in some scenarios, it’s not even possible (I’ll discuss such a scenario in my next post). But the good news is, we don't have to use routed commands. All we need is an appropriate implementation of ICommand – one that is more conducive to MVVM development.

imageIf you think about it, all we really want to do is have a command that – when executed – invokes a method in our view model. And when the command is queried for its executable status, it executes a different method in the view model. To continue our customer example, that command might be associated with a Button in our CustomersView. The availability of the command would be dependent upon the user first selecting a customer (you can't delete a customer if you don't know which customer to delete). The execution of the command might execute a DeleteCustomer method on the CustomersViewModel.

Sound simple? That's because it is! Far simpler than attempting to use routed commands for this scenario.

The command implementation I use is called DelegateCommand, simply because it invokes delegates when executing and querying executable status. Other people have different names for this type of command, the most common of which seems to be RelayCommand. That's fine - call it what you will.

Prism has a DelegateCommand too, which is almost exactly the same as this one. However, the reason I have my own is simply because we don't use Prism in our project, and it would be a large overhead to pull it in just for the sake of a class or two. Besides, if you're doing a non-composite WPF app, Prism may not be a good fit.

To create a DelegateCommand, you simply give it one or two delegates to use. If you give it only one delegate, the command is assumed to be always available. That is, ICommand.CanExecute() will always return true.

In our CustomersViewModel, we create the DelegateCommand as follows:

_deleteCustomerCommand = new DelegateCommand(DeleteCustomer, CanDeleteCustomer);

We then expose the command from a property in our view model:

public ICommand DeleteCustomersCommand
{
    get { return _deleteCustomerCommand; }
}

And bind to it in the view:

<Button Command="{Binding DeleteCustomersCommand}">Delete</Button>

It’s as simple as that. The delegates supplied to the DelegateCommand will be invoked at the appropriate times and our Delete button will only be enabled when a customer is selected. You can see all this and more in the download.

Incidentally, DelegateCommand inherits from a base Command class. That’s just to keep the code DRY with respect to other command classes I have, such as the ActiveAwareCommand. I’ll talk about that one in the next post.

† The application in question was built before Prism shipped, elsewise we would be.

Download Command.cs
Download DelegateCommand.cs
Download DelegateCommandExample.zip