Most programmers develop in cycles. Code, Compile, Test, Repeat. Depending on your process, you might add stages like Test, Code, Compile, Document, Deploy, Verify, Commit, but, as a rule of thumb, the programs of highest quality are usually those that are not a chore to develop. The ability to execute code immediately creates an efficient feedback mechanism that increases quality. If your cycle is quick, you’ll be able to debug and correct bugs faster than if you are constantly having to wait minutes to see if your current set of changes works. A long development cycle is similar to the experience one has trying to use a command line editor over a 300 baud modem - the time lag between typing and reading what you’ve typed causes speed and quality issues.
Ruby, Perl, Python…scripting languages are technologies with very quick development cycles. In a scripting language, you can make a change to your code and run it immediately. Compiled languages such as C, C#, and Java have slightly slower development cycles because they require compilation, but if you make the right choices you can attain a quick development cycle in Java. For example, the Sysdeo Tomcat plugin uses a custom classloader that allows you to modify your servlet code on the fly without having to restart your servlet container, and there are various approaches to speeding up Java development cycles using swappable ClassLoaders and the like. But, don’t let anyone tell you that a speedy development cycle is impossible with Java, it is possible, but usually not the norm.
There are times when one bad product selection or one misconfigured framework can ruin everything by introducing a huge span of dead time into your development cycle. Read more for a discussion of Development Cycle “Dead Time”, and how it can affect your approach to development.
Development Cycle “Dead Time”
First, some definitions. What is the “development cycle”? I’d define the development cycle as the cycle a
developer repeats over the course of a single day. At a very abstract level this can be “Code”, “Compile”, “Test”, and this is cycle is repeated maybe 10-100 times a day depending on the languages and/or platforms used. A developer can have more than one development cycle; for example, if you are working on a system that requires Java code and stored procedures in Oracle, you may have a distinctly different approach to working on either of these tasks. For stored procedures in Oracle, you may have to rebuild a database and run a series of unit tests to make sure that your changes didn’t introduce critical errors. For Java code, you might make changes in Eclipse, run units tests with Maven2, and then start the application to make sure your changes work properly.
One rule of development cycles is that they can rarely be mixed with other tasks. For example, if you are working on a development cycle for stored procedures that involves a 10 minute span of dead time to build an instance from a set of scripts. It is unlikely that you will be able to effectively swap out to another development cycle. The human brain doesn’t have a very efficient timesharing algorithm, nor does it have reliable registers for constant context switching. In general, a developer needs to focus on a single development cycle at a time. What I’m talking about here is a single “unit of work”. Trying to work on a braid of intertwined development cycles is possible, but it usually means that every once in a while you’ll confuse development cycles.
Another rule of development cycles is that it usually takes a few to complete a given task. If you are trying to fix a bug or implement a feature, you can count on having to complete an average of 2-4 development cycles. If you are fixing a simple typo, you’ll only have to complete one development cycle, but if you are trying to change a core piece of code, you might find yourself burning up 5 cycles trying to get everything working properly. In general a good rule of thumb is that simple changes take 2 cycles and major changes take 4 cycles. But, again, this is a general statement, and your experience may vary. If you are working on relatively straightforward issues, you might lump multiple tasks into a single development cycle.
A Typical Development Cycle
At a very concrete level, a development cycle can be described as a series of steps. For development of a swing application in Eclipse, my development cycle is usually:
- Write Code using Eclipse (2-60 minutes)
- Write a Unit Test for Code just Created or Modified (2-5 minutes)
- Compile Code and Unit Test (30 seconds - 1 minute) DEAD TIME
- Execute Unit Test (30 seconds ) DEAD TIME
- Start Swing Application (30 seconds) DEAD TIME
- Verifiy Changes in Application (1-2 minutes)
So, a given code change can take anywhere from a 2 minute fix for a typo to a 60 minute session of concentration trying to figure out the best approach for a difficult algorithm. Even if you are in “the zone”, it pays to take a break from deep concentration at least once an hour, as the brief break gives your brain some rest. If we add up the estimated times, for this cycle, we get the following results:
- Smallest Development Cycle: 6.5 minutes total with 1.5 minutes of dead time - Dead Time Ratio: 0.23
- Average Development Cycle: 31 minutes total with 2 minutes of dead time - Dead Time Ratio: 0.065
- Largest Development Cycle: 69 minutes total with 2 minutes of dead time - Dead Time Ratio: 0.029
In this development cycle, even the most complex change requires only an additional 30 seconds of DEAD TIME, and the speed of compilation and unit testing tools means that I’m rarely spending any prime development time waiting for my IDE or application to initialize. In reality, I think most of my programming changes involve about 10-15 minutes of coding and testing. With the development cycle described above, I can realistically expect to finish four or five major features of bug fixes a day with time to spare, and my dead time just serves as a gentle reminder that I need to take a break or check my email. In other words, an average development cycle of 31 minutes with a Dead Time Ration of 0.065 means that every half hour I’m staring at a progress bar for about 2 minutes. Over the course of a 8 hour day, I’m forced to endure about 30 minutes of dead time, most of which is efficiently spent doing things like checking email, and I can expect to complete 1 major task and about 2-3 minor tasks. This is a very efficient development cycle.
When Dead Time Starts to Become a Problem…
I’m currently working with a product that takes approximately 14 minutes to start. It then takes about 10 minutes to build a cache, after which I then need to load a massive applet-based UI that takes an additional 2 minutes to render. At this point, I can run my test and tail the appropriate log file. Running this test takes about 1 minute, changing the code takes about 5 minutes and deploying takes an average of 2 minutes. In detail, the development cycle is as follow:
- Write Code using Eclipse (5-60 minutes)
- Build and Deploy JAR with Ant (2 minutes) DEAD TIME
- Start Content Management Server (15 minutes) DEAD TIME
- Generate Local Cache (10 minutes ) DEAD TIME
- Load CMS GUI Tool (2 minutes) DEAD TIME
- Run Test and Verify (1 minute)
- Worst Case: Total time:35 minutes, dead time ratio is 0.83.
- Best Case: Total time 90 minutes, dead time ratio is 0.32
In the worst case scenario, 83% of the time is spent waiting for a process to complete, and there is only about 5 minutes every half hour for analysis and coding. In this case, the developer needs to fill 25 minutes with something constructive. In the best case scenario, the developer spends an hour writing code, and then has to wait a little less than a half-hour to verify that the code changes were appropriate. With this development cycle, I can expect to be able to complete 1-2 minor tasks in one day and 1 major task every 2 days. The product I’m working on is almost perfectly opaque, little documentation and lot’s of opportunity to screw up - badly. Because of this, the scope of every change is limited by design to reduce risk. I end up spending most of my time in the worst case scenario - 5 minutes of coding, 25 minutes of waiting, 2 minutes of testing.
Working with this development cycle is like trying to drive a rover on Mars. Each change needs to be small because the risks are high, and it takes approximately 25 minutes to see if the changes I just made took, and there is always the possibility that I’ve just driven the system into a rock. I can’t be the only one out there who experiences this kind of development cycle, and I’d wager that anyone working on “enterprise systems” designed by “architects” using a whole host of inefficient proprietary technologies has had a similar experience.
The Costs of Lengthy Development Cycles
When your development cycle is longer than a few minutes and has a high dead time ratio, you’ll know how difficult it is to focus on a problem that requires you to wait minutes between change and verification. You’ll find yourself distracted and frequently “swtiching contexts”. coding for 10 minutes, waiting for 20 minutes, and testing for 2 minutes, will probably turn into coding for 10 minutes, starting a conversation with a colleague for 40 minutes, and returning to your desk only to realize that you’ve lost track of your own progress. Another variation of this is coding for 5 minutes, starting an application that takes 10 minutes, and then getting distracted by slashdot.org or cnn.com. Dead time kills productivity.
What Java needs to learn
Startup cost needs to be minimized across the board. If you are designing a product or a framework, make sure that you are not introducing a technology that takes mulitple minutes to startup. Persistence frameworks like Hibernate and service frameworks like Spring are great tools, but if you are designing a system with hundreds of beans and hundreds of model objects, both technologies can add a significant startup penalty, if you are not careful about configuration. Keep applications focused, small, and modular. This will reduce the development cycle for any given subsystem.
If you are justifying high startup to increase performance of an application in a production environment, find a way to decreases statup costs in development. While biulding a cache or generating proxy objects on statup might increase performance for end-users, high startup costs increase the effective cost of development. In general, Javaland needs to be more nimble when it comes to startup cost. Minimize dead time in your development cycle as much as you can, and you’ll see an improvement in efficiency and quality.


