A Django site.
March 9, 2008
» Fire your dev teams (reprise)

No, of course I don’t really think you can fire your entire development team and throw away your existing successful code base. Just because a blog post is spell checked and doesn’t contain swear words all over it does not mean someone is being entirely serious. I’m really disappointed in the anonymous Internet hate comments that some of you have left. I’m surprised and disappointed that people claiming to be professional programmers are acting like teenage forum trolls.

Many people did leave constructive comments and their points are worth some discussion.

jimmyD pointed out that the Internet runs on “hacker built” systems such as Apache, Bind, Sendmail and many more. They’re built by a loose collection of programmers–sure–but in no way are those tools “hacks”. Apache has a rigorous process for defining their projects, managing and running each project, and for testing and releasing software. There’s a massive difference between “hacker built” and “hacked together” systems. The programmers who develop successful open-source tools are not your average computer programmer. Many successful open-source programmers are hired by large enterprise companies or successful startups in order to apply their skills to other software. Open-source is some of the most successful “enterprise” software you’ll find.

While there was disagreement about how best to move from “startup” to “enterprise” some people conceded that there is indeed a time when a company needs to move from a code slinger mentality to something a little more formal. (Thanks to Adam Ierymenko for contributing the term “code slinger”).

Business people who start companies are usually not the same people to take those companies from startup to enterprise. Many successful startup founders immediately hire business execs with years of experience running large businesses (Google, WestJet, RackSpace, Facebook). Why do we assume that technical people will be able to span the transition when business people are happy to admit that someone else has more appropriate skills? IT is not a commodity, developers often do not span these multiple roles. Dennis Martinez blames IT management for having the wrong developers, but based on the responses I had to my first post I suggest we also blame developers for failing to admit they cannot or should not span styles of development. (By the way Dennis, you should re-read my post before grabbing sentences out of context and claiming every line of text is advice.)

The terms “enterprise,” “enterprise quality” and “enterprise developer” drew a lot of flak. Many people assumed that since I had used the E word I was talking about massive engineering projects, slow application servers, or processes involving lots of overhead. I didn’t mean that, and just like you I’ve been burned by heavy shrinkwrapped stuff labelled “Enterprise”. What I mean when I say “enterprise” is that a thing is suitable for use and extension over the long term. That means it’s well tested, firstly. It means the architecture is coherent and consistent. It means the software is extensible, and maintainable by people who (often) did not write the software in the first place. It means the system is performant and scalable and easily deployed.

There will always be tradeoffs when writing software. There’s no one “right way” to create an application. A startup, under significant pressure to deliver, will usually make tradeoffs that produce worse code, and that’s the right decision at the time. But please, startup IT people, make sure you and your team are aware that you are making compromises. Discuss the problems you might face in future and have a plan in place for fixing the problems when you become the next Facebook.

January 30, 2008
» How to Post Comments

My last post seems to have generated some commentary, as was intended. I moderate all comments and if you haven’t posted before it might take me a while to approve your comment. Once you’ve had one comment approved any future comments should appear immediately. I’m doing this is so I can filter out Viagra spam and it’s really in everyone’s best interests.

Internet script kiddy “you fail, loser” comments do not further the discussion and I will delete them. I’ve let everything through so far, since I didn’t set any ground rules, but I’ll be less lenient in future. Please limit yourself to mature responses that contribute something other readers might find interesting. Anything else will be deleted—you’re wasting your time posting that kind of thing here.

Please use your real name when you post (not that I can actually check who anyone really is). Anonymous posts will be consigned to the bit-bucket in the sky. Feel free to enter a fake email address, I don’t think WordPress actually uses them for anything. Thanks!

January 29, 2008
» Startups: Fire Your Dev Teams

Facebook should have fired their development team the minute they became successful. If you’re a startup and you just made it big you should take a long hard look at your software team and make some changes.

I’ve worked for two startups and consulted at several more. I’m not just talking about software startups, this applies to many industries—transportation, web 2.0, shopping, digital media, government—where the guys who built v1 of your web site, order tracking software, customer service tool, batch processing system, whatever, are unequivocably not the people you should rely on to take you from Startup to Enterprise.

When you’re a startup, time-to-market and user base are absolutely the most important success factors. For an aviation startup, flying your planes, selling your tickets and generating a loyal customer base are the most important things. As a computer manufacturer, you hire ex-military types to run your logistics and can custom build a PC and get it to a customer’s doorstep in four days. In general, an IT/programming competency is not required for a startup to be successful. In fact, “enterprise” engineering practices can actually slow you down. As someone who’s written software at startups I know the pressures to get the next demo ready, to release the next feature for the web site. At that stage in the life of a startup we don’t even know if the company will survive another month. Heavyweight testing, deployment and release processes just slow you down. I’d argue that most development teams actually do the right thing at this point. Get the software done, fast, and make it mostly work.

The problem I’ve found when working at startups-turned-enterprises is that the guys who built v1 of that web site are now running the IT department. The operations guy who originally managed the company’s one web site is now in charge of your entire data centre. The v1 codebase has been hacked and patched into v2 and v3, and everything is in a mess. Let’s talk about the codebase. When trying to get stuff out the door as fast as possible developers will often find out that a design decision they made is no longer appropriate. Given enough time they could fix that problem, but they don’t because the demo is happening tomorrow. And this is the right decision! But letting that patched, hacked, copy-and-pasted codebase live any longer than it takes for the company to declare itself stable is a really bad idea.

Most software developers don’t know how to engineer large enterprise systems. Most large enterprise systems are engineered badly. I know, I’ve seen a lot of them. Even with a resume with years of experience on appropriate sounding systems, most developers won’t know a well engineered app from a hole in the head. Now give these guys a couple of years hacking some code together for your startup and promote them to Chief Architect. Hire an expensive consulting company to help you build your systems better, and allow Chief Architect dude to ignore their recommendations. What?

Seriously. The minute you’re successful, plan to rewrite your software from scratch. Plan to hire enterprise quality developers. Move anyone with decent business knowledge (like Chief Architect dude) into business-related roles. They’ll be much more valuable there and cause you less problems. Hire a new development manager with proven experience engineering enterprise software. Pay them market rate +30% (you’re successful, remember?). Keep your developers but explain to them that you’re no longer a startup and they’re going to have to raise their game. At the same time you’ll be putting that old codebase in maintenance mode and starting with a clean slate. This will require planning with your business—you won’t be giving them new features for a while until you can rewrite your software. Believe me, you’ll end up with much better engineered software that can respond to change faster than your existing stuff.

Don’t believe me? As a successful startup looking to become an enterprise, try the following exercises:

  • Add a column to an existing database table. Make it required. How many files did you need to alter to get that field to show up on screen? How many people were required to make the change? How did you migrate old data to the new format? How did you test the change, and are you sure you didn’t break anything else? How long did it take to deploy? What about rollback?
  • Run a cut-and-paste detector on your codebase. Simian works for Java, C#, C++, Ruby, HTML and other code and is a great way to scare the crap out of your dev team (assuming you’ve admitted that duplicate code is a bad thing).
  • Find out your automated test coverage percentage. If you’re not yet tracking this, now would be a good time. 80% coverage on a real world project is extremely good, most projects run much below this. If an automated test isn’t testing your code, how do you know it works?

December 28, 2007
» Blog upgraded to WordPress

I’ve upgraded to WordPress after several happy years using Blosxom. Whilst Blosxom is a neat blogging engine and has served my needs well, it doesn’t really have all the spanky new “community” features that I’d really like. A colleague told me recently that I’d gone “dark” and that’s true–hopefully easy drafting of blog posts and features like comments and trackback will help me reconnect.

The older archived mikemason.ca is still available, and anything indexed by a search engine will continue to work. If you see something awry, please let me know.

April 30, 2007
» Disabling Export Formats in Reporting Services

Reporting Services 2005 doesn’t allow you to selectively disable export formats for your reports. You can disable export formats for the whole server, but this is a bit useless in a shared environment. For my current client, we wanted to disable XML, Tiff and “web archive” export on all of our reports, but not affect any other reporting applications deployed on the server.

Our reports consist of custom parameter pages followed by a report view page onto which we’ve dropped a ReportViewer control. When the page loads, we programatically set the ReportViewer’s server URL, report path, and parameters. We’re doing this to ensure users are requesting reports for data that they’re allowed to see and not tricking us into revealing other users’ data.

Whilst there’s no official way to disable export formats on an individual report, a little bit of exploration using Reflector reveals that the ReportViewer contains a ServerReport that acts as a proxy between the control and the Reporting Services web service. The ServerReport allows you to list rendering extensions—these guys do the hard work of actually exporting in each format—but it doesn’t allow you to set the visibility of an extension. Reflection to the rescue!

The following code sample turns off XML, Tiff, and “web archive” export for a particular ReportViewer or ServerReport:

using System.Reflection;
using Microsoft.Reporting.WebForms;
using Microsoft.SqlServer.ReportingServices2005.Execution;

namespace MyProject
{
    public class ServerReportDecorator
    {
        private readonly ServerReport serverReport;

        public ServerReportDecorator(ReportViewer reportViewer)
        {
            this.serverReport = reportViewer.ServerReport;
        }

        public ServerReportDecorator(ServerReport serverReport)
        {
            this.serverReport = serverReport;
        }

        public void DisableUnwantedExportFormats()
        {
            foreach(RenderingExtension extension in serverReport.ListRenderingExtensions())
            {
                if(extension.Name == "XML" || extension.Name == "IMAGE"
		                           || extension.Name == "MHTML")
                    ReflectivelySetVisibilityFalse(extension);
            }
        }

        private void ReflectivelySetVisibilityFalse(RenderingExtension extension)
        {
            FieldInfo info = extension.GetType().GetField("m_serverExtension",
                                                          BindingFlags.NonPublic
							| BindingFlags.Instance);
            if (info != null)
            {
                Extension rsExtension = info.GetValue(extension) as Extension;
                if(rsExtension != null)
                {
                    rsExtension.Visible = false;
                }
            }
        }
    }        
}

I really hope Microsoft includes this functionality in the next release of Reporting Services. It would be really quite simple to include it in the graphical report designer and avoid this nasty reflection hack entirely. At the very least, the sealed RenderingExtension class could have a mutable “Visible” property, rather than the read-only property it has now.

» Disabling Export Formats in Reporting Services

Reporting Services 2005 doesn’t allow you to selectively disable export formats for your reports. You can disable export formats for the whole server, but this is a bit useless in a shared environment. For my current client, we wanted to disable XML, Tiff and “web archive” export on all of our reports, but not affect any other reporting applications deployed on the server.

Our reports consist of custom parameter pages followed by a report view page onto which we’ve dropped a ReportViewer control. When the page loads, we programatically set the ReportViewer’s server URL, report path, and parameters. We’re doing this to ensure users are requesting reports for data that they’re allowed to see and not tricking us into revealing other users’ data.

Whilst there’s no official way to disable export formats on an individual report, a little bit of exploration using Reflector reveals that the ReportViewer contains a ServerReport that acts as a proxy between the control and the Reporting Services web service. The ServerReport allows you to list rendering extensions—these guys do the hard work of actually exporting in each format—but it doesn’t allow you to set the visibility of an extension. Reflection to the rescue!

The following code sample turns off XML, Tiff, and “web archive” export for a particular ReportViewer or ServerReport:

using System.Reflection;
using Microsoft.Reporting.WebForms;
using Microsoft.SqlServer.ReportingServices2005.Execution;

namespace MyProject
{
    public class ServerReportDecorator
    {
        private readonly ServerReport serverReport;

        public ServerReportDecorator(ReportViewer reportViewer)
        {
            this.serverReport = reportViewer.ServerReport;
        }

        public ServerReportDecorator(ServerReport serverReport)
        {
            this.serverReport = serverReport;
        }

        public void DisableUnwantedExportFormats()
        {
            foreach(RenderingExtension extension in serverReport.ListRenderingExtensions())
            {
                if(extension.Name == "XML" || extension.Name == "IMAGE"
		                           || extension.Name == "MHTML")
                    ReflectivelySetVisibilityFalse(extension);
            }
        }

        private void ReflectivelySetVisibilityFalse(RenderingExtension extension)
        {
            FieldInfo info = extension.GetType().GetField("m_serverExtension",
                                                          BindingFlags.NonPublic
							| BindingFlags.Instance);
            if (info != null)
            {
                Extension rsExtension = info.GetValue(extension) as Extension;
                if(rsExtension != null)
                {
                    rsExtension.Visible = false;
                }
            }
        }
    }
}

I really hope Microsoft includes this functionality in the next release of Reporting Services. It would be really quite simple to include it in the graphical report designer and avoid this nasty reflection hack entirely. At the very least, the sealed RenderingExtension class could have a mutable “Visible” property, rather than the read-only property it has now.

March 21, 2007
» Card Infected

This whole Agile thing has messed me right up.

Wedding Card Wall

It’s not the most original idea—Joe Walnes had a card wall for renovating his house, where estimates were in money-costs rather than time—but it works well for me. I find myself getting a little stressed out when a personal project, even just “stuff I should do this week,” doesn’t have a card wall. Now that our wedding project has been successfully deployed I’ll be starting a card wall for happily ever after…

» Card Infected

This whole Agile thing has messed me right up.

Wedding Card Wall

It’s not the most original idea—Joe Walnes had a card wall for renovating his house, where estimates were in money-costs rather than time—but it works well for me. I find myself getting a little stressed out when a personal project, even just “stuff I should do this week,” doesn’t have a card wall. Now that our wedding project has been successfully deployed I’ll be starting a card wall for happily ever after…

March 17, 2007
» CVS to Subversion Experience Report

My current client in Calgary recently switched from CVS to Subversion. Our main goal for switching was to fix performance problems with CVS, but we also hoped to get some benefit from the improved features within Subversion. The CVS repositories were on a reasonably beefy Sun box but we’d been seeing “waiting for lock” messages and frequent hanging of our CVS clients. The server didn’t look like it was under load and switching the repositories to their own mount point didn’t fix the problem. One of the teams also wanted to clean up their branching structure–after five years of CVS they were in a bit of a mess.

Our first conversion was straightforward. We wanted to convert a recent project from its existing home in a CVS module into Subversion. We used cvs2svn to do the conversion and ended up with around 6,000 revisions in Subversion. This represented about 18 months of effort from about a dozen developers, and the conversion took about 2 hours to run. The team’s developers had been briefed on the conversion and all checked in to CVS beforehand, then checked out from Subversion once we were ready. The entire team–including business users, analysts and testers–upgraded from TortoiseCVS to TortoiseSVN and pretty much carried straight on with their work.

We got the performance improvement we had hoped for, with a Subversion update taking around ten seconds compared to CVS’ one or two minutes. This is with the repository on the same Sun server, the only thing we needed to do was actually install the Subversion software.

The second conversion was more complicated. We wanted to take a 5GB CVS repository with five years of history and not only upgrade to Subversion, but sort out some branching problems. One of the branches within CVS had started out as a release branch but evolved into its own product maintained by a separate team. We also had a fairly complicated set of branches we didn’t want to include, tags that were no longer worthwhile, etc. We scripted the conversion by customizing the example cvs2svn-example.options file included with cvs2svn to get exactly what we wanted. The big “Eureka!” moment came when we realized that promoting the CVS branch to its own product was really easy once everything was in Subversion. cvs2svn converts branches and puts them into their own directory, but there’s nothing stopping us from moving a directory within Subversion. We simply copied the branch-that-is-a-product into a higher level, mirroring a regular project’s structure, then deleted its old location so developers wouldn’t get confused about which was the right one.

Converting the 5GB, five year old repository took around 16 hours over a weekend. Shuffling directories around once converted took only a few minutes, and we used the excellent TortoiseSVN Repository Browser so all our move operations ran directly against the repository and were lightning fast.

» CVS to Subversion Experience Report

My current client in Calgary recently switched from CVS to Subversion. Our main goal for switching was to fix performance problems with CVS, but we also hoped to get some benefit from the improved features within Subversion. The CVS repositories were on a reasonably beefy Sun box but we’d been seeing “waiting for lock” messages and frequent hanging of our CVS clients. The server didn’t look like it was under load and switching the repositories to their own mount point didn’t fix the problem. One of the teams also wanted to clean up their branching structure–after five years of CVS they were in a bit of a mess.

Our first conversion was straightforward. We wanted to convert a recent project from its existing home in a CVS module into Subversion. We used cvs2svn to do the conversion and ended up with around 6,000 revisions in Subversion. This represented about 18 months of effort from about a dozen developers, and the conversion took about 2 hours to run. The team’s developers had been briefed on the conversion and all checked in to CVS beforehand, then checked out from Subversion once we were ready. The entire team–including business users, analysts and testers–upgraded from TortoiseCVS to TortoiseSVN and pretty much carried straight on with their work.

We got the performance improvement we had hoped for, with a Subversion update taking around ten seconds compared to CVS’ one or two minutes. This is with the repository on the same Sun server, the only thing we needed to do was actually install the Subversion software.

The second conversion was more complicated. We wanted to take a 5GB CVS repository with five years of history and not only upgrade to Subversion, but sort out some branching problems. One of the branches within CVS had started out as a release branch but evolved into its own product maintained by a separate team. We also had a fairly complicated set of branches we didn’t want to include, tags that were no longer worthwhile, etc. We scripted the conversion by customizing the example cvs2svn-example.options file included with cvs2svn to get exactly what we wanted. The big “Eureka!” moment came when we realized that promoting the CVS branch to its own product was really easy once everything was in Subversion. cvs2svn converts branches and puts them into their own directory, but there’s nothing stopping us from moving a directory within Subversion. We simply copied the branch-that-is-a-product into a higher level, mirroring a regular project’s structure, then deleted its old location so developers wouldn’t get confused about which was the right one.

Converting the 5GB, five year old repository took around 16 hours over a weekend. Shuffling directories around once converted took only a few minutes, and we used the excellent TortoiseSVN Repository Browser so all our move operations ran directly against the repository and were lightning fast.

June 14, 2006
» Pragmatic Version Control Using Subversion, Take Two

I’m very pleased to announce that the second edition of Pragmatic Version Control Using Subversion has been published and is now shipping. As an author, it’s great to get an opportunity to update a published book, and for there to be enough interest that making an update is worthwhile.

Since the book first came out Subversion has come a long way, from version 1.0 to 1.3, adding new features and making improvements. I’ve also had a bunch of feedback on what people did and didn’t like in the book and this was a good opportunity to add some more content and address some of that feedback.

The book is still very much a guide for using version control in a pragmatic fashion, suitable for people who are new to version control as well as those with prior experience, but the new edition adds some more advanced stuff like programmatic access to a repository, path-based security, and file locking.

It’s my continued pleasure to work with Andy and Dave—if you’re an aspiring author with an idea for a book you should seriously drop them a line. The Pragmatic Programmers’ editorial expertise and publishing system is second-to-none, and best of all you won’t have to write your book using Word!

» Pragmatic Version Control Using Subversion, Take Two

I’m very pleased to announce that the second edition of Pragmatic Version Control Using Subversion has been published and is now shipping. As an author, it’s great to get an opportunity to update a published book, and for there to be enough interest that making an update is worthwhile.

Since the book first came out Subversion has come a long way, from version 1.0 to 1.3, adding new features and making improvements. I’ve also had a bunch of feedback on what people did and didn’t like in the book and this was a good opportunity to add some more content and address some of that feedback.

The book is still very much a guide for using version control in a pragmatic fashion, suitable for people who are new to version control as well as those with prior experience, but the new edition adds some more advanced stuff like programmatic access to a repository, path-based security, and file locking.

It’s my continued pleasure to work with Andy and Dave—if you’re an aspiring author with an idea for a book you should seriously drop them a line. The Pragmatic Programmers’ editorial expertise and publishing system is second-to-none, and best of all you won’t have to write your book using Word!

February 15, 2006
» Model, View, Presenter with ASP.NET 2.0

Most people are familiar with the Model, View, Controller pattern (MVC) for separating business logic and presentational logic within an application. MVC is implemented in a number of Java web frameworks, such as Struts and Spring. A more recent pattern–Model, View, Presenter–can be applied in contexts where there is no central “controller” for the application. One such framework is ASP.NET.

My team recently built an MVP-based application on ASP.NET 2.0 and had great success with highly testable presenters and a highly adaptable presentation layer. In fact, we chose to switch from creating custom web controls to using simple .aspx pages and didn’t have to change our presenters at all–it’s always nice to validate those previously abstrct design decisions!

The MVP pattern separates three elements. The model is one or more domain-specific objects representing the current state of the system, the information we’re trying to display, etc. The view is how we present that information to the user and handle input, usually a particular screen or web page. The presenter is the logic that ties together the model and the view, handles navigation, business logic requests, and model updates.

