fhwang.net

software

The law of constant testing hassle

Over time, technological progress makes it easier to write automated tests for familiar forms of technology.

Meanwhile, economic progress forces you to spend more time working with unfamiliar forms of technology.

Thus, the amount of hassle that automated testing causes you is constant.

And build something you'll keep using

I’m sure a lot of my nerdy readers already saw this, but in case you didn’t, Marco Arment gives good advice about how to get started in programming:

The best way to get started is to rethink the question to be more pragmatic:

What do you want to make first?

Be specific. The answer isn’t “iPhone apps” or “websites”. An iPhone app or a website to do what, exactly?

If you don’t have a specific idea that you’re motivated to create, you’ll have a very hard time getting started and plowing through the hard parts. And there will certainly be hard parts: you’ll get frustrated, go to Google, find some guidance, bang against it for a while, then finally get it working and experience immense satisfaction for as long as you can go before hitting the next wall of frustration. Fortunately, as you get more experienced, you’ll hit those walls less frequently.

It’s solid advice, and for extra credit I’d add one thing: Build something you’ll keep using. It’s one thing to build a one-off Rails site or iPhone app to prove to yourself that you can do it. It’s another to build something that will become a regular part of your life, or a part of the lives of people you care about.

Why do I say this? Because building it just to prove it that it can be done will only get you, say, 80% of the way there. But only by using it regularly will you get immensely irritated by its flaws. The way a UX element can get in some inconsistent state when you click on different parts of the screen in a particular combination. The way that some Ruby gem you thought was so great last month now really seems to get in your way as your needs change. Etc., etc.

Being personally inconvenienced by these flaws is the best single way to get the motivation to take that software from 80% done to 99% done. (100% done is pretty much impossible, so don’t worry about it.) And in doing so, you will learn an immense amount. If the devil’s in the details, there are fewer crafts that are more devilish than computer programming. Programmers are often motivated by grand ideas. But in software engineering, execution matters as much as ideas, if not more.

So, before you ask somebody to pay you to execute for the product they care about, get some practice executing for something you care about yourself.

Is computer programming an art form? Let's get specifical.

The talk I gave at CUSEC last year, Blind Men and an Elephant, compares computer programming to a number of other types of work, with an eye towards finding both similarities and differences. In order, I compare writing code to: math, engineering, writing, law & politics, business, and … art.

I almost left that last one out. Whether or not computer programming is an art form is a subject that attracts a lot of attention among certain groups of people, and I see this more acutely than most since I know a lot of hackers and a lot of people in the new media arts field. But I find the resulting discussion can generate a lot more heat than light. And certainly for computer programmers I dare say that it’s not a very important question. There are plenty of other questions to ask yourself instead, such as “how can I get better at writing code?”, “how can I make sure the work I’m doing is worthwhile?”, and “should I be a programmer at all?”

Perhaps it is worth a discussion, but it would probably be most useful for us to speak from some specific experiences, and not steer ourselves into a morass of vague metaphors.

So let me start, with something I’d written in a comment to Tom earlier today: I don’t think computer programming is an art form. That doesn’t make programming better or worse than art, just different. And the specific experience that leads me to say this goes something like this: In all my years writing code, and in all my years making artistic work, I can’t think of a single time when it was useful to treat one like the other. Even when I was writing code to build net-art, during that the time that I was writing code I was putting on my software engineering hat, and really not thinking artistically at all. Because when I try to write code like I’m an artist, it ends up being buggy, mysterious, and unmaintainable. And when I try to make art like I’m a computer programmer, it ends up static and inorganic.

But maybe other people have had different experiences.

Programmers: If you believe computer programming is an art form, how has that made you a better programmer? What has art taught you about programming that you couldn’t have learned from anything else?

Artists: If you believe computer programming is an art form, how has that made you a better artist? What has programming taught you about art that you couldn’t have learned from anything else?

In which nerds tell jokes and other nerds laugh.

The C Programming Language, by Brian W Kernighan & Dennis M Ritchie & HP Lovecraft

“Cap’n Marsh, see, he’d been dealing with queer folks in the South Sea islands, and they taught him some peculiar ways. Out there on Devil Reef, he built a funct’n that called itself to print any leading digits, then printed out the trailing digit at the end.

