Not long ago I went with a couple of friends to a bar in lower Manhattan. While we were sipping Coronas, Jerry, our system architect friend, told us he had just inherited a high-profile J2EE system, along with one of the top Java teams in his company. "Now we know who's buying the beers tonight," we cheered.
Instead of a round of beers, Jerry decided to surprise us: "My first J2EE project might very well be my last." Apparently, Jerry had overestimated the flexibility of the project's code base, and for a guy obsessed with time lines, it cost him dearly - he missed his first deadline by weeks. What bothered him more was the fact that the team seemed to be giving up. "There are bandages everywhere," one developer told him before taking off. "But I thought the team was very good," I said. "They still are, but they just can't seem to keep up with the changes. The next thing you know, broken structures have mushroomed everywhere....And now I'm working late every day."
As we were trying to raise Jerry's spirits, Ben, our project manager friend, pointed to a nearby TV and said cheerfully, "He can help you." It was a news clip about Time's man of the year - Mayor Rudolph Giuliani.
Mayor Giuliani and Broken Windows
Turns out that Ben wasn't joking. If there is one tip Mayor Giuliani can share with Java developers, it's the power and simplicity of the "Broken Windows" theory. In a speech he gave at Lincoln Center in 1998, Giuliani pointed out that New York City had turned around, with overall crime dropping 44% over the last four years, and the "Broken Windows" theory, "an integral part of our law enforcement strategy," made this possible.
First written about in 1982 by political science professor James Q. Wilson and criminologist George Kelling, the "Broken Windows" theory states that "If a factory or office window is broken, passersby observing it will conclude that no one cares or no one is in charge. In time, a few will begin throwing rocks to break more windows. Soon all the windows will be broken, and now passersby will think that not only is no one in charge of the building, no one is in charge of the street onto which it faces. So more and more citizens will abandon the street to those they assume prowl it. Small disorders lead to larger ones, and perhaps even to crime." The net result of this strategy, Giuliani observed, was a transformation "that's improving the lives of millions of New Yorkers."
The State of Many Java Neighborhoods
Broken windows exist not only in the real world (possibly in a neighborhood near you), but also in the Java world, taking on various forms under the cover of functional code. Some broken Java windows are easy to spot and are better known in the industry as spaghetti code: massive nested if-else, code duplications across modules, and dead code, to name a few. On more than one occasion I've run across component instantiation routines with over 200 if-else, which can easily be replaced with one line of Class.forName().
Other broken Java windows are more subtle and require some digging. One such example is premature abstractions. Good abstractions make Java systems more flexible, but sometimes developers fall into the trap of trying to solve abstract problems before they even understand the concrete ones. The net result is unnecessary complexity that gets in the way later down the development stream (if you think no abstraction is bad, try bad abstraction).
Some broken Java windows are just plain inefficient. They work, but there are better ways of doing them (e.g., an optimized sorting algorithm implementing a comparable interface). Others are like time bombs that could blow away your whole system at any time; a security loophole comes to mind. When triggered, these sort of broken windows tend to be very costly, as we've seen in the past with eBay, whose 22-hour server downtime cost more than $5 million in return auction fees.
Contrary to popular belief, broken Java windows are not always the result of a manager or developer not knowing Java technologies any better, not drinking enough Java to do the job. Some windows are broken by inexperienced programmers who lack Java skills or by seasoned Java programmers who lack time and political support. A conversation like, "Hey bud. Hard wire Favorite Customer Inc. in the code. We'll all be out of here if we don't do this for them by next Monday. BTW, the big gun was just asking about this earlier," is not uncommon.
Some windows are broken the minute they're installed (early in the development stage), while others "creep in" later when dealing with high-speed, high-frequency business changes. The success that most Java systems enjoy has to take some blame for some of these changes. As a successful system becomes more popular, it attracts more users, who in turn demand more features and more flexibility quickly. The once ever-changing Java specifications are a good case in point. Also, most of the Java systems find their homes in Internet-driven business. Unfortunately, the Internet industry is constantly reinventing itself with businesses trying different models. Some models deal with how you charge, some with how you deliver the services. Some work, some don't. The dynamic nature of this environment can break all windows if not managed carefully.
What's the Big Deal About a Few Broken Java Windows?
Despite their diverse appearances, all broken Java windows seem to be sticky - they have a tendency to stay around for a long time, sometimes even throughout the whole system's life cycle. Although developers are not particularly fond of them, they don't lose sleep over them either. After all, broken windows do work with respect to specified behaviors, and what's a better alternative to not delivering the system on time?
This also explains the fact that developers generally don't introduce bugs intentionally, but the same thing can't be said about broken windows. People on the business side don't seem to mind them either - they might not even be aware of their existence. And if they do, a typical response is along the lines of "Does it work?" "Yes, but it's a bad thing to do." "Well, if it ain't broke, don't fix it. We are way overloaded already." So broken Java windows are given a license to do whatever they like for as long as they like.
Another common characteristic is that broken Java windows "replicate" fast. Like worms, they spread swiftly, leaping from module to module throughout the whole system. But how? If an object or routine is broken, developers observing it will conclude that no one cares or is in charge. In time, a few will conclude further that the system is not worth the effort (i.e., "All the rest of this code is crap") and more routines will get broken. Soon all the routines will be broken, and now developers will think that, not only is no one in charge of the object, no one is in charge of the subsystem to which it belongs. So more and more broken windows will pop up all over the subsystem and its neighbor subsystems.
Small disorders lead to larger ones, and perhaps even to project cancellation and firings. In other words, broken Java windows create a delusion of dysfunctional systems, even though a system might be perfectly fine up to that point. Once developers are convinced that the current system is crap, it becomes a license for them to break some more Java windows. In contrast, if developers are convinced otherwise, they would think twice about breaking any window - after all, we Java developers are no different than any other artist - we love and appreciate beautiful things. With that appreciation, we do everything we can to preserve them. It's these two characteristics that enable broken Java windows to accelerate their damages.
The Little-Known Evil Twin of the Java Bug
If a broken window sounds just like another name for a Java bug, it's not - it's the more evil twin of a Java bug that we don't usually hear about. A bug is usually defined as something that's not functional and is visible to the business. On the other hand, a broken window is functional and often invisible, but has a mid- to long-term negative impact on the health of the system and the development team.
In many ways comparing a Java bug to a broken window is like comparing a cold to an early-stage terminal disease - without warning signs it's harder to detect (remember why your doctor recommends regular checkups), but in the end it proves far more lethal than a cold. Like any terminal disease, broken windows slowly deteriorate system internals over time, until one day the system is completely drained. In other words, it becomes so "bloated" or badly structured that you'll find yourself spending an enormous amount of time and effort to implement a simple change. At the same time, it "deteriorates" the most precious resource of all - the development team. It bumps up the turnover rate so high that no one really knows about the system anymore.
As Giuliani pointed out, if a climate of disorder is allowed to take root, more serious antisocial behavior will increase. "There's a continuum of disorder." Obviously, bugs and broken windows are two different "disorders." But they are part of the same continuum, and a climate that tolerates one is more likely to tolerate the other. "...A city in which an increasing number of people respect and are willing to accommodate the rights of others is a city that's moving in a progressive direction." By the same token, a Java system in which broken windows are "arrested" is a system that's moving in a progressive direction with true Java spirit.
Does that mean that as Java developers, our new mission is to "hunt down" all broken windows mercilessly ASAP? In a time-starved society, that's often impossible. What we need instead is a different approach, an approach that allows us to make steady progress toward our real goal - delivering functionality and, at the same time, fixing broken Java windows, an approach that says a Java team should only fix windows at natural project breaks, and prioritize their broken windows before trying to fix them.
Identify Broken Java Windows
Some Java developers react to broken windows by installing a "broken Java window detector." Since broken windows are a legitimate concern throughout development, no new functionality can be considered done until it has passed the detector. This practice might sound good and complete on paper, but in real life it is the recipe for killing a good Java system. The first symptom is the fast-dropping development velocity. And instead of listening to the users' needs, concentrating on business scenarios, and getting functionality done right, every thought is now interrupted by the question "Is this a broken window?" A team will most likely miss the chance to make a big leap in their development progress.
Plan on identifying broken windows toward natural breaks, such as when a module is expected to be complete, or before every minor release. Allocate time in your project plan to do so. It helps keep your team and project stakeholders informed of your priorities so they'll act accordingly.
Categorize Broken Java Windows
Once identified, you could "arrest" broken Java windows one at a time. In my experience though, some Java windows are broken due to a particular design or approach that spans multiple areas. For instance, without a class factory, you might find component instantiation code scattered over multiple subsystems. In this case, if we arrest broken windows one at a time, we might have ended up with different fixes, as the windows might get assigned to different developers. In other words, we miss the benefit of finding commonality. Another approach is to profile all identified broken windows, take into account several modules in which the same type of broken window occurs, and you may find yourself a different fix.
Profile your broken windows, categorize them, and you just might be able to fix two or more windows at one time.
Prioritize Broken Java Windows
Once all broken windows are categorized, our gut reaction is to "arrest" them all. Unfortunately, due to time constraints, that would force you to either commit to less functionality than you should be implementing or fail to deliver the system on schedule, in which case no one would care about broken windows anyway.
Prioritize your broken windows before putting a lot of energy into fixing them. Now is also a good time to involve project stakeholders. They might dislike certain broken windows more than others. On one project, just when I thought everyone would care less about executable size than memory footprint, some stakeholders were more than happy to indicate otherwise. And of course they were right.
Arrest Broken Java Windows
Once prioritized, we know we'll be arresting the ones that offer the biggest bang for the buck. There are many ways to actually fix broken Java windows. The best-known technique is probably refactoring and JUnit.
If we can't fix all identified broken windows, what do we do with the rest of them? Keep them in your ongoing broken windows list. More important, do the little things that show the team cares. My personal favorite is to write down a little comment next to the code starting with the word "FIXME" for bad functionality or "TODO" for a missing one. That would buy the team some time psychologically, until the next time slot for broken Java windows comes around.
If we're investing time and money in Java bugs, shouldn't we do the same for their evil twin? If broken windows in your Java world are not getting fixed, maybe it's time to seriously think about moving to a new Java neighborhood. After all, who likes to have a time bomb in their Java backyard?
Giuliani, Rudolph W. "The Next Phase of Quality of Life: Creating a More Civil City":
Wilson, T. (1999). "The Cost Of Downtime." InternetWeek. July.
Wilson, J.Q., and Kelling, G.L. (1982). "Broken Windows: The police and neighborhood safety." The Atlantic Monthly. March.
Hunt, A., and Thomas, D. (1999). The Pragmatic Programmer: From Journey
man to Master. Addison-Wesley.
Gamma, E., Helm, R., Johnson, R., and Vlissides, J. (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
Joe (Leizhou) Xu, an AVP with Credit Suisse First Boston, delivers
large-scale J2EE systems for Fortune 1000 and e50 companies.
He holds an MS and a BS in computer science.