Chapter 3 Do One Thing, and Do It Well
Theres only one way to eat an elephant: a bite at a time. Thats also the best way to code. Each bite of clear, simple Java code must have a single purpose. The best Java programmers keep a maniacal focus on a single problem at a time and go to extraordinary lengths to maintain that focus. If you want to improve, emulate them.
Im a whitewater kayaker. For a long time, I walked around every serious rapid that I faced. I could see how to run a one-shot waterfall or drop, but I couldnt get my head around the linked moves that would take me safely through Humpty-Dumpty on the Little River, or .25-mile Pine Creek on the Arkansas. A light clicked on for me on the Watauga River in Tennessee. I learned that I just couldnt bomb down continuous Class IV rapids with a preconceived set of moves in my head. Instead, I needed to find the natural break points within the rapids, and run many little ones. I learned to read the river and find the natural resting places within the whole. Then I could conquer one section, set up, and attack the next section. When I approached the problems this way, I received unexpected benefits. Coding, to me, is similar:
Its usually easier to clearly define a piece of a big problem than the whole. We all tend to get overwhelmed by large problems, but not as much by many smaller ones. Our brains just work that way, whether were on a river or behind a keyboard.
When things go wrong, its easier to adjust or adapt if your plan is segmented.Plans change; its harder to change a grand, sweeping plan than several smaller ones.
You can protect yourself from disaster. On the river, I now plan for safety one small section at a time. While coding, we must build test cases that identify problems quickly in each logical section.
You can better reuse techniques and code. On the river, I learn new moves that I can use elsewhere. Instead of frantically paddling through a section, I use a draw stroke to avoid one rock, an aggressive brace and sweep to punch a hydraulic, and so on. In code, I build collateral and learn techniques to solve smaller, moregeneral problems. Each design pattern that you learn in context is worth any 20 that you read about.
Whether youre a kayaker running a Class V rapid, a physicist working on a space station, or a programmer dealing on a massive problem, your approach should be the same.
Understand the problem
You must understand a problem to solve it well. Effective programming goes beyond your code editor and debugger. You need to be able to accurately gather requirements, and control the scope and expectations of your customers. There is nothing worse than a solution without a problem; it just generates more problems.
Distill the problem to its essence
Its often said that programming is more of an art than a science. Nowhere is this axiom more obvious than in the ability to cut through clutter and find the core problem. Youve got to recognize what belongs in the center of your problemspace and what you can push out to other classes around the perimeter, or out of the project altogether. Most of the time, less is more.
Layer the architecture
If youre solving a difficult problem and you can only focus on one thing at a time, you must layer your architecture, with each layer handling one task. The broadest, most successful design patterns help you build effective, decoupled layers. Model-view-controller lets you design user interfaces with three layered components. Façades allow you to build clean interfaces between major layers in your application. If you like to study design patterns, pay attention to how often this theme arises.
Periodically refine your approach
Left to its own devices, software loses focus over time. Youve got to make a concentrated effort to refactor, decoupling your software into autonomous layers. Automated tests will help you refactor with confidence and design decoupled code in the first place. Getting feedback from teammates and clients often helps make sure the approach still solves the right problems.
In this chapter, we explore each of these concepts in detail. You dont need to go through them all to see a difference in your programmingyou can benefit from each technique individually. But combining them multiplies their impact.
Understanding the Problem
Communication is a huge part of programming. Writing better Java wont do you any good if youre building the wrong thing: you must understand before you can code. As you advance in your programming career, youll find that more and more of your job demands effective communication. It doesnt really matter where your requirements come fromyour team lead, an analyst, or the customer. In each case,your first job is to accurately gather each requirement and focus your customer on what you can reasonably achieve with your resources at hand. Dont plow your customer under with enormous requirements and arcane design documents. If the customers cant understand your documents, they cant focus on the real issues. Like your code, keep your requirements simple and clear.