02 August 2006

On the importance of being the right width

This shambolic post is about the width of things, specifically C++ code, Python code, and GUI windows.

I ran a script on some C++ code today, looking at line width. This probably raises more questions than it answers, but here are the results:

    2-5: #############
   6-10: ###########################
  11-15: ########################################
  16-20: ##################################################
  21-25: #########################################
  26-30: #####################################
  31-35: ###############################
  36-40: ###########################
  41-45: ########################
  46-50: #####################
  51-55: ################
  56-60: ###############
  61-65: ############
  66-70: ##########
  71-75: #########
  76-80: ########
  81-85: #########
  86-90: ###
  91-95: ##
 96-100: ##
101-105: #
106-110: #
111-115: #
116-120: #
121-125: #
126-130: #
131-135: 
136-140: #

This graph shows how many lines are 2-5 characters wide, how many are 6-10 characters wide, and so on. The script ignores indentation and comment lines, and lines that are blank or just have one character (usually }).

So you can see that, for example, about 75% of nontrivial code lines are 50 characters wide or less.

The trailing end of the curve actually goes all the way out to 500 characters, but almost all of these extreme cases involve very long strings.

Looking at some C++ code I personally wrote, the curve is similar, but for me about 75% are 40 or fewer characters wide, and the curve dies out entirely at 115 characters. I habitually break up long lines. Of the longish lines (40+ characters), most are not all that complex. They're long because the things involved have really long names:

  bool ImageGenerator::isImageObjTypeReloadable(uint64_t uObjectType)

  initCustomBasket(pOldBasket->getLocalResourceNameObject());

  Boa::WebBoaSubnetStartAttributes networkAttributes = wbNetwork.getDefaultStartAttributes();

(Disclaimer: Identifiers have been changed to protect the innocent. I'm just talking about line length and complexity, and in these respects the examples are genuine.)

Okay. Now, same script, totally different code sample:

    1-5: #################
   6-10: ######################
  11-15: ###########################################
  16-20: ##################################################
  21-25: #############################################
  26-30: ########################################
  31-35: ##################################
  36-40: ############################
  41-45: ######################
  46-50: ###################
  51-55: #################
  56-60: ################
  61-65: ###############
  66-70: ########
  71-75: ###
  76-80: #
  86-90: 

This graph describes the idlelib directory of Python 2.4. This is Python code, not C++. It's a similar curve, though.

Python and C++ are very different languages, but they (and all modern languages) have this in common: they'll let you write arbitrarily complex code lines. The compiler will accept a 3000-character line without batting an eye.

The teams that wrote these two code samples are undoubtedly very different, but they have this in common: they tend to break complex thoughts into two or more lines.

Part of this is just that it's easier to understand several simple, independent lines than one complicated one. I think part of it is visual, too. But the why doesn't matter; IDEs should take advantage of programmers' tendency to work in lines of a certain size.

Microsoft Visual Studio is an excellent example of an IDE that completely fails to do this. The current MSVS is all about the myriad gadgets and capabilities it offers—in ten trillion fiddly docking panels, none of which shows any tendency to make itself the right size or shape for the information displayed. Least of all the central code window, which initially gapes some 200 characters wide, but spinelessly cedes screen area to each new gadget you open until practically nothing is left.

By contrast, the Inform 7 GUI shows source on the left half of the screen and uses the right half for documentation and play-testing.

I can't rave enough about this arrangement. It works extremely well, at least partly because each half is a comfortable width.

It's possible to mimic this layout in Visual Studio: put Solution Explorer in a narrow strip on the left, code in the center, and a wide tabbed panel for everything else on the right. I'll try it out.

One last note. I have a program called HalfMax in my Startup folder. It runs in the background, and when I hit Windows+1 or Windows+2, it moves the current window to fill the left or right half of the screen, respectively. It so happens that a lot of the programs I use are almost ideal when filling half of my screen (given my font sizes, screen resolution, and so on). Right now I have the following applications open: Microsoft Outlook, an Outlook e-mail message, Perforce, some Command Prompts, SysInternals DebugView, some Notepads, some file Explorers, Microsoft SQL Server Query Analyzer, the Windows Services control panel, TestTrack, a Python shell, Emacs, Araxis Merge, Adobe Reader, Word, Visual Studio, and Internet Explorer. (I think this is just about all the applications I ever use. :) Most of these are either simple browser-like apps, Notepad-like editors, or shells: the kind of app that is significantly better half-maxed than maximized. The rest—Visual Studio, Windows Explorer, TestTrack—use that horizontal space for stuff like docking panels or table-view UIs.

No comments: