Composite Application Block MdiWorkspace Sample


As has been noted on some other blogs, there is no sample provided for the MdiWorkspace in the Composite Application Block. There are a couple of examples elsewhere, but these seem a little overcomplicated, and I had difficulty getting them running. Also there doesn’t seem to be an example that shows how to use a SmartPartInfo object with the MdiWorkspace.

As a result I have put together a simplified MDI workspace example.

The Application

The screenshot below shows this running. Every time you hit File/New a new child window appears in the parent:



The code for this contains a bog-standard form (‘MdiForm’) and user control (‘ChildControl’). The form has a MenuStrip on it, with a ‘File’ menu item at the top level, and then a ‘New’ menu item in the drop down from ‘File’. There’s no user-entered code in the user control or the form.

The application is started using a standard CAB ShellApp class, with the MdiForm used as the shell form. This has functionality in the ‘AfterShellCreated’ method to hook up a CommandHandler to the ‘New’ menu item, and to instantiate an MdiWorkspace on the shell form as below:

public class ShellApp : FormShellApplication<WorkItem, MdiForm>
    public static void Main()
        new ShellApp().Run();
    protected override void AfterShellCreated()
        // Get a reference to the New' menu item already on the menu
        ToolStripMenuItem fileToolStripMenuItem = (ToolStripMenuItem)Shell.MainMenuStrip.Items["fileToolStripMenuItem"];
        ToolStripMenuItem newToolStripMenuItem = (ToolStripMenuItem)fileToolStripMenuItem.DropDownItems["newToolStripMenuItem"];

        // Hook up the FileNew command (in CommandHandlers) to the click event of
        // the New menu item
        RootWorkItem.Commands["FileNew"].AddInvoker(newToolStripMenuItem, "Click");
        // Create an MdiWorkspace in the shell
        RootWorkItem.Workspaces.Add(new MdiWorkspace(Shell), "MdiWorkspace");

Finally a CommandHandlers class contains the handler for the ‘New’ menu item as below. This adds a new ChildControl to the WorkItem for the application, and then shows it in the MdiWorkspace. It also instantiate a WindowSmartPartInfo object and sets a few random properties of the child control using it:

public class CommandHandlers
    private WorkItem workItem;
    public CommandHandlers([ServiceDependency] WorkItem workItem)
        this.workItem = workItem;
    public void OnFileNew(object sender, EventArgs e)
        IWorkspace mdiWorkspace = workItem.Workspaces["MdiWorkspace"];
        ChildControl childControl = this.workItem.Items.AddNew<ChildControl>();
        // A SmartPartInfo object lets you set various properties of the child control
        // you are displaying, relative to the workspace it's being shown in.
        // The WindowSmartPartInfo is used by the MdiWorkspace, and lets you set stuff
        // like caption, location, icon, size, and whether minimize/maximize/control boxes are present.
        WindowSmartPartInfo smartPartInfo = new WindowSmartPartInfo();
        smartPartInfo.Title = "Child Form";
        smartPartInfo.Location = new System.Drawing.Point(10, 10);
        smartPartInfo.ControlBox = false;
        mdiWorkspace.Show(childControl, smartPartInfo);

The code is available for download.



Introduction to Dependency Injection (Introduction to CAB/SCSF Part 3)


This article is actually part 3 of an introductory series of articles on Microsoft’s Composite Application Block (CAB) and Smart Client Software Factory (SCSF). However, this particular article will only talk about dependency injection in general terms and not discuss the CAB/SCSF. Part 5 of the series will address dependency injection in the CAB. Part 4 of the series expands the discussion here by talking about inversion of control (IoC) and dependency inversion.

Dependency Injection

Dependency injection as a general concept is explained far better than I could do it by Martin Fowler at However, in short it is a means of allowing a main class to use a second, dependent class without directly referencing that class. Some external entity will provide the second class to the main class at runtime – it will ‘inject’ the ‘dependency’. Obviously to be useful the second class will need to implement an interface that the main class knows about.

The aim of this is to let us change the behaviour of our class structure by changing which second class is injected into the main class. Because the main class has no hard dependency on the second class this can be done at runtime. Thus our code is very flexible, easy to modify and loosely coupled.

Class Diagram

The class diagram looks something like this:

Dependency Injection Class Diagram

