rc3.org

Strong opinions, weakly held

Tag: software development (page 14 of 16)

Whitespace sensitivity

Armin Ronacher points out that in some aspects, Ruby is more sensitive to white space than Python. (Via Simon Willison.) What I can say with confidence is that I am more sensitive to white space than Python or Ruby, and I’ll also add that civilized developers adapt to the conventions of the language that they’re using. I guess what I’m saying is that arguments against Python or Ruby based on how they handle white space are fundamentally weak. In the end, they all seem to boil down to, “It doesn’t look enough like C for me to be comfortable.”

How I roll

Inspired by this post where Flickr’s developers talk about their toolset, here are the tools I use to get the job done:

  • 20″ iMac with second 20″ monitor (in the office)
  • 24″ iMac (home)
  • black MacBook (don’t leave home without it)
  • Terminal.app
  • Quicksilver
  • TextMate (for Rails and PHP development)
  • Eclipse (for Java development)
  • vim (for everything else)
  • Subversion
  • MySQL
  • Perl (I still rely on it for one offs)
  • Adium
  • Gmail (all my mail goes through my Gmail account)
  • MarsEdit
  • Google Reader
  • NetNewsWire

Update: I inadvertently removed Firefox (and Firebug) from the list when I was working on this post. I honestly don’t know how people do JavaScript without Firebug.

Adventures in consulting (from June 30, 1998)

Here’s an old essay I wrote back in 1998, reproduced for no good reason. The story is completely true, and the client in question was Pfizer.

Adventures in Consulting, Episode 1

Sometimes as a consultant, you make seemingly innocent suggestions to your clients that end up haunting you for months. For example, I was working on a groupware project, and the client wanted usage reports to see how the application was being utilized.

I innocently suggested that we could beautify the reports with some simple graphs generated using Java applets. The applets came prepackaged with the middleware we were using, and setting them up with dynamic data was trivial. They had drop shadows, nice legends, and all sorts of other eye candy, and the performance was pretty darn good, all things considered. The client was impressed. This is why they pay the big bucks to consultants for these types of things.

Then, I noticed a problem. The client’s site is standardized on Netscape Navigator. Netscape Navigator won’t print Java applets. Faced with the prospect of being unable to print out these eye pleasing graphs, the client was nonplused. Naturally, with our solution crumbling before our eyes and the deadline staring us down, the project shifted into panic mode.

It was too late to pull back, what was once a feather in our cap was swiftly looking like a black eye. The graphs had become a requirement. We were redeemed by a third party product that was only going to cost the client another thousand bucks. It was another suite of Java graphing applets, but this one came with a funky client-server application that allowed you to click on a button and create a duplicate of the page with a GIF instead of an applet.

Sure, compared to the single Java applet, this was a bit more complex. It required two Java applets instead of one, and oh yeah, you have to run a separate server process on the Web server that will generate the GIFs dynamically. Naturally, these additional components hurt performance a bit, but hey, it worked, and when you start throwing in requirements as the project progresses, these things happen.

After we demoed this fine working alternative, there were questions about the speed of Java, firewall issues with the client-server applet, and general issues with performance. Panic again reared its ugly head.

It’s not like we were out of alternatives. Remember, I’m a consultant. The Java applet suite shipped with yet another utility, one which will run a Java applet locally and save a snapshot as a GIF. We could just create a snapshot of each report nightly and let the users go to static HTML pages. This seemed to be a fine solution; at the low price of slightly stale data we’d get great performance and something that works in almost every single browser. The verdict was rendered — the graphs must be generated using realtime data.

At this point, you may think that I was scrambling, but it takes more than a few serious setbacks to put me out of the game. Never mind that the deadlines had come and gone, and our new deadline was a couple of short days away; failure was not an option. In the shower one morning, I had an epiphany. I would write a Perl CGI script that would figure out which report a user wanted (and whether they were allowed to see it), which in turn would call the Java utility, which would call the script that would dynamically render the page and graph, and save the snapshot; and then redirect the user to the new page that was created on the fly. Brilliance.

Sure, it sounds a bit complex, and you might think that there are performance issues with a Perl script that launches Java which in turn loads a scripted web page, writes the page to new HTML and GIF files, and then sends the users to that page, but hey, that’s the price you pay for long lists of convoluted requirements. With a devilish gleam in my eye, I delivered my newest Rube Goldberg creation to the product manager, proud that I had managed to actually meet every single requirement of the project, with no tradeoffs (except for perhaps a small performance hit).

Sitting in my cube, getting started (late) on my next project, I was jarred by the very project manager to whom I had just made the delivery. “It doesn’t work.” What do you mean, I asked. Of course it works. “The page never comes up.”

Innocently I responded, “How long did you wait?”

Blame software

When all else fails, blame a programmer. Credit rating agency Moody’s blames a software error for granting inflated ratings to certain securities. However, as Andrew Leonard points out, it just so happens that Moody’s rival Standard & Poors rated the same securities identically. I guess it’s easier to blame the software than it is to admit you were cooking the books to help out your customers.

Skipping the error handling?