For MVP in ASP.NET 2.0, we use an .aspx page–or more precisely, the code behind partial class–as the view, custom domain objects as the model, and a Plain Old C# Object (can I steal the term POCO?) as the presenter. Let’s assume we’re creating a page to list customers in our application. Our ListCustomers.aspx page might look like this:

<asp:Content ContentPlaceHolderID="Main" Runat="Server">
    <h1>Customer List</h1>
    <asp:GridView ID="customerGridView" AutoGenerateColumns="false" runat="server" SkinID="CustomerGrid">
        <Columns>
            <asp:BoundField HeaderText="Customer" DataField="Name" />
        </Columns>
    </asp:GridView>
</asp:Content>

Nothing special here, we’ve just defined a GridView which will list the customers and display a title. What’s interesting is the code-behind:

public partial class ListCustomers : System.Web.UI.Page, IListCustomersView
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ICustomerService customerService = ServiceRegistry.GetService();
        ListCustomersPresenter presenter = new ListCustomersPresenter(this, customerService);
        presenter.PageLoading();
    }

    public List<Customer> Customers
    {
        set
        {
            customerGridView.DataSource = value;
            customerGridView.DataBind();
        }
    }
}

The code-behind partial class implements IListCustomersView, which we’ll see in a moment. When the page is loaded we create a new ListCustomersPresenter, passing it the view (this) and anything else it requires (in this case, an ICustomerService). We then call the presenter’s PageLoading() method. What’s happening is that the code-behind is making no decisions about what to display on the page, it simply delegates to the presenter for any non-display-related business logic.

The IListCustomersView interface defines how the presenter can interact with the ASP page. There’s just one settable property, Customers:

public interface IListCustomersView
{
    List<Customer> Customers { set; }
}

Looking back up at the code-behind, you can see that the implementation of the Customers property sets the grid view’s datasource to the list of customers and then calls DataBind() to populate the grid.

Let’s take a look at the final piece of the puzzle, the presenter:

public class ListCustomersPresenter
{
    private readonly IListCustomersView view;
    private readonly ICustomerService customerService;

    public ListCustomersPresenter(IListCustomersView view, ICustomerService customerService)
    {
        this.view = view;
        this.customerService = customerService;
    }

    public void PageLoad()
    {
        List<Customer> customers = customerService.GetAllCustomers();
        view.Customers = customers;
    }
}

When our presenter is constructed the two things it depends on, the view and the customer service, are passed to it (in this case, by the code-behind). This is known as constructor dependency injection. In the PageLoad() method the presenter simply accesses the customer service to load customers and sets this information on the view. This simple example can be extended to include input (the view can have read-only properties that correspond to text boxes, etc) and action (add a button to your web page and in the code-behind for its click call an action method on the presenter, like AddCustomerClicked()).

So why is this useful? Why not just have the code-behind access the CustomerService to load the customers? One of the main benefits is that the difficult business logic is captured in the presenter and can be more easily tested. Because we’re using dependency injection we can instantiate the presenter in an NUnit test, mock-out the view and service, and check the presenter does the right thing. The “load customers” example isn’t very hard but you can imagine logic that needed to take a set of user input and perform something more complex, such as placing an order. A second benefit is it’s very easy to see how the presenter can interact with the view–it can only use methods and properties on the IListCustomersView interface, which means it’s much easier for us to see the logical interface between the UI and the business layer. Finally, it’s possible to test drive your presenters and views, which tends to lead to simpler, more modular design for the system.

I’ve simplified some of the other stuff you’ll need to do in a real application. Screen flow and input validation are good examples. We solved the flow issue by having presenters able to return a “presenter result” object, indicating whether the ASP.NET framework should redirect to another page, stay on the current page, go to a login screen, etc. With input validation and error conditions, we add properties on the view so that the presenter can instruct the view to show a particular error message. You can still use an ASP.NET validator for client-side validation, but the presenter needs to be able to toggle it visible too.

We started our application using MVP, implementing the view using custom controls coded in C#. We did this mostly because we envisaged our application as a series of reusable controls, some of which (for example a Wiki control) should be embeddable in other applications. Ultimately we went a bit too far with this and coded some simple screenflow, which wasn’t really reusable, with the same C# controls. We found that layout and other tweaks became fairly onerous and decided to switch to implementing the view using traditional .aspx pages and code-behind. We found that our presenters required no changes at all to be able to accomodate the new view–excellent validation of the MVP design pattern.

» Model, View, Presenter with ASP.NET 2.0

Most people are familiar with the Model, View, Controller pattern (MVC) for separating business logic and presentational logic within an application. MVC is implemented in a number of Java web frameworks, such as Struts and Spring. A more recent pattern–Model, View, Presenter–can be applied in contexts where there is no central “controller” for the application. One such framework is ASP.NET.

My team recently built an MVP-based application on ASP.NET 2.0 and had great success with highly testable presenters and a highly adaptable presentation layer. In fact, we chose to switch from creating custom web controls to using simple .aspx pages and didn’t have to change our presenters at all–it’s always nice to validate those previously abstrct design decisions!

The MVP pattern separates three elements. The model is one or more domain-specific objects representing the current state of the system, the information we’re trying to display, etc. The view is how we present that information to the user and handle input, usually a particular screen or web page. The presenter is the logic that ties together the model and the view, handles navigation, business logic requests, and model updates.