“Matt Elliot, Obed’s fust mate, he allus was agin’ it, but he saw it with his own eyes how that funct’n used to call itself up like a serpent eatin’ its own tail–

      void Cthulhu
      (int Ia) {
      if (Ia/10)
      Cthulhu (IA/10);
      putchar // ftagn!
        (Ia % 10 + '0');
      } // neblod zin!

“Twistin’ and writhing like nothing of this Earth, it’d spit out those strings without no heap allocation in sight.”

Google Chrome Issue 31482: Huge amount of goats teleported

Comment 25 by luke.schlather, Jan 12 (2 days ago)

How is it that Chrome still has these enormous show-stopper bugs on Linux? I’m not going to introduce this kind of system instability just to get a mild performance improvement over Firefox. Firefox has never teleported an unreasonable amount of goats. It always keeps it within the acceptable range of my teleporter.

Blind Men and an Elephant

Last January I went to Montreal to speak at CUSEC 2009: The title of the talk was “Blind Men and an Elephant: Thoughts on an Amorphous Profession”. They’ve just put the video online now:

Francis Hwang – Blind Men and an Elephant: Thoughts on an Amorphous Profession from CUSEC on Vimeo.

By the way, CUSEC was pretty amazing, and if you ever have a chance to go I’d highly recommend it. It was a solidly organized event with a great list of speakers. Too bad about it being in Montreal in January: If you go you should probably include long underwear in your travel budget.

Agile in big companies

Tim Bray writes on enterprise computing vs web startups, and there’s not much secret which side he favors. Obviously, I favor that side too:

Here’s a thought experiment: Suppose you asked one of the blue-suit solution providers to quote you on building Ravelry or Twitter or Basecamp. What would the costs be like? And how much confidence would you have in a good result? Consider the same questions for a new mobile-network billing system.

The point is that that kind of thing simply cannot be built if you start with large formal specifications and fixed-price contracts and change-control procedures and so on. So if your enterprise wants the sort of outcomes we’re seeing on the Web (and a lot more should), you’re going to have to adopt some of the cultures and technologies that got them built.

My two cents is that Tim’s right, but there are some non-trivial complications that are worth adding. First is that from the point of view of product requirements I’d imagine that most enterprise computing has complexities that most web startups don’t have to think of right off the blocks. When they were starting out, the terribly smart guys who built Twitter didn’t have to worry that much about decade-old legacy systems, regulatory compliance, or an installed user base of three hundred stressed-out employees who know the old thing just fine. This makes the process of reducing requirements into small sensible iterations harder. Not impossible, but I bet there aren’t many people who are great at it in that context.

Another question is of core competencies. There’s no question that a company like Facebook is a web technology company, so its web technology better be completely awesome, period. Its management will pay more for programmers because 1) it believes it’s important to get good programmers and 2) it believes in its own ability to tell good programmers from bad. But that’s not the case for every company that employs programmers. If you’re in the IT shop of a large pharmaceutical corporation, you’re not the core competency, the medical researchers are. You’re just part of the back office, and most likely, somebody above you occasionally has a conversation about whether they could get more bang for the buck by sending your work to an outside contractor.

Anyway, that relates because I believe that agile methodologies, as great as they are, are very talent-dependent: A bad technical team will do worse with agile methodologies than with something more top-down and constrained. So there are a number of organizations that are going to think “we can’t pay to have top-notch Web 2.0 coders, so we’ll have a big room of so-so coders and hire one architect to tell them what to do.” It’s about limiting the range of outcomes, which when done well, can reduce the possibility of catastrophic failure—as well as reducing the possibility of an astounding breakthrough.

And, yes, if you’re working at a place like this, and you love writing great code, and want to be treated well for writing great code, then it’s probably time to send your resume a few places. I talked about this at RubyConf in my Conversations vs. Laws talk, btw.

One last issue is of culture. Even if you can deliver highly iterative, high-quality code, your enterprise clients might not be able to think iteratively. And let’s be fair: Agile can be tough for a client to get used to. It’s genuinely hard to think about small iterations in terms of interaction design, or organizational workflow, and it can involve a lot of careful planning. More than once I’ve found myself saying things like “they’ve got the old steps 1 through 5 already, this week we’ll be deploying the new step 1 which flows into the old step 2, make sure to let these ten people know that as of Tuesday morning those screens will look different.” Getting these transitional steps right, and communicating to everybody who needs to know, and getting feedback from everyone involved, can be time-consuming.

