I hate that phrase, “Working hard, or hardly working?” It’s a mean-spirited jibe at someone’s effectiveness and work ethic. However, it says something about practice. If you are only going through the motions, you aren’t really practicing.

When discussing practice, it makes sense to identify two types. Practice, as in a practicing attorney, is the act of doing a thing. Practice, as in deliberate practice, is about isolating disciplines to find ways of improving. This second type is what I’m talking about today. It’s the soccer player dribbling around cones, the musician doing etudes, or the artist drawing a page of ears.

I’m going to define deliberate practice as “performing a discipline to gain feedback on the quality in order to improve proficiency. The key is ‘feedback’. Without the feedback cycle, we don’t improve. It is what makes the distinction in the phrase, “Ten years of experience, or one year ten times over.”

To practice, we deconstruct our performance into it’s constituant parts and strengthen our skills. The isolation is important, because it allows us to focus on one area for improvement at a time. Why isn’t doing as good as practice? A musician won’t focus on breath control and tonal quality while making a tricky 16th note run, so they perform one-minute drills, playing each note on a scale for one minute while maintaining centered tone. Sure, they may hit all the notes at tempo, but what about the quality of their attack, tone, volume, and speed of their transitions?

What does that have to do with Development? (Disclaimer, I say typical in the following because I still brush up against people from organizations who have these experiences. Your millage may vary) The typical factors effecting software development encourage “all performance, no practice.” The drive is to constantly move towards completion of the product. This is good, as we find business value and justify our paycheck. This is bad, because we don’t invest towards our future capabilities. I’m not talking about the perfect, flexible code that will slice, dice, and make julian fries. I’m talking about our ability to do a better job next week, month, or even year.

The typical industry workplace distracts us from improving in a couple of ways. The pressure on the project usually means the database expert does all the database code, preventing a sharing of knowledge and encouraging focus on existing strengths. Reviews, when done, are months removed from development and focus on finding defects. They are not intended to provide the more subtle feedbacks that will make fundamental changes in the way a developer addresses their work. Developers aren’t given time to explore and attempt to use new techniques and determine their impact on the fitness of the code base. All this leads to an environment that encourages stagnation and the status quo amongst the development staff.

Typical design reviews are done well in advance of development before any new lessons learned from the implementation of other parts of the system can be incorporated. Typical code reviews are delayed until the code is stabilized to reduce re-work. This means reviews happen well after the initial design decisions are made, so they can’t make meaningful comments on the larger patterns, but only look for defects or show stoppers. If we delay detailed design until we are actually working on a task, we see the code take shape while the design decisions are fresh. In addition, if the designer is actually the developer implementing their code, they learn what did and didn’t work well. Another way to get timely feedback is to target your development tasks at one or two days of work. This makes code review quick and doable as part of the normal work flow, the code can be reviewed before the developer being reviewed starts on new work. This starts to bring them into the practice feedback loop of do, evaluate, and do again. The tightest method of feedback is constant feedback. That comes from pair programming. Even if you don’t pair as part of daily routine, you should consider it as a means of knowledge transfer and training for ALL developers.

Practice is about strengthening your weaknesses. A quote from David Mead’s 10 Minute Acoustic Guitar Workout describes a player who had revisited several songs after a few years. He realized he still had the same problems in the same areas of those songs because he had not addressed those fundamental weaknesses, but practiced and played what he wanted. More correctly, what he could already do. If you encourage the developers to get done fast and perfect at all costs, then they will gravitate to what they already know. They will begin to have siloed code ownership. You’ll turn around and find out that the analytics specialist, the only one who knows that part of the code, is spending a week in the Keys, and you have a customer who wants a change NOW. This is an example of “bus-factor,” the degree to which losing a single team-member puts your project at risk. More insidious, they will drift apart in their understanding of the system because, “That doesn’t effect me.” If they don’t have a shared vision, they aren’t a real team. If the developers work on and share several sections of the project, you strengthen their weaknesses. Agile teams strive for ‘Generalist’ developers. This doesn’t preclude expertise, but that dev is now a reference and mentor sharing the knowledge. While one developer may be able to handle all the analytics now, what if you have to double her workload? If you have a team of UI developers, but aren’t focusing on the UI this release, do you let them go, or shift them to areas where they are needed?

