CodeHappy

October 6, 2007

Fluency, the least appreciated aspect of great code

Filed under: General Programming — pwrighta @ 4:33 pm
Tags:

750793_hands_talking.jpg

When it comes to the English language, Yoda is not the most fluent Jedi in the galaxy: “Strong in you the force is”. He gets his point across, but it’s certainly not elegant. Borat is probably even worse, but at least there are few pauses for thought in Yoda’s prose. Borat on the other hand has to think each word through before piecing together sentences. His speech is neither elegant, or efficient.

With so much talk in recent years about Object Oriented best practices, test driven development, and countless other devices to raise the quality bar on our code I’m surprised how little discussion there has been of fluency in programming languages. We all seem caught in a race towards the next new framework/buzzword/technology and all but ignore the most fundamental of all the foundation stones we need.

Fluency effects quality on many levels, perhaps the most significant areas being refactoring and testing. Working on some code the other day I found myself resisting refactorings that I know should be done. The reason was my lack of fluency. It’s easy to look at a section of code and know pretty much what refactorings need to happen, but until you are truly fluent in a language it’s very hard to motivate yourself to tackle those areas of the code. Refactoring is supposed to make the codebase easier to manage, more elegant and simpler to work with. However, without a high level of fluency some of the more complex refactorings suddenly take on the appearance of daunting mini projects.

The same applies to testing. I hadn’t written any production Rails code for some months. With the large project we have on at the moment I found myself writing code again, and against very tight deadlines. As I developed the pages of the application, struggling against my lack of fluency, I knew that I had to write tests for all layers of the application. Unit tests are easy enough to tackle, as are functional tests. Integration tests on the other hand started to look daunting to the point that I avoided writing them. Just as with the refactorings, I knew exactly what I wanted to do, but without a good level of fluency figuring out exactly how to write those integration tests just looked like a daunting task requiring a great deal of time, time that I wouldn’t be adding vital new features to the application.

And this I think is why a lot of people avoid testing in general. It could be, as in my case, a lack of fluency with the language itself, but most often a lack of testing tends to reflect a lack of fluency with the testing framework in use. RSpec for Ruby for example gives me a lot of flexibility when it comes to writing full integration tests, but not knowing it too well scared me into not writing the tests. My lack of fluency effectively damaged not only my productivity, but also the quality of my code. Working in a team, that translates to generating a burden the rest of the team will have to address on my behalf.

Your fluency, or lack of it, affects everyone you work with.

One of the most impressive books I ever read on the subject of testing and refactoring was Ron Jeffrey’s “Adventures in C# Programming’. In it, Ron tackles the development of a full application using Microsoft’s C# and .NET. He didn’t know either the language or the framework, but instead used the principles of Test Driven Development and Refactoring to learn as he went.

Faced with a complex problem, be it functional, a test or even a refactoring, write a test. If the test itself is daunting then the problem you are tackling is probably too large. Test small atomic pieces of code. Write tiny tests to assert your beliefs and then set about solving the test. The experimentation to solve the test improves your fluency, and the test turning green shows you when you are done.

Back in my own project, I had a relatively simple problem. A class I was using was supposed to call down to a class method elsewhere, grab a value and return it. It didn’t work, and I knew it was related to my lack of fluency with namespaces in Ruby. While the temptation was there to just start banging out code, refreshing the page in question over and over and over until I saw a result, I wrote a test. The test simply called the higher level class and asserted that the value returned was non zero. With the test in place I was able to experiment with the code, find out what was wrong and fix it getting the test to go green. My fluency increased, but more importantly an area that had me stumped is now documented in the project’s tests, in code. If I face the same problem again I know that I have a test that will lead me to the solution.

It’s just common sense that the more familiar you are with your text editor and development environment, the more productive you will be. However, it’s less well accepted that familiarity with your development environment also contributes to fluency.

We’ve reached a point with our programming languages and frameworks where it’s almost impossible to memorize every command, method, class, or interface available to us. Modern development environments offer a lot of features to help us write code, and completely mastering your development environment of choice can go a long way to aiding your fluency in the language and framework of choice.

Take TextMate for example, the now legendary text editor for Macintosh. It’s not an integrated development environment in the classic sense, but it is incredibly extensible. It’s so extensible in fact that there are literally hundreds of ‘bundles’ available for it to help programmers using almost any programming language and framework. I use it for my Ruby and Python work and while I’ve looked at numerous other IDE’s as alternatives nothing comes close to the flexibility, speed and power offered by TextMate. It’s the Emacs of the 21st century, a single tool that can pretty much do everything from helping you write code, to writing blog posts, to managing your todo lists, querying your database and so on. The bundles offer a great deal of power to programmers, but it takes time to learn just what’s available. The rewards for time spent digging deep into TextMate though are immense.