Nice article, and I think many of your points are valid. One thing you might want to consider in this whole "dead time" concept is "execution speed". Compiled languages *are* faster at execution time. It may not be significant, but that's one of the main reasons that compiled languages are still around.
re: Ryan S.
No doubt. I'm not discounting compiled languages. the tradeoff between something like Ruby vs. Java is that Java's performance is going to be better in a production environment. What I'm trying to say is that regardless of the performance goals in an organization, minimizing startup costs for a product are going to benefit the development cycle.
I've worked in many situations where a company's "application" is a very complex web application that takes minutes to initialize. In general, I think it advantageous to be able to hot deploy code to a working application without having to pay the cost of restarting the [jvm|container|cms|ejb server]. It is something I think people need to approach - speed for the user is important, but speed for the developers is just as important to productivity.
don't worry, this isn't a ruby is better than java piece. ;-)
Tim, I think you are dead-on here. Build systems aren't very sexy to work on, but they usually need more care and feeding than just about any part of a system.
I'm always amazed how quickly people can let it get out of control and start consuming the dev cycle. I think the two main "smells" of build systems getting out of control are long build times and fragility. Both need to be addressed as soon as they appear.Here at work we call those the "productivity governors".
I can't stress how important it is to aggressively refactor your build as much as you refactor your code. It's not terribly fun but if you don't you will incur an insurmountable debt. Thanks for the article.
--Alex
Alex, thanks for the comments. Two things stuck out, the idea of a long build time being some kind of "productivity governor" - this is exactly the point. When your build or product takes minutes, you limit productivity. For anyone not familiar with the use of the word governor here, Alex isn't refer to "governor" as an elected official, he's refer to governor as a "feedback device on a machine or engine that is used to provide automatic control, as of speed, pressure, or temperature". A governor is usually used in an automobile as a feedback mechanism to create a maximum speed.
Also, "Insurmountable Debt" is a great way to put it. In my example, the legacy application I'm trying to improve takes approximately 8 minutes to initialize (most of that is hibernate). This is a price I have to pay everything I need to restart and test. losing 8 minutes 10 times a day adds up to a lost of lost opportunity/money.
I completely agree with what you've written here, and wasted far too much time on projects for exactly the reasons given. There are some nice ideas around -- management interfaces/APIs which could allow portions of code to be replaced for quick testing without restarting an entire infrastructure -- but more often than not (in my experience) they are not used effectively, or not available on the target platform. Java has a great, and greatly under-utilised, feature in it's reflection API I think.
Good piece. I had a simple web application starting to suffer from that. I thouroughly refactored the testing code: all beans without deploy locally, then after deployment only integration tests, then when that worked tests on remote server. Also in designing, I now make sure that functionality is testable standalone.
Big picture: in the US/Europe long cyles translates to high cost, thats the drive to go to India. There you can get the same 'development power' for less or increase by putting more 'cylinders' in your development 'engine' But your story rightly points out that development is also about individual tasks that needs to be done in a single 'cylinder' because of human brain and concentration constraints. Each cylinder must make a minimum number of revolutions to be efficient, so the cycle time must come down.
That is the single most important factor in selecting frameworks and tools: does it allow optimal cycle time? That beats reusability or architectural neatness every time.
Food for thought .
Very interesting! In addition the development environment (which is almost your own pc) has a deficit to the productiv environment. So the response of a development enviroment is partly very slow.
This are only some seconds per cycle, but for the whole project it can be more than a day.
Well written article. This is a problem we face everyday.