How I Work - Software Design as a weak Scientific Process

Alias on 2009-09-22T04:29:16

Matt Trout has asked people to write about how they learned to design programs.

I've also had a number of other people this year ask how the hell do I maintain so many modules.

Being largely an autodidact it's hard to say how exactly I learned design, since most of it was on the job. But I do recognise some elements of my process from before I became a programmer. So here is my story.

I get bored very easily, and I always have. I tend to get absorbed in a problem, a game, a sport, or a TV show, burn intensely on it for a few weeks or months or (occasionally) a few years, and then burn out and move on never to return. This would fine, except that this often it makes it extremely hard to do the same thing day after day and work in the real world.

The way I've adapted to this character trait is to classify issues in life into things that need to be solved (effectively) forever, and things that don't matter much and if they go away it's no big deal. Things that are important I always try to fix in a way that means I never have to revisit the issue.

You can see a lot of this in my CPAN work. I mostly tend to take on small compartmentalised problems that I can solve comprehensively (with two glaring exceptions of course). And I'm quite happy to give away commit to everything because (as long as nobody breaks things that currently work) I don't really care, I'm just not interested in that problem any more.

This has meant my code tends to mostly be reliable and require not a whole lot of maintenance (at a design level), which means that now I have automated away the actual work of doing releases, I'm able to concentrate more on writing new code (or lately, taking over modules) because I rarely revisit problems.

Of course, this means that I tend not to attack problems that are large and thorny. People like Matt Trout and Steven Little, by chasing huge problems with massive commercial scope, do far more for the Perl community as a whole than I do.

The design methodology I've come up with to work in this way is based on a dumbed down mix of the scientific method and engineering practice. 1. Invent hypothesis or steal ideas from others 2. Attack them (utterly ruthlessly) and try to kill the ideas 3. Implement the first decent idea that survives 4. If several options become possible, evaluate on relative merits What I like about this process is that it fits well with the natural way we accumulate lifelong learning and experience.

Talks from places like http://ted.com/ are rich in ideals to steal, as are magazines like New Scientist or The Economist.

The criticism step in my process is the one I've had to work a bit harder at. Normal experience helps you identify bad ideas, but I've found this isn't often enough here. So I've done a fair bit of reading on failure, and these days information on new modes of failure are some of the things I find the most interesting.

I've tried to distill a whole collection of these failure modules into my popular "Nothing Can Possibly Go Wrong" macro-talk, a collection of 2-10 minute problem discussions that I can assemble differently for different audiences and different lengths of time.

I've tried to expand my areas of criticism out to wider and wider areas, and as I've done this I've found that criticism is a great entry into new kinds of solutions.

PPI only exists because we discovered both why you can't parse Perl, and that these problems are mathematically robust. And so the solution is not really about finding a way to parse Perl, it's about a search for a path between all the different impossible problems that allows for something, ANYTHING, that is useful.

This seems to hold true generally. When you are faced with a problem domain that is littered with failed attempts over a long time, often the solution you are looking for is the first one you can come up with that doesn't suffer from endemic problems that killed all the previous attempts.

This methodology is a large part of what drives Padre.

If you look around at all the failed and stale and stillborn editor projects, and you have a calalog of failure modes in mind, you can see that editors and IDEs suffer from four main problems.

1. IDEs are open problems with a soul-crushingly large scope, that run for multiple decades. Contributors will burn out, get bored, lose their jobs, reach diminishing returns of personal value for their efforts, and (for big enough projects) die regularly.

2. Editors are used by the (highly diverse) masses. Ideas about how code "should be" that are baked into the editor, or a focus on one particular set of features at the expense of all others, make it hard to accumulate a long-term userbase. People leave for tools that solve a bigger set of their daily needs in one place.

3. Programming tools written in languages other than the one they are working with suffer a huge contributor penalty. Taking Emacs and Eclipse as examples, while there are many people that separately know Perl well, or know Lisp/Java well, the number of people that know BOTH Perl and Lisp/Java well is orders of magnitude lower. The result is either limited functionality or an editor that doesn't really "think" in terms people that know only the target language prefer.

4. Desktop tools that do not use a native toolkit often don't "look real" in the minds of people familiar primarily with just that platform. This squeemishness is particularly a problem with less technically elite people.

By using a problem-avoidance approach for this notoriously messy problem domain, you get a set of fairly straight forward design principles to follow as a baseline before you even start to address the issue of actually making the IDE work.

1. To attempt an IDE you need a HUGE team. You are going to have to constantly and aggressively recruit anyone and everyone you can. This also means you should expect to have lots of people of varying quality, and structure your project to deal with it. You want features in your IDE specifically to try and convert your users into contributors.

You want a good plugin system, lowest-common-denominator development infrastructure, easy real-time support, mentoring programs, and a culture of intentionally valuing and allowing bad code into the project if it is the first attempt at a new feature. Anything that accelerates the feedback loop for turning users into contributors is a good thing. Less clicks are good, more obvious instructions are good.

The Padre repository has a unique monthly contributor count of about 20. Emacs has around 25-30 but slightly falling. Eclipse reportedly has around 300 across all 45 sub-projects that make up their main release train.

2. Even if you are going to focus on being a "Perl Editor" and add core support for it first, don't limit others adding other languages if someone wants to work on a plugin. If your userbase is spread across divergent platforms, don't pick core technologies that favour one platform at the expense of all others.

Try to adapt smartly to the user, rather than requiring extensive initial configuration to get rid of stupid "sensible defaults". And make sure the core toolkit pieces are smart enough to let people solve their specific development problems, so you aren't holding people back.

3. Unless it horribly cripples the resulting product, write the IDE in the same language as it will be used for. If you do this well, and keep the IDE code simple and understandable, you turn every single user into a potential contributor. There are few things more seductive and freeing to a programmer than being able to make annoying bugs in their tools go away.

4. Use native widget sets wherever possible. If you have a cross platform userbase, either use an abstraction layer that wrap each of the different underlying widget sets, or one that emulates the look and feel so well that people won't notice. If different platforms have different HCI standards, try to adapt to them (for example, don't show toolbars by default on Mac).

Looking at Padre, you can see these four principles at work. Between Gabor and myself, we had all four of these principles in place by around release 0.10.

Gabor has been tireless in reaching out to developer communities for "reviews" and translators. We have a "Live Support" option right there in the help menu that feeds people into our main developer IRC channel, and the "My Plugin" system that bootstraps a plugin for every single user.

We had a plugin system in place almost before we had working cut and paste, and the plugin APIs have had more work done that any other part of Padre.

And the decisions to do an editor in Perl, and using Wx, have fed a huge volume of people into the meat grinder. Even though we have hardly any Mac users, the people that have tried it on Mac have said it looks like they expect it to look like. And although we do have some problems with learning Wx, we never anyone say that Padre "looks weird" or is hard to navigate.


grrr

Alias on 2009-09-22T05:23:45

Apologies for spelling/grammar typos, but editing of posts appears to be broken now on use.perl, so I can't fix the mistakes.

FYI: Monthly contributors to Git

jnareb on 2009-09-22T11:50:16

Just FYI: Git (distributed version control system) has unique monthly contributor count of around 50 (for the last month).

Yep. Looks Mac-ish.

phillipadsmith on 2009-09-23T01:47:58

"Even though we have hardly any Mac users, the people that have tried it on Mac have said it looks like they expect it to look like."

You've got one here. :-) And, agreed, it looks and works basically as I expected. Fingers crossed that it keep improving at the rate it has been.