Developers are usually not given flexibility to explore better ways of doing something. While uniformity make development easy, it can be a false prophet. “We can’t do that module differently because then we’ll have to change these two.” Experiment. Try it. Is it easier to maintain? great! Is it worse? Then you learned, and that’s valuable as well. Do you have to change solid, tested, working code because you have a new methodology? No. Wait to change the code until the requirements change. Often the first code laid down is fixed with rigidity, even if we find strong evidence for change. This can be a false economy. The local highway is expanding traffic lanes to accommodate more cars. Older homes are re-insulated and fitted with grounded electrical outlets. But developers seem to think the only way to change code is to burn it all down and start over.

This is about how an organization can try to enable the growth of its development staff. A lot of this points to lean processes and agile techniques. I’m not sure if the software craftsmanship movement, who prize practice so highly, developed the agile techniques because they sought feedback, or because they saw the effects of feedback, they began to understand practice.

Some time in the future, I’ll be addressing some practice techniques that individuals can use so they take some charge of their own growth. The organization can only do so much, you have to take it the next step.

5 Comments

You’ve actually got a few things going on in this post. All good, IMO.

One thing I’d add when it comes to the team, the generalists, and the lower bus number – it may pay to also consider actually reigning in your geniuses. I didn’t think I’d ever find myself saying this because my old attitude was “We hire smart, capable people who can learn, right? Yes, it’s a new technique – deal.” We don’t compromise the quality of our solutions like this when learning is the core of our job expectation anyway. Right?

But not everybody is created equal. Which is to say talent-wise, sure, but also interest-wise and time-wise. If you put a SQL genius on a project and let them free reign, you might have them submit some things that are elementary to them that your other people just can’t grok. And I don’t even mean “clever code” in the traditional backhanded sense. It could be smart and “clear”, as long as you have the 2 years daily professional use to get it.

If bus number is important, I’d say you can’t just rely on people to practice outside their comfort zone. You also would want to consider working it the other way. Something inside me is uncomfortable telling a genius they can’t exercise their full talent and push the limit of their craft. I’m maybe more uncomfortable telling a smart but less-talented-IN-THIS-ONE-AREA team member they’ve got to count cards as well as Rainman (an impossible standard).

I’m going to chew on this, and maybe ask around an post again. I don’t have a firm understanding of how to handle the mad-scientist, the kind who develops a DSL to replace your test environment one night, because I’m either him or standing on the sidelines yelling, “That is SOOO sweet!” While I’m learning more and more the importance of leaving maintainable (by people who don’t find it “fun” to learn the nooks and crannies of Perl for example. I’m oh, so sorry for my crimes. Mostly.) code, The team should try to find that line between “dark-magic,” “Encapsulated but hard,” and “pattern” together.

There will probably be dark corners of any interesting application, but they should be placed there on purpose and successfully encapsulated from the rest of the app. Why would they exist? Performance optimizations (the crazy SQL statements come to mind) or to make the rest of the app easier to develop (app specific frameworks). If you do identify a need to get magical, you need to re-think it, then test the crap out of it. Asking for a white paper on the topic wouldn’t hurt.

As soon as you said “mad scientist”, I’m reminded of the Spolsky tidbit in his Duct Tape programmer post: “…what would otherwise be a perfectly good programming technique FOR SPOCK.” Spock, Rainman, Mad Scientists… not evil, just misunderstood. 🙂

I really relate to your perl comment. I’d forgotten all about my perl “transgressions” until you mention it. And… uh… Huh. My sudden resentment over the indignance of my C# contemporaries with regard to Perl has temporarily neutralized my already limited ability to make further constructive comments. Dammit.

Nice article – I am however a bit confused on exactly where you want to go with what you describe. At one point you encourage change and experimentation at another you point fingers at burning down and starting over.

I really enjoyed the article and it made me put a my practices at my day job into perspective – but I think you squeezed in too many aspects of organization, self-development and practices in one single article – or perhaps it is just me, who cannot follow you.

About Brian Ball

I'm a Software Engineer in Indianapolis. I'm interested in programming languages. I love dynamic languages like Ruby and Perl. I'm exploring functional languages like Haskell, F#, Clojure, and Erlang. I also use the .NET framework and occasionally deal with System Testing.

If you're not careful, you might also see some sketches and other art come up every once in a while.