July 2008 - Posts
Decided to get NDepend dealt with. I've been fortunate in that I've had a professional license but time has been of short supply in the last few months to be playing with something as cool and as big as NDepend. So here starts a series of posts on NDepend. My code base of choice is the Subtext blogging platform that I'm a contributor to.
Starting with NDepend is incredibly simple. The startup screen has a very "Visual Studio" type feel. Click "New Project", give it a name and we're presented with this screen:
The easiest way to start from here, is to immediately add your assemblies to the project that you want to analyse. As you can see below, I've now added the Subtext assemblies. Note the checkboxes in the left hand panel. You can easily see that none of my assemblies have strong names but NDepend has picked up that there are PDB files that can be used for later analysis such as LOC counts.
For this post, we won't deal with Analysis Comparison or Code coverage and move straight onto the Reports tab. This gives you some options on what reports you want to generate and the option to use your own XSL sheet in the report build. Once you've set your settings here, you're ready to go! Click the play button and let NDepend generate the results.
Once the analysis is done, a web page will pop open with the core information inside (I've attached a sample here for you to have a look at). NDepend will simultaneously change to a drill-down type display where you can view results to your heart's content.
Once you're in this view, the power of NDepend starts to show. Everything is contextual, from the dependencies view, the metrics view to the assembly info panel, you have complete control of what you want to analyse.
The Class Browser shows all the assemblies that you've chosen plus all external dependencies (in blue). Hovering over the assembly or drilling down into classes or even methods, the info panel updates, the metrics will display the position of the selected item. Very quickly you can see important information. As an example, the Subtext BlogRequest HttpModule has 71 IL instructions, 12 lines of code, 19 comments and a cyclometric complexity of 9. Awesome stuff, and a great UI.
I'm going to leave the post here. I'm wanting to deep dive into each feature and would prefer to spread each feature over a separate blog post. Keep subscribed for the next instalment. :)
In a medium sized project I'm working on at the moment, we've had a rather large memory leak issue. We've implemented our tiers in a pattern called MVVM. I wasn't sure on how well this would work but to be honest, its been an amazing pattern to follow and pretty easy to get right.
Our UI exclusively does binding, I.e. there is no real code behind. Our buttons are bound to commands, ItemsControls bound to ObservableCollection<T> and inputs bound to properties on our ViewModels. Pretty simple stuff and extremely powerful. During testing of the application, switching in between items in a ItemsControl, the RAM usage would go up. And up. And up. Until we hit 800MB of RAM and the system would start thrashing and be unresponsive. After further investigation, it was down to buttons that were binding to ICommands. As the button was in a template in the ItemsControl, each time we changed the selected Item, the datatemplate was being instanciated and therefore a new button instance was being created inside the framework.
1: <ItemsControl ItemsSource="{Binding Property=DataToBindTo}" >
2: <ItemsControl.ItemTemplate>
3: <DataTemplate>
4: <Button Command="{Binding Property=RunCommand}" />
5: </DataTemplate>
6: </ItemsControl.ItemTemplate>
7: </ItemsControl>
Above is a very simple example of the scenario I have. In the Button Control which extends ButtonBase, whenever the Command's DependencyProperty is changed, a callback is fired which is supposed to remove any handlers from the command's CanExecute EventHandler. However, the code to Unhook these event handlers NEVER seems to run, so the Button is therefore NEVER released and stays in memory.
1: private void OnCommandChanged(ICommand oldCommand, ICommand newCommand)
2: {
3: if (oldCommand != null)
4: {
5: this.UnhookCommand(oldCommand);
6: }
7: if (newCommand != null)
8: {
9: this.HookCommand(newCommand);
10: }
11: }
The code above is from the WPF code base inside PresentationFramework.dll. In researching this bug on the Internet, a few posts mentioned clearing the command bindings. This would set the Command in the Button to null, which in turn, the OnCommandChanged method would be called. Line 3 and 5 are important here, since the oldCommand is not null, it will be unhooked. However, because the UI has no code behind, we can't clear the bindings in code without some serious hacking.
To get round this bug, we ended up implementing our own Button object, extending ContentControl and writing our own keyboard and mouse events to handle executing the command. Please note, this is on 3.5 without the SP1 beta installed so things may change when this goes RTM.