The Relevance blog has an excellent post on simplifying code called Refactoring from Ceremony to Essence. In part it explains why people find Ruby on Rails to be a compelling alternative to J2EE, but it also illustrates a number of techniques applied by Ruby on Rails that could just as easily be used regardless of which language you’re using to develop your applications.

One point in their post directly addresses the “use less indentation” rule I posted about on Sunday. I spoke in favor of doing all of the basic sanity checks up front in a method and avoiding nesting, this post recommends leaving them out entirely:

Conditionals make code expensive to test; so ceremonial conditionals are a particular nuisance. Let framework error handling deal with missing data on the form.

I need to give that one a little more thought.

My rules of thumb for developers: use less indentation

Over a month later, post number two in my “rules of thumb” for developers series. The first post was on writing less code, period. This one is on using less indentation.

What I really mean by this is that I’m strongly not in favor of complex nested code structures. I find them to be difficult to follow when reading code, and to be good places for little logic bugs to hide. How often have you seen code that looks like this?

if (something > 10) {
    if (something < 100) {
        // Do something
    }
    else if (something > 150) {
        // Do something else
    else {
        return false;
    }
}
else {
    while (something < 10) {
        // Do some other stuff
    }
}

I often see conditional structures three or four levels deep, comprising case statements, if statements, and loops of various kinds, and in those cases, it can be very difficult to figure out exactly which conditions have to be in place for a given line of code to be executed.

Let’s look at a really common sort of coding problem:

private boolean doSomeStuff(String str) {
    if (str.equals("something")) {
        // Perform some tasks.
        if (str.length() == 10) {
            return true;
        }
        else {
            return false;
        }
    }
    else {
        return false;
    }
}

I would always write that method like this:

private boolean doSomeStuff(String str) {
    if (!str.equals("something)) {
        return false;
    }

    // Perform some tasks.

    return str.length();
}

Any time there’s a condition that causes code to be skipped, I like to put the return statement above the code that could be skipped. It enables me to avoid a level of indentation and, I think, makes the code more readable. This approach goes hand in hand with the practice I’m going to discuss next, which is to write more methods. I think it’s always better to be able to quickly figure out which code you can ignore when you’re reading through code and trying to figure out why something is happening. In the second version of the method above, it’s easy to see the conditions under which you can ignore most of the code in the method.

It’s particularly important to avoid excess nesting when you’re talking about mixing markup with code, in PHP files, JSPs, ERB templates, or whatever. Excessive nesting can render the source nearly unreadable. It’s almost always better to use includes or other approaches to make it easy to distinguish between the control structures in the page and the markup used to render the page.

This practice may seem pretty obvious, but I don’t think I’ve ever seen it explicitly describe before, and I read a lot of code that includes lots of deeply nested structures. I’d love to hear in comments whether people see any downsides to this approach, because I’m methodist when it comes to writing code this way.

Donald Knuth on unit tests

Programming guru Donald Knuth on unit tests:

As to your real question, the idea of immediate compilation and “unit tests” appeals to me only rarely, when I’m feeling my way in a totally unknown environment and need feedback about what works and what doesn’t. Otherwise, lots of time is wasted on activities that I simply never need to perform or even think about. Nothing needs to be “mocked up.”

If your name is not Donald Knuth, you must continue writing unit tests.

Donald Knuth on mortality:

Naturally, the cancer will be a serious concern. I have superb doctors. At the moment I feel as healthy as ever, modulo being 70 years old. Words flow freely as I write TAOCP and as I write the literate programs that precede drafts of TAOCP. I wake up in the morning with ideas that please me, and some of those ideas actually please me also later in the day when I’ve entered them into my computer.

On the other hand, I willingly put myself in God’s hands with respect to how much more I’ll be able to do before cancer or heart disease or senility or whatever strikes. If I should unexpectedly die tomorrow, I’ll have no reason to complain, because my life has been incredibly blessed. Conversely, as long as I’m able to write about computer science, I intend to do my best to organize and expound upon the tens of thousands of technical papers that I’ve collected and made notes on since 1962.

Analyzing Git

Evaluating tools is sort of like judging art. The two questions you should have about a work of art are, “Do I like it?” and “Is it important?” They’re completely separate. You may not enjoy the music of The Beatles, but that doesn’t change the fact that they were hugely important in the evolution of popular music.

When I’m looking at tools, I try to keep both of those questions in mind. I don’t care for Enterprise Java Beans, but it was important for me to know what they’re used for and why they’re important. Git, the distributed version control application, has been getting a lot of attention lately. I haven’t had a chance to take much of a look at it myself, and I’ve been wondering whether I would like using it. The excess hype has awakened my inner skeptic, but I’m still very curious.

In the meantime, Ryan Tomayko has written an outstanding piece of analysis that answers both my questions. It explains why developers might enjoy using Git, and its significance. What’s important about Git is that it allows you to adapt your version control usage to your working style rather than adapting your work style to Subversion or whatever system you use, in that it allows you to manage exactly which changes you check in at any time, including multiple changes to a single file. Ryan explains how this works by describing the “Tangled Working Copy” problem and how you go about solving it in Subversion and Git.

I never run into Ryan’s “Tangled Working Copy” problem because I have adapted myself to be a creature of Subversion. I am always very mindful of what’s in the current change list and when I want to commit it. But I shouldn’t have to work that way, and it’s very cool that Git lets you escape that model. It seems that’s the important thing about Git.

I wanted to flag Ryan’s article not just because it demystifies some of the Git hype for those of us who are still using Subversion, but also because it represents what blog posts that purport to provide analysis should aspire to.

My rules of thumb for developers: less code

I was discussing basic coding philosophy today and realized that I have a few rules of thumb that I bring to my programming. I guess you’d call them a basic sensibility of how to write code. The four big rules are:

  1. Write less code.
  2. Use less indentation.
  3. Write more methods.
  4. Externalize everything.

I’ll write separate posts for each of these rules, starting with this one.

The “less code” movement has gained a lot of attention over the years, mainly with people migrating to scripting languages (like Ruby and Python) from Java. Using languages that encourage concise coding is helpful, but you can adopt less code as a philosophy regardless of the language you use.

Why less code? When I talk about my work as a programmer, I put it in two categories–problem solving and typing. I want to spend as little time as possible on the typing so that I can spend more time on the interesting stuff. Nothing agitates me more than starting a new project that’s going to require lots and lots of typing with very little problem solving. I consider less code to be an absolute good in this regard. Less code means less typing.

The second reason for “less code” is that it means there’s less code to maintain. I spend a pretty fair percentage of my time explaining why code works the way it does to other people. The more code I have to slog through to answer questions, the more time I spend on the answering. The ideal application would consist of nothing but clear, simple business logic. Declarations, error handling, database infrastructure, logging statements, and network code are required to make the computer work correctly, but in most applications they tend not to be very interesting. Less code of this type is always good. If you can make your application better by spending time on this stuff, do so, but usually there’s no reason to write it and maintain it yourself.

Here are some general approaches that can enable you to avoid writing code you don’t need.

Use Economical Code Constructs

The first is to use the most concise language constructs you can. For example, you can take Java code that looks like this:

Iterator it = someCollection.iterator();
while (it.hasNext()) {
    String foo = (String)it.next();
}

into a block like this:

for (Iterator<String> it = someCollection.iterator(); it.hasNext();) {
    String foo = it.next();
}

That saves you a line of code and a bit of pollution in your local namespace. If you’re using Java 5 you can write even less code:

for (String foo : someCollection) {
    // Do stuff
}

Using the enhanced “for” loop saves you lines of code and leaves you with less namespace pollution and more readable code. This example isn’t very exciting, but it’s the sort of economizing you ought to be doing.

Avoid Redundancy

A second and more important way to write less code is to avoid redundancy. What I mean here is that if you’re using copy and paste when you’re editing code, there’s a very good chance that you’re doing something wrong. It’s almost always the case that rather than copy and pasting, you should be creating a new method and calling it from both places. Two classes that are mostly the same should probably extend the same base class. In cases where subclassing is not the right answer, you should be using composition to share functionality among classes rather than duplicating code.

Obviously code duplication means you have more code, but it also makes your applications much more likely to contain hard to find bugs. When those two methods that do the same thing get out of sync, problems are almost certain to ensue. It’s funny that DBAs understand this incredibly well but many programmers do not. The entire point of database normalization is to avoid storing the same piece of information in more than one place. Programmers should adopt this philosophy as well.

As an example, one of the danger areas for code repetition is in input validation. Redundancy often occurs because validation code is written in two different languages–JavaScript and whatever is used for back end code. I oftentimes find the same redundancy within back end code. The Web layer has one implementation of validation, and there’s also lower level validation that takes place in the business layer. “What describes a valid instance of this object?” is a question that, ideally, will only be answered once.

Pick Your Libraries Wisely

It’s perfectly reasonable to choose libraries in part based on how little code they force you to write. One compelling reason to use Spring (a Java dependency injection library) is that it enables you to avoid writing lots of code that does nothing more than wire your objects together. One of the most compelling advantages of jQuery among JavaScript libraries is that lets you get a whole lot done in a very small amount of code.

This is also the primary advantage of persistence frameworks like Hibernate. They eliminate the need to write code to manage database connections, construct prepared statements and do all of the other database-related chores that lead to more code in an application.

Enabling you to do more with less isn’t the only reason to pick a library, but it’s a big reason to choose one library over another.

Some Other Tips

  1. If you use version control, quit commenting stuff out, instead just delete it. I’m talking about that method you commented out six months ago. Get rid of it. You have a copy in version control and it’s just taking up space.
  2. If you’re a Java programmer, your IDE will probably warn you if you have a variable or a method that’s not referenced by anything. Either that’s a bug or there’s some code you can get rid of.

There’s a whole additional article to be written on this same topic about JavaScript, CSS, and HTML and how you can use them together to produce less code. I’m not sure I’m the best person to write it, though.

Links for April 3rd

Older posts Newer posts

© 2025 rc3.org

Theme by Anders NorenUp ↑