But it can be done, at least within limits. One funny issue I’ve seen is of credibility and iterations. I worked for a client that was used to seeing new code every few months or so. So you can tell someone like that, “hey we’re the new guys and we’re awesome, we’re going to do a release every week”, and they might smile and say they’re looking forward to it, but they probably don’t believe you deep down inside. They’ve been lied to before.

So this makes weekly iterations actually harder, because a big part of small iterations is having the freedom to say that a given feature isn’t ready, but if they don’t believe there’s another release coming soon, they’ll want to hold up this release for that feature. They want to pile everything on this train that’s about to leave the station, because who knows when another train’s coming?

In the case of this client we actually reduced iterations to every three weeks at first, waited to see if they were comfortable, and then reduced to two weeks, then down to one week. We augmented this with feature development branches and alternate deployments. Over time they got completely hooked on it.

Not to be influenced by the name

Other programmers sometimes ask me why I like dynamic typing, and, sure, I can talk about various specific reasons. It makes refactoring easier, it makes testing easier, and it’s not as if static typing ever caught my difficult bugs anyway.

But, really, this is why I like dynamic typing:

Suppose mind consciousness is observing an elephant walking. During the time of observation, the object of mind consciousness may not be the elephant in and of itself. It may only be a mental construction of the elephant based on previous images of elephants that have been imprinted in store consciousness. Mind consciousness has then lost contact with the particular; now it is in touch with the universal….

Inquiry means not using the function of mental creation, but allowing yourself to get in touch and to try to see how things truly are…. We practice not to be influenced by the name, because when we are caught in the name we can’t see reality.

—Thich Nhat Hanh, Buddha Mind, Buddha Body: Walking Toward Enlightenment

(Incidentally, this Google Books thing is pretty cool; I’d never really looked at it before. But something tells me it’s easier to secure digital rights when the author’s a Buddhist monk.)

How necessary is refactoring?

So, yeah, I get into a lot of discussions about mocks, and why I almost never use them in testing. One of the reasons I give is that I often end up having to do extensive refactoring if I get the overall structure of the code wrong the first time.

I feel like there’s a deeper issue, which might lead to some of the disagreement, which is this: How difficult is it to do a decent design of your code the first time ‘round? If you rarely have to do significant refactoring, then maybe mocking is worth it.

So maybe this’ll demonstrate where I’m coming from:

[admin_assistant (master)]$ git log

commit fdb3c373b69d27e0f9410302836f51de2aef7cfe
Author: Francis Hwang <sera@fhwang.net>
Date:   Sat Mar 14 09:41:43 2009 -0700

    Rrrrrrrr

commit f21355213b636f496314413939b41efb4a7819d7
Author: Francis Hwang <sera@fhwang.net>
Date:   Sat Mar 14 09:30:44 2009 -0700

    don't stop the body rock

commit 81a5ea273d47663525f16e6336fa1fe87f40c3a0
Author: Francis Hwang <sera@fhwang.net>
Date:   Sat Mar 14 09:19:53 2009 -0700

    rhifahct0rr

commit 5d07bd7b5ffd864315867d9f697dcaa501a748e5
Author: Francis Hwang <sera@fhwang.net>
Date:   Sat Mar 14 09:04:09 2009 -0700

    the R-word

commit 36f667199cab32c4ac4ba02b209f456996f34746
Author: Francis Hwang <sera@fhwang.net>
Date:   Sat Mar 14 00:25:13 2009 -0700

    r3f4ct0r

commit d82586bbf4d5a429749e6e2769701031ef7b1b2b
Author: Francis Hwang <sera@fhwang.net>
Date:   Sat Mar 14 00:11:42 2009 -0700

    rearranging deck chairs

commit 9440c364b161455cf095a1a9e33381e715e29564
Author: Francis Hwang <sera@fhwang.net>
Date:   Fri Mar 13 18:32:43 2009 -0700

    refactor

commit 2194a9c80bc0ed10cbb5a7e878b32dd0c867c66a
Author: Francis Hwang <sera@fhwang.net>
Date:   Fri Mar 13 14:31:55 2009 -0700

    rfctr