I write a lot of database migrations in Rails, but I have to admit that I rarely remember the syntax for every facet of them. TextMate’s Rails bundle however supports everything I would ever want to do in a migration. When I need to add a column to my database I just have to remember to type out ‘mcol’ and hit tab. TextMate will generate the code for me to both add the column, and to remove it if ever I need to ‘undo’ my schema changes. That’s a whole lot easier to remember than ‘add_column :tablename, :columnname, :datatype, {:options}’

Mastering your development environment also demonstrates that fluency extends beyond simply writing code. The TextMate bundles help me write code well enough, but the tool also offers a great many keyboard shortcuts for navigating that code. Rails for example is a very powerful framework, but also quite prescriptive in terms of what code goes where. When you generate a skeletal rails application you get a ton of files all with very specific purposes, and all with very clear relationships to each other. Mastering my development environment I know that I can hit just a couple of keys to rapidly jump from my controller to my view, to find a model, to move from method to method and so on. As the frameworks we use increase in complexity a critical part of fluency involves knowing what goes where. Learning the features your development environment offers you can go a long way towards mastering that level of complexity – just rely on the tools to know what they are doing and you can focus on mastering the code, leaving the grunt work of navigating a complex code set to the tool. This is particularly important if you are working on maintenance of a project that you are less than familiar with.

So, if fluency is so important in programming, how do you go about gaining it? The answer is simple. You get fluent in a language or framework the same way you get fluent with a spoken language; you use it. Dedicated language students will often spend time immersed in the culture of the language. Language schools frequently organize long term exchanges with schools in other countries. Students fly out, live with a foreign family for a long period of time then live, work and study in the culture with the language being studied. It’s a great technique. Even if the student is tired, sleepy, or just not ready to study one day, they have no choice but to exercise their skills.

So gain fluency in programming you have to apply the same principles. If it’s a technology you’re not paid to work with each and every day, you have to make time every single day to do something useful with it. It’s no good just reading a book, blog or message list about it. You need to do something. You need to tackle a problem of some kind, gain experience ‘immersed’ in the culture of the language. When you fire up that text editor and start writing code you’re doing the programming equivalent of moving to the foreign country of your dreams and immersing yourself.

But, what should you tackle? What programs should you write in the time you dedicate each day? Tackling trivial pointless programs is the equivalent of reciting phrases from a phrase book. You need to have a purpose. You’ll learn how to ask, in Chinese, where the bathroom is real quick when you’re walking around Beijing with a bladder full of Chinese Tea.

A great source of real, and challenging problems, is Ruby Quiz. Although the site is geared around Ruby, providing answers to the problems in Ruby, it’s still a great source of inspiration for programmers of any language. I also find newsgroups a great source of problems. I learned Visual Basic for example by hitting newsgroups and tackling every single complex question I read.

Better yet, scratch itches. All of us, every day, come across things that we wish we had a program for. Maybe it’s just a fleeting thought that doesn’t stick around and really niggle you for more than a second or three. Keep a journal handle (yes a paper one – they don’t need to be booted up to use them) and when you have these simple ideas, write them down. I probably come up with about 10-20 ideas for small programs every single day. I also usually come up with 1 or 2 really huge and complex ones every week. In the time you set aside for your ‘immersion’, walk through these problems diligently. Don’t give up either. When you face tricky problems work through them. Research solutions. Go on IRC and ask questions. Do what you do as a programmer and solve the problems that you face and the fluency will come very fast indeed. Better yet, before you know it you’ll have a burgeoning library of example code that you wrote yourself to tackle a wide range of problems, and real world experience in solving those problems that will arm you to tackle more complex ones further down the road.

My final suggestion for improving your fluency is perhaps the most common sense one. But, if we all followed common sense consciously everyday I’m fairly certain the self-help book market would collapse overnight. Don’t avoid the hard stuff. When faced with a challenging problem dive in. Break it up into as many tiny, testable chunks as you can and then get the tests written. Then get the tests passing. To grow, you need to stretch. You’ll never improve if you keep your code in a nice safe place and never venture into the uncomfortable world of the unknown.

Fluency is a vastly under-rated aspect of being a great programmer. The more you are aware of where your fluency problems lie, the easier it is to focus on addressing them. Great programmers write great code with elegance and style. They do that because expressing themselves in the language of choice is something that comes as naturally as having a conversation with a close friend.

1 Comment »

  1. Hello Peter,

    Thanks for that inspirational (I’m serious!) insight into attaining coding fluency.
    I’ve dabbled in coding several times over the years, but because for me it’s always been for a temporary role, either to solve a student project or as a Support programmer or to fix a transitional problem with a system. I’ve never actually got really fluent with anything – but always loved doing it and always felt an odd sense of loss at the point when the “work” was over. If only I had realised it wasn’t “work” and I could have gone on a perpeptual problem hunt for the sheer pleasure of the challenge.

    Reading your Beg.Vis C# 2005 Exp Edn at the moment and have a real life problem to solve AND this time when I finish I’m going to get as fluent as I can & stay there as long as I can – thanks Mate!

    Comment by Paul Sandvig — November 3, 2007 @ 12:42 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.