MainClass contains a reference to an object that implements IDependentClass, and can thus call the DoSomethingInDependentClass method on that object. DependentClass1, DependentClass2, and DependentClass3 implement the interface.

Some client code will then create the appropriate dependent class and tell the main class to use it (via the interface). It’s easiest to understand this via some example code, which I’ll demonstrate below.

Strategy Pattern?

In many ways this is the classic Gang of Four Strategy pattern with a twist. The class diagram above is very similar to the usual one given for the strategy pattern: see (don’t worry if you don’t know the strategy pattern at this stage though). The difference is that with dependency injection exactly which class is going to be provided as the dependency (strategy) is often left to configuration at runtime. That is, it can be abstracted out of the code entirely.

In the Spring framework, for example, XML configuration files can be used to specify which class gets created and used. This is an extreme example of deciding which class to use at runtime: you can change the dependencies without changing the compiled code at all.

However, there are some reasons for not using external configuration files to specify these dependencies: it makes it difficult to debug, and you’re probably not going to want to change application behaviour via a configuration file in any case. Dependency injection frameworks in general will allow you to specify your injection in code (Spring allows this).

Dependency Injection Example

We can easily create an example that does this using .NET. Full code for all these examples is available for download.

Firstly we create an interface that will be used to call our dependent class:

    public interface IDependentClass
        void DoSomethingInDependentClass();

Then we create dependent classes that implement this interface to do something. Which one of these classes will actually be used will only be decided at runtime based on a setting in the App.Config file:

    public class DependentClass1 : IDependentClass
        public void DoSomethingInDependentClass()
            Console.WriteLine("Hello from DependentClass1: I can be injected into MainClass");
    public class DependentClass2 : IDependentClass
        public void DoSomethingInDependentClass()
            Console.WriteLine("Hello from DependentClass2: I can be injected as well, just change App.Config");

Now we create a class that will use the dependent classes, calling their functionality via the interface. This ‘main’ class has no knowledge of the dependent classes types, only of the interface that they implement:

    public class MainClass
        IDependentClass dependentClass;
        public IDependentClass DependentClass { get { return dependentClass; } set { dependentClass = value; } }
        public void DoSomething()

Now we need some code that will use this structure. Clearly we need to instantiate the main class and tell it (using the interface) which dependent class to use. We can then call the functionality on the main class.

        static void Main(string[] args)
            // Get the correct dependency based on configuration file
            IDependentClass dependency = GetCorrectDependency();
            // Create our main class and inject the dependency
            MainClass mainClass = new MainClass();
            mainClass.DependentClass = dependency;
            // Use the main class, the method references the dependency
            // so behaviour depends on the configuration file

Finally we need some code in GetCorrectDependency() that decides which dependent class we are going to use, and instantiates it. We do this by examining the ‘ClassName’ setting in App.Config, and instantiating that using Activator.CreateInstance:

        static IDependentClass GetCorrectDependency()
            string classToCreate = System.Configuration.ConfigurationManager.AppSettings["ClassName"];
            Type type = System.Type.GetType(classToCreate);
            IDependentClass dependency = (IDependentClass)Activator.CreateInstance(type);
            return dependency;

The App.Config file is as below:

<?xml version="1.0" encoding="utf-8" ?>
    <add key="ClassName" value="DependencyInjection.DependentClass1" />

So we can compile this code and run it as above and it will output the message in DependentClass1. If we then just change the configuration file so that the ClassName value is DependencyInjection.DependentClass2 and re-run the code will output the message in DependentClass2.

Note that what is powerful about this code is we could write a DependentClass3, with new behaviour, and use it by changing the configuration file without the need to change any of the existing code.

Types of Dependency Injection

Martin Fowler’s article talks about three different types of dependency injection: constructor injection, interface injection and setter injection. The example above uses setter injection: we give the main class its dependency via a setter in the line:

mainClass.DependentClass = dependency;

In constructor injection we give the main class its dependency in the constructor. With interface injection we define another interface that the main class will implement that sets the dependency.

I have reworked the example above for both constructor injection and interface injection. As you can see these are relatively trivial changes in this simple example.

Full C# code for these examples is available.

This series of articles is continued in part 4, which discusses inversion of control.

Two Philosophers Problem

A problem doing the rounds (way too hard for an interview question though):

There are 2 numbers between 1 and 100 (not including 1 or 100, and they are different).
Socrates knows their sum. Plato knows their product.
Socrates knows that Plato knows the product.
Plato knows that Socrates knows the sum.