commit 64a8a4325cdfb083b04ac0de763935b755555e9f
Author: Francis Hwang <sera@fhwang.net>
Date:   Fri Mar 13 09:01:19 2009 -0700

    refact0r

commit 756b023a1fa249cb15e8839bb1538c36e107a79b
Author: Francis Hwang <sera@fhwang.net>
Date:   Fri Mar 13 08:49:59 2009 -0700

    refacteezy

commit e9f5898a76a9a4b1c678f6c3e6e9a71618ac59a9
Author: Francis Hwang <sera@fhwang.net>
Date:   Thu Mar 12 10:06:29 2009 -0700

    refactor

This is for admin_assistant, my very-alpha replacement for ActiveScaffold. I made 11 commits in a row that didn’t add any functionality, they only tried to preserve existing functionality while expressing the problem more clearly. Why is that?

  • Francis is insanely OCD, and this git log is the coder’s equivalent of a girl going over her face with a magnifying mirror and a pair of tweezers,
  • Francis is completely horrible at modeling simple problems and should probably go into a different line of work, like muffler repair,
  • Francis is working on a genuinely hard problem and finds that for this sort of thing, a slow, arduous crawl towards the right design leads to the best design in the end.

Obviously I think Door number 3 is true to a large extent but I could be just deluding myself. And, of course, they’re not mutually exclusive.

Understructuring your code: Roughly right instead of precisely wrong

“It is better to be roughly right than precisely wrong.”—John Maynard Keynes

Last November at the last RubyConf, I gave a talk called Testing Heresies. One of the many strange ideas in that talk was the argument that understructuring your code can actually be an agile practice. That is, rather than decomposing everything down into small methods and small classes, you might choose to temporarily leave your code in a state of slight sprawl, as long as you’ve got decent test coverage.

The other day it occurred to me that I’m getting some of my inspiration on this one from, of all places, the area of finance.

Continue reading “Understructuring your code: Roughly right instead of precisely wrong” »

The virtuous pain of writing your own manual

Today’s release of Lafcadio, 0.9.2, adds a fairly extensive manual to the documentation. There are various tools you can use to write manuals: I wrote mine in Docbook and then used Docbook XSL stylesheets to publish it to HTML. (Thanks to Patrick for pointing out how he did it for Ruby-Web.) But this isn’t really a task where automation can help you much. Writing a manual is a lot of work because writing is a lot of work. This first version took more than a month of my after-work time, which was much longer than I’d expected, and I’m already nervous about how soon it will go out of date as Lafcadio development continues.

Still, I found the process to be worth the time spent. Writing a manual doesn’t just help other people use your software. It also forces you, the writer, to take a bird’s eye view of how your code looks to somebody who’s never used it, which is so easy to lose in the day-to-day when you’re plugging away at a list of granular features and bugfixes. Any strange or arbitrary aspects to the interface become more obvious because the pain you feel in having to explain them probably mirrors the pain of others in understanding them. More than once I found myself thinking “You know, I could just fix this part in the code so that explaining it in the manual wouldn’t take so many damned words.”

Some programmers will tell you that software should ideally communicate its intentions so well that it wouldn’t require documents. This belief is strongest, I suspect, among adherents of Agile methods, and I’d definitely place myself in that camp. But reality often intrudes, and I suspect I’ll never be able to write any non-trivial software that won’t need some explaining.

In the meantime, I’ll probably try to keep updating my docs on a regular basis. I think it’s important to stay close to my users. I wonder what effect it has on the process when you’re in a large technical team, in Microsoft or a major free-software project, where documentation is often delegated to technical writers. Perhaps this arrangement is unavoidable at a certain scale, but that separation also seems like a pity.

One of the many valuable aspects of my tenure at Rhizome was the fact that for more than three years I did the front-line tech-support for a website with more than 1 million pageviews a month. I learned first-hand how easy it is for non-technical users to find web sites difficult or frustrating or even intimidating. And when I rolled out a new change, I could tell within weeks—on the anecdotal level at least—whether it had made people’s lives easier or harder.

After all, who are you writing code for? If you’re writing it for yourself, then no worries. But plenty of us are trying to write it for others, whether those other people are fellow Rubyists or blog advertisers or hedge fund traders. Our profession has a terrible track record at understanding what others need out of the code we create. If you have ways to get closer to those other people, and to understand how to make their lives easier, then those ways are probably time well spent.