For MVP in ASP.NET 2.0, we use an .aspx page–or more precisely, the code behind partial class–as the view, custom domain objects as the model, and a Plain Old C# Object (can I steal the term POCO?) as the presenter. Let’s assume we’re creating a page to list customers in our application. Our ListCustomers.aspx page might look like this:

<asp:Content ContentPlaceHolderID="Main" Runat="Server">
    <h1>Customer List</h1>
    <asp:GridView ID="customerGridView" AutoGenerateColumns="false" runat="server" SkinID="CustomerGrid">
        <Columns>
            <asp:BoundField HeaderText="Customer" DataField="Name" />
        </Columns>
    </asp:GridView>
</asp:Content>

Nothing special here, we’ve just defined a GridView which will list the customers and display a title. What’s interesting is the code-behind:

public partial class ListCustomers : System.Web.UI.Page, IListCustomersView
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ICustomerService customerService = ServiceRegistry.GetService();
        ListCustomersPresenter presenter = new ListCustomersPresenter(this, customerService);
        presenter.PageLoading();
    }

    public List<Customer> Customers
    {
        set
        {
            customerGridView.DataSource = value;
            customerGridView.DataBind();
        }
    }
}

The code-behind partial class implements IListCustomersView, which we’ll see in a moment. When the page is loaded we create a new ListCustomersPresenter, passing it the view (this) and anything else it requires (in this case, an ICustomerService). We then call the presenter’s PageLoading() method. What’s happening is that the code-behind is making no decisions about what to display on the page, it simply delegates to the presenter for any non-display-related business logic.

The IListCustomersView interface defines how the presenter can interact with the ASP page. There’s just one settable property, Customers:

public interface IListCustomersView
{
    List<Customer> Customers { set; }
}

Looking back up at the code-behind, you can see that the implementation of the Customers property sets the grid view’s datasource to the list of customers and then calls DataBind() to populate the grid.

Let’s take a look at the final piece of the puzzle, the presenter:

public class ListCustomersPresenter
{
    private readonly IListCustomersView view;
    private readonly ICustomerService customerService;

    public ListCustomersPresenter(IListCustomersView view, ICustomerService customerService)
    {
        this.view = view;
        this.customerService = customerService;
    }

    public void PageLoad()
    {
        List<Customer> customers = customerService.GetAllCustomers();
        view.Customers = customers;
    }
}

When our presenter is constructed the two things it depends on, the view and the customer service, are passed to it (in this case, by the code-behind). This is known as constructor dependency injection. In the PageLoad() method the presenter simply accesses the customer service to load customers and sets this information on the view. This simple example can be extended to include input (the view can have read-only properties that correspond to text boxes, etc) and action (add a button to your web page and in the code-behind for its click call an action method on the presenter, like AddCustomerClicked()).

So why is this useful? Why not just have the code-behind access the CustomerService to load the customers? One of the main benefits is that the difficult business logic is captured in the presenter and can be more easily tested. Because we’re using dependency injection we can instantiate the presenter in an NUnit test, mock-out the view and service, and check the presenter does the right thing. The “load customers” example isn’t very hard but you can imagine logic that needed to take a set of user input and perform something more complex, such as placing an order. A second benefit is it’s very easy to see how the presenter can interact with the view–it can only use methods and properties on the IListCustomersView interface, which means it’s much easier for us to see the logical interface between the UI and the business layer. Finally, it’s possible to test drive your presenters and views, which tends to lead to simpler, more modular design for the system.

I’ve simplified some of the other stuff you’ll need to do in a real application. Screen flow and input validation are good examples. We solved the flow issue by having presenters able to return a “presenter result” object, indicating whether the ASP.NET framework should redirect to another page, stay on the current page, go to a login screen, etc. With input validation and error conditions, we add properties on the view so that the presenter can instruct the view to show a particular error message. You can still use an ASP.NET validator for client-side validation, but the presenter needs to be able to toggle it visible too.

We started our application using MVP, implementing the view using custom controls coded in C#. We did this mostly because we envisaged our application as a series of reusable controls, some of which (for example a Wiki control) should be embeddable in other applications. Ultimately we went a bit too far with this and coded some simple screenflow, which wasn’t really reusable, with the same C# controls. We found that layout and other tweaks became fairly onerous and decided to switch to implementing the view using traditional .aspx pages and code-behind. We found that our presenters required no changes at all to be able to accomodate the new view–excellent validation of the MVP design pattern.

October 19, 2005
» Splitting, Merging, and Organizing a Subversion Repository

When setting up Subversion within an organization, folks will often ask “How many repositories should I create?”—my advice is to just create one repository until you have a concrete need for more. I take this approach because it’s easy to split an existing repository into two. I also remind people it’s not the end of the world if they create multiple repositories and then they need to merge them, because Subversion has good support for splitting, merging, and reorganizing repositories. I’ve never really gone into any detail on how you actually do this stuff, but since I recently needed to merge two repositories I thought I’d share the technique I used.

Splitting a repository

First off make sure you tell everyone you’re going to split the repository. The ideal situation is where everyone can check in, go home for the night, leave you to organize stuff, and then come in the next day and start on something fresh. If people can’t commit all their changes you may need to help them relocate their working copy. Once everyone’s committed their changes, close down network access to your repository to be sure no-one’s committing further changes. This might be overkill depending on your situation, but it’s nice to be safe.