They meet and talk…
Socrates says “I don’t know the numbers, but neither do you”
Plato says “Now I know them”
Socrates says “Me too”.

What are the numbers?

I did a solution in C#.

An Introduction to the Smart Client Software Factory and Composite Application Block: Part 2 WorkItems


In part 1 of this article I introduced a simple example of how to use Microsoft’s Composite Application Block. To try to keep the example as simple as possible I only covered modules and shells.

There are two other core concepts that you need to understand to be able to use even the most basic functionality of the CAB. These are WorkItems, and dependency injection. This part of the article will discuss WorkItems, and part 3 will discuss dependency injection.

WorkItems – Basic Concepts

Microsoft’s documentation defines a WorkItem as ‘a run-time container of components that are collaborating to fulfill a use case’. In many ways the best way to think of them is as classes that contain collections of other classes that are logically grouped together. The name is a little strange: ‘work items’ in general tend to be individual tasks that need to be performed in, say, a workflow, or, in the .NET Framework, in a thread pool. The WorkItems in the CAB are broader than that.

In code terms WorkItems are just objects of type ‘WorkItem’ (a class in the Microsoft.Patterns.CompositeUI library). Each WorkItem has collection classes associated with it to allow it to ‘contain’ components. Three of these collection classes that are reasonably easy to understand are:

  1. The Items collection, which can contain almost anything since it’s a (special) collection of System.Objects
  2. The Services collection, which is a collection of CAB services.
  3. The WorkItems collection, which is a collection of other ‘child’ WorkItems.

However there are several other collections of CAB code objects on the WorkItem class. WorkItems also have state (used to track changes), and status (active/inactive).

Container Hierarchy and the Root WorkItem

There’s a second important aspect of WorkItems: they can be arranged into a hierarchy. This hierarchy typically starts with a root WorkItem that contains components (code objects) and other WorkItems, the other WorkItems again can contain components and other WorkItems, and so on.

This is particularly useful since we can construct the hierarchy across modules, even though the individual modules may not reference each other. We can then use the WorkItem hierarchy to use components in other modules.

I’ll show exactly how this works in a minute, but in our example from part 1 we could add a WorkItem class to each of our three projects. We could then instantiate one WorkItem object per project at runtime. The WorkItem object in the Shell program could be a root WorkItem. It could contain the other two WorkItems.

If we add a component from the Shell project to the root WorkItem we can access that from, say, the Red application’s WorkItem by simply using this.ParentWorkItem.Items[“ComponentName”].

One obvious difficulty with this approach is that we are then tightly-coupling our two modules together to some extent, which is what we were trying to avoid by not having direct dependencies between our modules. However, as we’ll see we can still release new versions of each module independently of the rest of the code.

WorkItems and the FormShellApplication

In part 1 of this article we saw that to start a CAB application we inherit from FormShellApplication<,>. We provide two types when we declare the new class to close the generic definition:

    public class Program : FormShellApplication<WorkItem, Form1>

As we have seen the second of these (Form1) is the shell for the application and gets instantiated and shown at start up (when we do new Program().Run()). The WorkItem also gets instantiated at start up. This will be the root WorkItem for the application, sitting at the top of the hierarchy described above. It can be referred to in the Program class using the RootWorkItem property (this.RootWorkItem).

To be continued in part 3.

An Introduction to the Smart Client Software Factory and Composite Application Block: Part 1 Modules and Shells


Microsoft’s Smart Client Software Factory (SCSF) and associated application blocks are excellent pieces of software. However, for a developer coming to them for the first time they can be extremely daunting. There are many things that can be confusing. Firstly we have modules, workitems, workspaces, and shells, all of which sound similar. Then there’s dependency injection, command patterns, event brokers, model-view-presenter patterns and other high-level concepts, none of which are easy to understand. There’s a load of other concepts as well, multiple example applications, and plenty of documentation. Microsoft’s documentation has a very steep learning curve indeed.

I’m going to write a series of short articles that assume you are a developer coming to this for the first time and are confused as I was. To do this I’m going to focus on one or two basic concepts in each article. There’s quite a lot of blogging about CAB/SCSF on the web, but I couldn’t find anything that gave me a quick, basic introduction with a gentle learning curve. This is what I will try to achieve here.

