Wednesday, December 30, 2009

When is it OK to build up Technical Debt?


As I previously mentioned I’ve been writing a bit of Ruby on Rails. I’m surprised at how quickly I can slap something together and get results, especially prototypes, up and running quickly.

Technical Debt is generally defined as the eventual consequence of building software in a quick and dirty way. This most commonly occurs when a developer jumps directly into writing code without architecting or thinking through the solution. Usually a solution is spit out prematurely and will quickly fall over under heavy load or stringent testing.

The opposite of this would be to slowly build skills, tooling, requirements, specifications, tests, libraries, etc. until the problem is well defined and it’s just a matter of converting requirements and specifications into code. The problem with this is it is SLOW.

Other development techniques have been developed to bridge this gap. To provide the right amount of guidance when it’s necessary, but not so much that we develop requirement paralysis. TDD and Agile are two techniques that come to mind, but other technological solutions such as Object Oriented Programming, fantastic libraries and frameworks also help us get results and make headway quickly.

Still there will come a time, even with TDD, Agile, OOP, and a framework that makes you happy, when you have to decide between the right way, and the right-now way. At these times it’s important to know how to weigh those decisions properly. Here are some questions that might help you decide whether to build up technical debt or to build your software in a more measured way.

How long until the next version? – if this is a quick demo version that will be completely replaced it makes more sense to build it quickly leveraging anything you can get your hands on, using the skills you have now, rather than trying to learn a new tool. However, if this version has to stand on its own for an extended period of time, real customers will use it or if it will have to stand up to heavy live testing or load then you may not be able to cut corners.

How many customers are likely to become dependent on this? – Don’t forget that you may not just building up technical debt for yourself, but also for your customers who rely on stable software to build their solutions on. Changing large amounts of the software under existing customers can be difficult, you may even lose some of them to a competitor. Preserving perfect backwards compatibility makes it easier for your customers but forces you to shoulder the whole burden of your technical debt. Making this decision too many times can cause you to lose revenue to support and maintenance staff.

Is there an easy way out? - Using layers of abstraction to firewall the well architected pieces from the “quick and dirty” pieces is a good way to be able to componentize pieces that need to be replaced later. Before laying down thousands of lines of code ask yourself “How easy will it be to replace the technical debt pieces?” and if it’s going to be easy or there’s a way to make it easier on yourself then you might have the right decision. If your technical debt is taking a large dependency (for example a framework that is not well supported and will need to be replaced) then it may not make sense.

How likely will it be that you’ll have time to pay down your technical debt? – If you work at a company like most of the people I talk to you probably have a stack of todo items five feet tall and the only way anything ever gets done is if it is figuratively and sometimes literally on fire. If that’s the case then paying down the technical debt when you have a chance so you do it right the first time makes the most sense which will reduce future headaches. However if you need to release something right away and you know you can schedule time to return to the pieces that need attention you may be able to take on some debt without too much risk.

What kind of load will your application be under in this version? – If you’re anticipating very heavy load immediately upon release performance needs to be in the forefront of your decision making. One of the best examples of this is twitter; they were able to slide by on a shaky ruby-on-rails application until they grew to be one of the most visited sites on the internet. When they were in the throes of their growth pains we saw the fail whale often. They’ve had to quickly pay down their technical debt by replacing most of the backend of twitter with scala, memcache and starling, erlang, MySQL, Mongrel and more.

How much (real) market pressure is there to release a solution immediately? – Sometimes we feel every day we don’t release is another day people are filling the terrible hole in their lives with some other product. Unfortunately or fortunately this is often not the case. If we look at many examples of current market leaders they weren’t the first to market, but the best. The first mp3 player wasn’t the iPod, the first windowed GUI operating system wasn’t Windows, the first (nor the last) social media site was facebook. If you’ve promised a customer or client a solution it’s good to be on time, but if you don’t have customers shipping a half-baked product may give any potential customers such a bad taste in their mouth they won’t reconsider when you’ve had a chance to repay that technical debt you built up.

Many times it’s more important to get something out to get traction. As I mentioned in my “Let the pedestrians define the walkways” blog sometimes it’s better to get traction and feedback with people now and build up a little technical debt than to build a perfect solution that nobody can use.