Next, back up your repository using svnadmin dump to create a dump file. A dump file is a portable representation of a Subversion repository and something you might be using for backups already. We’re going to load the dump file into a new repository, using svndumpfilter to select just the directories we wish to move to the new repository. A typical transcript might look like this:

[mgm@penguin temp]$ svnadmin dump /home/svnroot/log4rss > log4rss.dump
* Dumped revision 0.
* Dumped revision 1.
    :     :     :
* Dumped revision 37.
* Dumped revision 38.
[mgm@penguin temp]$ mkdir tools-repos
[mgm@penguin temp]$ svnadmin create tools-repos
[mgm@penguin temp]$ cat log4rss.dump | svndumpfilter include log4rss/trunk/tools | svnadmin load tools-repos
Including prefixes:
   '/log4rss/trunk/tools'

Revision 0 committed as 0.
Revision 1 committed as 1.
Revision 2 committed as 2.
    :     :     :
<<< Started new transaction, based on original revision 38

------- Committed revision 38 >>>

In the above sample, I dumped the Log4rss repository into a file called log4rss.dump and created a new directory called tools-repos initialized with an empty repository. Then I piped my dump file through svndumpfilter and told it to include just the tools directory, and piped the result of the filter into svnadmin load into the new repository. I haven’t included it here, but I got a bunch of information about which items were included in the filter and which were dropped. Now the new tools-repos repository contains just the tools directory.

At this point, I can make the new repository available and tell developers where to find it. It’s probably also wise to delete the log4rss/trunk/tools directory from the original repository, just so people can’t accidentally use the old stuff. Subversion doesn’t have an obliterate command so the tools directory is still using space in the old repository—if this is an issue you’ll need to consider loading your dump file into a new repository using an “exclude” command to weed out the directory you no longer want.

Merging two repositories

My current project recently moved from Chicago to Calgary. For a while we had two teams running, using separate Subversion repositories. When everything moved to Calgary, we needed to merge the Chicago team’s code into our repository. We didn’t want to just import the files, we wanted to include historical information too.

We created a dump file of the Chicago team’s repository and loaded it straight into our repository using svnadmin load. This worked because the load command simply replays a series of commits, simulating what would have happened if the Chicago team had been working with us all along. The key thing to note here is that we had been using different directory paths in the two repositories, so their stuff didn’t conflict with ours. If they had used the same directory structure we would not have been able to simply load their changes into our repository. In that case, we would have had to work some magic with the dump file—it contains plain-text path definitions, so in a pinch we could have munged those path names so they didn’t conflict.

Organizing a repository

Once we’d loaded the Chicago code into our repository we used TortoiseSVN’s graphical repository browser to move the new stuff into our existing directory tree. Here’s a screenshot of the repo browser—it’s a great tool for this kind of thing and made reorganization very simple. We just used the “rename” command to move everything around in the repository, and once done we all checked out the newly organized directory tree and continued working.

Subversion repository browser

» Splitting, Merging, and Organizing a Subversion Repository

When setting up Subversion within an organization, folks will often ask “How many repositories should I create?”—my advice is to just create one repository until you have a concrete need for more. I take this approach because it’s easy to split an existing repository into two. I also remind people it’s not the end of the world if they create multiple repositories and then they need to merge them, because Subversion has good support for splitting, merging, and reorganizing repositories. I’ve never really gone into any detail on how you actually do this stuff, but since I recently needed to merge two repositories I thought I’d share the technique I used.

Splitting a repository

First off make sure you tell everyone you’re going to split the repository. The ideal situation is where everyone can check in, go home for the night, leave you to organize stuff, and then come in the next day and start on something fresh. If people can’t commit all their changes you may need to help them relocate their working copy. Once everyone’s committed their changes, close down network access to your repository to be sure no-one’s committing further changes. This might be overkill depending on your situation, but it’s nice to be safe.

Next, back up your repository using svnadmin dump to create a dump file. A dump file is a portable representation of a Subversion repository and something you might be using for backups already. We’re going to load the dump file into a new repository, using svndumpfilter to select just the directories we wish to move to the new repository. A typical transcript might look like this:

[mgm@penguin temp]$ svnadmin dump /home/svnroot/log4rss > log4rss.dump
* Dumped revision 0.
* Dumped revision 1.
    :     :     :
* Dumped revision 37.
* Dumped revision 38.
[mgm@penguin temp]$ mkdir tools-repos
[mgm@penguin temp]$ svnadmin create tools-repos
[mgm@penguin temp]$ cat log4rss.dump | svndumpfilter include log4rss/trunk/tools | svnadmin load tools-repos
Including prefixes:
   '/log4rss/trunk/tools'

Revision 0 committed as 0.
Revision 1 committed as 1.
Revision 2 committed as 2.
    :     :     :
<<< Started new transaction, based on original revision 38

------- Committed revision 38 >>>

In the above sample, I dumped the Log4rss repository into a file called log4rss.dump and created a new directory called tools-repos initialized with an empty repository. Then I piped my dump file through svndumpfilter and told it to include just the tools directory, and piped the result of the filter into svnadmin load into the new repository. I haven’t included it here, but I got a bunch of information about which items were included in the filter and which were dropped. Now the new tools-repos repository contains just the tools directory.

