The experiment I performed for myself, and you might consider performing for yourself, is acting as if design emerges from a sequence of local optimizations. Remove duplicated code, ensure that all possible intent is expressed through naming and even the occasional "extra" method, then delete everything that doesn't pay for itself. All "without thinking", in the global sense. I started doing this, and my designs got better and better, and I went faster and faster.
I am aware there are other ways of designing, and practice them myself when I hit a local maxima. Most of the time I just spend putting one foot in front of the other.
The factors that were critical to the success of my experiment (at least my opinion of what was important) are:
- Having a clear set of CodingPatterns? to follow. That way all the typing just rolls off my fingers.
- Consciously acknowledging and discarding my fears about the future. This made running this experiment a personal challenge. I was afraid that if I stopped thinking in a way that had made me valuable, I would stop being valuable.
- Having a clear set of criteria for better and worse. Less duplication is better than more duplication (including subtle duplication like parallel class hierarchies and duplicated conditional logic). More intention is better than less intention. Messages to self are better than messages to other objects. Fewer classes is better than more classes. Fewer selectors is better than more selectors. Fewer lines of code is better than more lines of code. Fewer instance variables is better than more instance variables.
I took a large-ish piece of code I had written (Profile/V) and started walking up hill. A week later I had raging carpal tunnel from going back and forth to the mouse so much and I had beautiful code. I was shocked that I could get from a pile of spaghetti to elegance without ever considering the big picture (aside from the coding patterns and the criteria for better above, which indeed encode a lot of thought about the big picture).
If you try this, for a week or a day or an hour, please let us know how your HillClimbingDesign
I think you got at the crux of exactly how I was thinking about it. I do the above type of thing all the time.
I agree that being too paranoid beforehand, and during
can lead to AnalysisParalysis
that stops one from being productive and adding value. So instead of interrupting my flow at every step to call into question what I'm doing, I go with the flow and stay focused ("in the zone" if you will). But then at the end I make another pass and ask myself "Okay, is everything you've done here
really and truly
called for? Have I made any unsafe assumptions during my coding episode?"
So I wait to take that look until after
I leap, because if I try to do it mid-air (or even right before take-off) I'm sure to crash and burn. But after I've landed, I look back at the trail I've blazed to convince myself I didn't go too far or wander astray (because I will surely need to follow the trail again
A concrete technique I use is: when I can't think of anything else to do, I click through all the methods in the classes in question from top to bottom. If I can't see anything else I want to change, I'm done. WardAndKent
used to do this all the time in SmallTalk
, and today I found myself doing it in VisualAge
Java. The same dynamic applies- following some arbitrary order through the code can give you new direction that you weren't able to see following senders and implementers chains. --KentBeck
I wanted to add some experiential information on the HillClimbingDesign
experiments. I have done this a number of times on existing systems. It has exposed the design greatly. It is very like doing archaeology. When I am at I feel like I am dusting the debris and dirt from around the valuable artifacts (true design). The technique has proved very powerful. At my current company I was able to reduce the bug count thus improving the reliability of the code, and improve the responsiveness and performance of the subsystem to where it became very useful from the first version. The speed up that came from the HillClimbingDesign
was on the order of going from hour long runs to runs that took less than 5 minutes. A strong example of exposing the real design from existing artifacts. --AdrianSmith?
I always do a quick backup of my codebase then switch off and start climbing. Refreshes the brain especially during times of design stress. I always thought of it as housekeeping. --SimonArmstrong
As another anecdote, I've been doing this for the last several months with tremendous success. I scared folks when I started doing it because I'm not the only one working on the code, but over time they have come to be pleased with the results. I follow the IfItIsWorkingDontChange
model, but when I get two or three defects that come from the same area (ParetoPrinciple
), I RefactorMercilessly
. Usually end up with a large number of files changed and all regressions pass (whew). As a side benefit, our user documentation has improved because I use that as my tome of knowledge - then act surprised when someone reports yet another undocumented feature broke. -- BryanEwbank
This is an excellent way to RefactorMercilessly
, and it occurs to me that I've been doing things like this since before I had the PatternPattern
and certainly before I had WikiName
s for all of these concepts. But then, I also tend to do a fair bit of BigDesignUpFront
(but coupled with acceptance of PlanToThrowOneAway
- and to date I haven't had to work on very large projects except in a maintenance role) - I've picked up a lot of ExtremeProgramming
ideas just by applying good sense, but find I can't really turn the dial past 8 or so, to extend the metaphor. -- KarlKnechtel