Remember until you release nobody cares how fast, well architected, well commented or beautiful your software is.

Labels: ,


Sunday, October 11, 2009

I Code in my Freetime


I just read Ted Dziuba’s blog on not programming on his spare time. His point is interesting, but I don’t think he expressed it very well. For any readers out there, I think I should first put this entry in a bit of context. I program all the time. I am constantly writing little tools, websites, learning new technologies (my blog entry on Ruby on Rails was posted at near midnight), and getting excited about the next new thing. Just ask my wife, while she’s checking Perez Hilton; I’m reading a programming guide.

I deeply believe there is a balance in work and life. I believe a person should do as much of what makes them happy as possible. I’m writing this in between a run and a bike ride to a climbing gym, for example. However, people tend to do things that they enjoy and that makes them happy in their free time.

What makes me happy? Learning things.

I’ve known for quite some time that my biggest hurdle wasn’t discovering what I found interesting so I could pursue that as a career, but rather focusing my energies on something that I could really make a difference in and that was really inspiring to me. The things that I gravitate toward are usually challenging and represent a huge learning curve. I attribute my attraction to this somewhat to our natural tendency for seeking.

I don’t know Ted, and I don’t want to put words in his mouth, but I think what Ted was trying to say is that it’s important to balance your outside work activities and understand when others have different habits than you.

Would I hire somebody that doesn’t program outside of work? Absolutely.
Would I ask in an interview what they like to do with their free time? Of course I would.

Part of working for my company, Security Innovation, is fitting in with our company culture, and part of that is sharing common interests. We tend to work long hours and I wouldn’t want to spend 10-14 hours per day with somebody I didn’t have anything in common with. I also want to know that they’re interested in what they’re doing and that they are doing what they love. These people tend to work harder, learn faster and do better work than people that don’t enjoy what they do, in my experience.

So I guess my big lesson from all of this is just take all things in balance. Just because somebody programs with all their time, or knows every bit of security knowledge doesn’t make them a good hire. Conversely, though, being excited about what you do with the majority of your life is a very important thing.

Labels: , ,


Wednesday, October 7, 2009

Musings on a ComboBox


I just spent a good half an hour debugging a control I thought I had a pretty good handle on, the ComboBox.

In .NET 3.5 we have a really neat control called the ComboBox, it's a bit of a textbox, and a bit of a dropdown list box. However the eventing seems a little wonky.

I had the following code:

private void MyComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(TargetBox.Text))
    {
        if (MessageBox.Show("There is text in the request textbox, do you want to replace this?",
            "Replace Text?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
            DialogResult.Yes)
        {
            TargetBox.Text = File.ReadAllText(MyComboBox.SelectedText);
        }
    }
    else
        if (!string.IsNullOrEmpty(MyComboBox.SelectedText))
            TargetBox.Text = File.ReadAllText(MyComboBox.SelectedText);
}

Seems simple enough, right? I'm just grabbing whatever the user just selected out of the dropdown (which happens to be a file in my case) and read that file and populate a textbox with the new value. When there was already text in the text box I'd display up a MessageBox warning the user I'm about to blow away the existing text.

Here's the interesting part, when there was text in the TextBox already (so I displayed the MessageBox) everything worked as expected. However, when there was no text in the TextBox I always got the previous value of the ComboBox, as if the ComboBox hadn't updated its state yet. This occurred if I removed all the MessageBox code and just tried to set read the filetext directly.

The fix? Get the newly SelectedIndex of the ComboBox directly, lookup the value of the item that's selected from the Items list, store that value in a string and reference that throughout.

Final Code:
private void MyComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    string selectedFile = MyComboBox.Items[MyComboBox.SelectedIndex].ToString();
    if (!string.IsNullOrEmpty(TargetBox.Text))
    {
        if (MessageBox.Show("There is text in the request textbox, do you want to replace this?",
            "Replace Text?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
            DialogResult.Yes)
        {
            TargetBox.Text = File.ReadAllText(selectedFile);
        }
    }
    else
        if (!string.IsNullOrEmpty(selectedFile))
            TargetBox.Text = File.ReadAllText(selectedFile);

If you see something I missed, please let me know in the comments. I am a firm believer in clean code and would love to learn how to make this better.

Labels: , ,


This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]