At this point, I can make the new repository available and tell developers where to find it. It’s probably also wise to delete the log4rss/trunk/tools directory from the original repository, just so people can’t accidentally use the old stuff. Subversion doesn’t have an obliterate command so the tools directory is still using space in the old repository—if this is an issue you’ll need to consider loading your dump file into a new repository using an “exclude” command to weed out the directory you no longer want.

Merging two repositories

My current project recently moved from Chicago to Calgary. For a while we had two teams running, using separate Subversion repositories. When everything moved to Calgary, we needed to merge the Chicago team’s code into our repository. We didn’t want to just import the files, we wanted to include historical information too.

We created a dump file of the Chicago team’s repository and loaded it straight into our repository using svnadmin load. This worked because the load command simply replays a series of commits, simulating what would have happened if the Chicago team had been working with us all along. The key thing to note here is that we had been using different directory paths in the two repositories, so their stuff didn’t conflict with ours. If they had used the same directory structure we would not have been able to simply load their changes into our repository. In that case, we would have had to work some magic with the dump file—it contains plain-text path definitions, so in a pinch we could have munged those path names so they didn’t conflict.

Organizing a repository

Once we’d loaded the Chicago code into our repository we used TortoiseSVN’s graphical repository browser to move the new stuff into our existing directory tree. Here’s a screenshot of the repo browser—it’s a great tool for this kind of thing and made reorganization very simple. We just used the “rename” command to move everything around in the repository, and once done we all checked out the newly organized directory tree and continued working.

Subversion repository browser

May 2, 2005
»

Roots Conference in Norway

I’ve just spent a great couple of days attending the Roots Conference in Bergen, Norway. There were a bunch of very interesting people there and I had a fun time presenting. Norweigans seem to be very friendly and speak great English (lucky for me!).

My talk about Subversion Security includes some updated slides—if you have the proceedings CD you might want to grab the updated version. For the Test Driven Development session, we wrote a bunch of code which I thought people at the conference might like to see again, and you can grab that here including the slides.

» Roots Conference in Norway

I’ve just spent a great couple of days attending the Roots Conference in Bergen, Norway. There were a bunch of very interesting people there and I had a fun time presenting. Norweigans seem to be very friendly and speak great English (lucky for me!).

My talk about Subversion Security includes some updated slides—if you have the proceedings CD you might want to grab the updated version. For the Test Driven Development session, we wrote a bunch of code which I thought people at the conference might like to see again, and you can grab that here including the slides.

March 30, 2005
» Shelving Subversion

My colleague Clinton Begin asked me whether Subversion supports shelving. This is something that the new Visual Studio may have as part of its “Team” features, and is basically a way for a developer to put aside a set of changes come back to them later. Storing shelved changes in your version control tool is pretty sensible—your repository is reliable, backed up, and not liable to disappear if someone pinches your laptop.

So can you do this kind of thing with Subversion? You betcha. Here’s roughly how it would work:

  • Whilst working on adding the new “frobscottle” feature Alice decides she’d like to shelve her current working copy changes. Her project, codenamed “xyzzy,” is checked out from svn://svn.acme.com/xyzzy/trunk.

  • Needing somewhere to store her changes, Alice branches the trunk to create svn://svn.acme.com/xyzzy/shelves/alice/frobscottle.

  • Alice uses the Subversion switch command to switch her working copy from the trunk to the new frobscottle branch. When switching, Subversion preserves any changes you’ve made to the working copy.

  • Alice checks in her working copy. The changes will be safely stored under the shelves directory.

  • Alice switches her working copy back to the trunk and works on something else. In future if she wants the shelved frobscottle changes she can merge from the branch to her trunk working copy, then commit the changes back into the main code line.

There are a few details you’ll need to get right—you may need to create the new branch from an older revision on the trunk rather than from the head—and it’s less pretty than a “shelve” button in a GUI, but it’ll work great and you’ll understand exactly where your changes actually are.

» Shelving Subversion

My colleague Clinton Begin asked me whether Subversion supports shelving. This is something that the new Visual Studio may have as part of its “Team” features, and is basically a way for a developer to put aside a set of changes come back to them later. Storing shelved changes in your version control tool is pretty sensible—your repository is reliable, backed up, and not liable to disappear if someone pinches your laptop.

So can you do this kind of thing with Subversion? You betcha. Here’s roughly how it would work:

  • Whilst working on adding the new “frobscottle” feature Alice decides she’d like to shelve her current working copy changes. Her project, codenamed “xyzzy,” is checked out from svn://svn.acme.com/xyzzy/trunk.
  • Needing somewhere to store her changes, Alice branches the trunk to create svn://svn.acme.com/xyzzy/shelves/alice/frobscottle.
  • Alice uses the Subversion switch command to switch her working copy from the trunk to the new frobscottle branch. When switching, Subversion preserves any changes you’ve made to the working copy.
  • Alice checks in her working copy. The changes will be safely stored under the shelves directory.
  • Alice switches her working copy back to the trunk and works on something else. In future if she wants the shelved frobscottle changes she can merge from the branch to her trunk working copy, then commit the changes back into the main code line.

There are a few details you’ll need to get right—you may need to create the new branch from an older revision on the trunk rather than from the head—and it’s less pretty than a “shelve” button in a GUI, but it’ll work great and you’ll understand exactly where your changes actually are.