To start I’m going to look at the basic set up of modules and shells in the Composite Application Block. This is the starting point for most SCSF projects. I’m not going to cover WorkItems until my second article as I found them quite confusing initially.


For this example you only need download the code. This contains the CAB dlls it needs to run.

Composite Application Block

The starting point for many developers coming to the Composite Application Block (CAB) is the need to either

1. To design a complex user interface that has some kind of separate components that can be developed and released independently, or
2. To take several existing user interface applications and combine them in such a way that they can continue to be developed independently, but appear in the same window with common menus etc and can interoperate on some level.

This is certainly where I started. The key point in both cases is that if we want our components to be released independently then they can’t have direct references to each other. In short we want ‘applications’ or components that appear in the same user interface (same window) with common menus and some ability to talk to each other, but don’t directly reference each other.

The CAB allows us to do this. It clearly offers us a lot more than just this, but in this article I will show the basics.

Modules and Shells

The first concept you need to understand for this is that of a ‘module’. This is what I am referring to as a ‘application’ or ‘component’ in the paragraph above: a block of code, usually with a user interface that can be displayed in a common window, but which doesn’t reference other modules. In reality these are separate .NET projects within our solution that don’t reference each other.

The second concept is that of the ‘shell’. This is simply the ‘common window’ I’m referring to in the paragraph above. It will contain our modules, or at least the visual parts of them. In reality the shell is usually contained in its own .NET project, but one that doesn’t reference any of the modules, nor is referenced by them.

So, simplistically:

Module = standalone project to be used in a composite user interface
Shell = the host form for the composite user interface

Our Example

Let’s start with a really simple example. Assume we have a C# project that just displays a red form, and another separate project that just displays a blue form. These are going to be our two modules. Then we want a third project to contain a shell, which in this case will just be another form that we want displayed. To keep this example really simple we won’t try to display the red and blue forms actually inside the shell: this will be done in part 2.

The difficult bit is that although all these projects will be in the same solution, none of them will reference each other directly, yet all three forms will display at start up. Obviously we could do this fairly simply with reflection, but we will use the CAB to do it.

Naïve Application Example

The code for this example is available.

To implement the example:

1. We set up three projects (all Windows applications) in a solution. We’ll call these Red, Blue, and Shell. For the Red and Blue projects (which will be our modules) we simply change the BackColor property of the form to red and blue as appropriate.
2. We add references to the CAB dlls (Microsoft.Practices.CompositeUI.dll, .Practices.CompositeUI.WinForms.dll, and Microsoft.Practices.ObjectBuilder.dll) to all three of the projects. We also make sure all three build into the same build directory (via the Properties/Build tab). Shell is the startup project.
3. Now if we run the projects all three will build, but clearly only the form from the Shell project will get displayed, since that is the start up project. We need to tell the other modules to show their forms. To do this we change Program.cs in Shell (our start up code) to inherit from FormShellApplication<,> as below:

 using System;
 using Microsoft.Practices.CompositeUI.WinForms;
 using Microsoft.Practices.CompositeUI;       

 namespace Shell
     public class Program : FormShellApplication<WorkItem, Form1>
         static void Main()
             new Program().Run();

The two types passed in to FormShellApplication<,> both get instantiated when Program is instantiated and .Run() is called (this calls into the base classes clearly). Form1 is our shell form and gets displayed, WorkItem I will discuss in part 2. After this change the application will still only display the MDI form, but the .Run() call will enable us to show the other two screens with some other simple changes.

4. In fact the application is now looking for an XML file telling it what other modules to load. Again this happens as a result of the call to .Run(). The XML file has to be called ProfileCatalog.xml, has to be copied always into the output directory, and has to look like the XML below:

<?xml version="1.0" encoding="utf-8" ?>
<SolutionProfile xmlns="">
    <ModuleInfo AssemblyFile="Red.exe" />
    <ModuleInfo AssemblyFile="Blue.exe" />

We add this file to the Shell project. Now if you get the names of the modules wrong and then run the application it will throw an exception, showing that it’s trying to find the relevant files.

5. Finally we need something in the Red and Blue projects that will actually run as a result of this (the CAB doesn’t just call the usual start up code). We can do this by adding a class that inherits from Microsoft.Practices.CompositeUI.ModuleInit and overrides its Load() method. The CAB code will call this Load method from the .Run() call above:

