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.
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: development, software development
Monday, November 23, 2009
Let pedestrians define the walkways
I like to post my own thoughts here, but I just read a short blog on Derek Sivers' blog that really hit home for me. He tells the story:
I love it! I've seen so many places that have beautifully planned out landscaping that is marred by efficient pedestrians that know that the shortest distance between two points is a straight line.
He goes on to say how we can model our business after this plan. This follows the use of rapid iteration model of software development.
Listen -> Build -> Release
Listen to what people need, listen to their pain points. Build something lightweight that you think people will love and that will remove their pain, build it quickly. Release it before you think it's done. Go back to listening, listen to what they like, what they don't like, and what they want. Go back to building, build what they want. This reduces the amount of time you spend concocting crazy use cases or user models that may or may not exist or spending too much time building something that nobody wants and let's you leverage the wisdom of the crowds. When you're done building you know that you have something that people want to use because they helped you decide on the features.
One example of a company that doesn't seem to do this is of course Apple. Apple (an to an extent Google) has an incredible ability to anticipate what consumers want before they know they want it. To be a true market leader and leap over the competition risks like these are not only desirable but necessary. There is often a time when a consumer doesn't know what they want or need, they just know they don't like what's out there. What was wrong with the Philips GoGear? Before the iPod Touch came out I don't know if I could have put my finger on it. It took Apple's leap of design and development before I realized how many features were missing. This model is significantly riskier, but like all things with risk comes the potential of reward.
A new green college campus was built, but one thing was still debated:
Where in the grass should we put the paved walkways?
Some felt the walkways should be around the edges, to leave the center green and untouched.
Some felt the walkways should cut diagonal, connecting all buildings to all buildings.
One professor had the winning idea: Don't make any walkways this year. At the end of the year, look at where the grass is worn away, showing us where the students are walking. Then just pave those paths.
I love it! I've seen so many places that have beautifully planned out landscaping that is marred by efficient pedestrians that know that the shortest distance between two points is a straight line.
He goes on to say how we can model our business after this plan. This follows the use of rapid iteration model of software development.
Listen -> Build -> Release
Listen to what people need, listen to their pain points. Build something lightweight that you think people will love and that will remove their pain, build it quickly. Release it before you think it's done. Go back to listening, listen to what they like, what they don't like, and what they want. Go back to building, build what they want. This reduces the amount of time you spend concocting crazy use cases or user models that may or may not exist or spending too much time building something that nobody wants and let's you leverage the wisdom of the crowds. When you're done building you know that you have something that people want to use because they helped you decide on the features.
One example of a company that doesn't seem to do this is of course Apple. Apple (an to an extent Google) has an incredible ability to anticipate what consumers want before they know they want it. To be a true market leader and leap over the competition risks like these are not only desirable but necessary. There is often a time when a consumer doesn't know what they want or need, they just know they don't like what's out there. What was wrong with the Philips GoGear? Before the iPod Touch came out I don't know if I could have put my finger on it. It took Apple's leap of design and development before I realized how many features were missing. This model is significantly riskier, but like all things with risk comes the potential of reward.
Labels: feedback, software development
Subscribe to Posts [Atom]