using Microsoft.Practices.CompositeUI;
namespace Blue
    public class BlueModuleInit : ModuleInit
        public override void Load()
            Form1 form = new Form1();

That’s it: if we put the code above in the Blue project, and the equivalent in the Red project, the three forms will now load and we have our first composite application. None of the three separate projects has a direct reference to any other.


The difficult thing to understand when you see this for the first time is that the CAB is doing a lot of work for us when we call that .Run() method on a FormShellApplication class. It’s instantiating and showing our Form1 (our shell). It’s checking for an XML file called ProfileCatalog.xml. If it finds ProfileCatalog.xml, it is loading the assemblies it finds listed in there. It’s then looking for any ModuleInit classes in them, and calling .Load if it finds them. None of that’s too complicated, but it can feel a bit like smoke and mirrors are being used.

This article is continued in part 2, where I explain WorkItems, and part 3 where I will explain dependency injection, and show how we can get the two forms in the Red and Blue projects in our example to be MDI children in the shell.

C#, Visual Basic and C++ .NET Line Counter Utility – Version 2


Source code download.

Executable download.


An updated version of the line count utility described in an earlier article is now available. This now:

  • Does basic C++ line counting of Visual Studio.NET projects and solutions, as well as C# and VB.NET as previously.
  • Counts the total number of code files and displays them in the summary section.
  • Allows the summary to be selected (by dragging over it) and copied to the clipboard with Ctrl-C.

Unfortunately for C++ projects I don’t think there’s an easy way of identifying auto-generated code, and hence the application will always return zero for code-generated lines for C++ projects.

Code Project

An abbreviated version of these articles is available on the Code Project.

C# and VB.NET Line Count Utility – Version 1

This program has now been upgraded to version 2, which additionally deals with C++ .NET solutions. This can be downloaded from my later article.


The attached program is a line count utility written in C#. This:

  • Counts the number of lines in a .NET solution, project or individual code file.
  • Works with both C# and VB.NET.
  • Works with both Visual Studio 2003/.NET 1.1 and Visual Studio 2005/.NET 2.0 (but needs .NET 2.0 to run).
  • Provides a sortable grid of results so you can easily find your biggest projects or biggest code files.
  • Caches results at all levels and provides views onto them. For a solution you can see a view of all projects and their sizes, all code files and their sizes, or a view that combines both projects and code files.
  • Shows the number of blank lines at every level.
  • Shows the number of lines auto-generated by code-generators at every level (e.g. layout code on forms, or typed DataSet code).
  • Shows the number of lines of comments at each level.
  • Allows the grid to be copied into the clipboard in a format that can be pasted into Excel.
  • Comes in a fetching green and white colour scheme.


I was recently asked how many lines of code there are in our current C# project, and how that compared with another similar project. The ‘other’ project is much bigger in terms of resources (numbers of developers), although it’s been running for slightly less time than our project. Our project has had two or three developers working on it for about a year.

I looked around for a line count utility on the internet, but couldn’t really find anything I liked the look of. So I upgraded an old VB6 line count utility I wrote several years ago. I used the VB6 to VB.NET upgrade wizard initially. It still amazes me that the upgrade wizard works at all, but in this case I got a VB.NET project (with VB6-style code) that compiled immediately. With a little work I got it counting code in individual C# projects.

This program told me we had about 180,000 lines of code in our entire C# solution. If you do the maths on that it comes out at about 1500 lines of code per developer per week, or over 300 lines per day.

300 lines per day per developer of production code seemed very high, so I decided I needed a tool that could analyze the data in a little more detail. This program is the result of that. Below I will discuss why our developers (myself included) are nowhere near as productive as the initial analysis suggests, and why.

Design – Code Containers

This is not a highly complex application, and there isn’t all that much to say about the design. However it was clear early on that I would want classes that represented the three possible types of entity that the program can be run on. These are solutions, projects and individual code files. In addition I would want some polymorphic behaviour from these three classes. That is I would want them to implement the same methods to do stuff like counting lines and getting results.

I have implemented this using an abstract base class for the three classes, with abstract methods CountLines and PopulateResults. I call the solutions, projects and individual code files ‘code containers’, and hence the abstract base class is called ‘CodeContainer’. Note that semantically the code containers are not just the individual solution file, project file or code file (although they contain a reference to that file), but represent the associated code structures and the line counts on them.

In particular each code container contains a list of other code containers that are contained directly within them: a Solution object will contain a list of Project objects which will in turn contain a list of CodeFile objects. These objects are then used to cache the line count results at the appropriate level: after calculation each CodeFile object will contain its own line count in its numberLines member variable, and the Project object will similarly contain the overall total number of lines in all its CodeFiles in its numberLines member variable. So in some ways this is a simple composite pattern, although it can only have three levels with specific types at each level.

The CodeContainer abstract base class lets me cache the actual line counts in member variables in the base (since all the code containers need to store these), and to have a ToResultString method that just output these numbers with a bit of blurb. Finally a factory idiom (CodeContainerFactory) allows the correct code container to be instantiated when necessary based on the extension on the name of the file.

All this means that the client code doesn’t need to know which type of code container it is dealing with: it instantiates the correct one by calling the CodeContainerFactory and then just calls the abstract methods on the base class when it needs to do something.


At start up the application opens a dialog to allow the user to select the solution, project or code file (.vb, .cs) that the program will run on initially. Once a file is selected the application calculates the line counts for that item and displays the results as below. Here a solution file has been selected and both project files and individual code files are being shown in the resulting grid:

Line Count Main Small

The grid can as usual be sorted by clicking the column headers. Here it has been sorted by the number of lines in individual code files.

Additional functionality is available on both the traditional menus and a context menu. These can be used to hide the code files and show only project files, with one line in the grid per project file (by clearing the check mark alongside ‘Show Code Files’):

Line Count Projects

For a simpler view at code file level, the application can also be used to show code files only (by checking ‘Show Code Files’ and clearing ‘Show Project Files’). The breakdown columns (numbers of blank lines, code designer lines and comments) can also be hidden using the ‘Show Breakdown’ menu option:

Line Count Code Files

The other functionality on the menus is pretty self-explanatory.

If you want to copy the grid into Excel you can simply select the entire grid (Ctrl-A), copy to the clipboard (Ctrl-C) and then launch Excel and paste (Ctrl-V). In a later version of the application I will add a menu option to do all this.


There are some issues around the counting of auto-generated code with this application, particularly with Visual Studio 2003 projects. In Visual Studio 2005 we have auto-generated code neatly split into partial ‘designer’ files, which makes it much easier to identify and count. For Visual Studio 2003 I have tried to identify the auto-generated code regions, but have been forced to do this by looking for the #Region or #region strings that precede these regions. This probably isn’t the most accurate method of identifying this code. See method ‘SetCodeBlockFlags’ in CodeFile.cs.

A further problem arises if your project references a web service. The proxy code for this is generated by Visual Studio in a file called ‘Reference.cs’. At the moment this is being identified by name and by the fact that it will have the text ‘Web References’ in its file path. Again, this isn’t a great solution.

Note that in any case only auto-generated code in .cs or .vb files is counted.


The Line Count program showed us that whilst our project does have 180,000 lines of code, 100,000 of them are auto-generated by Microsoft’s code generators.

Of the 100,000 auto-generated lines 73,000 are in our data access component. Our application is a low-volume but reasonably complex product, and for ease of development we have extensively used typed DataSets to get our data out of our database. Those 73,000 lines of code are mainly in these typed DataSets. In addition 22,000 auto-generated lines of code (out of the 100,000) are in our presentation layer. As you’d expect these are mainly auto-generated layout code for our forms and user controls.

So we’re down to 80,000 lines of code written by developers. Of this, a further 10,000 lines are blank, and another 10,000 are comments. Even this exaggerates the size of the actual application code as we can see that our unit test project has 16,000 lines of code.

I expect these numbers are not untypical of enterprise .NET applications. I’d be interested in some statistics from other projects.

As for the ‘other’ project I mentioned above, that has 50,000 lines of code, 10,000 auto-generated, 5,000 blank, 6,000 comments (and no unit tests).


In the end all this goes to back up something that all developers know instinctively: using lines of code as a metric for the ‘size’ of an application really doesn’t make much sense. Maybe that’s why I couldn’t find a decent line count program in the first place.

However counting lines can provide some interesting analysis. We can see at a glance which our biggest classes are, and these are clearly candidates for refactoring. Also, if you look closely at the screenshots you can see that we probably have too much logic in our presentation layer compared to our model layer (middle tier business layer). We knew that already, but the line count statistics bring it home.


Executable download.

Source code download.