picture home | pixelblog | qt_tools

omino code blog

We need code. Lots of code.
entries for category "broad generalities"
David Van Brink // Mon 2007.02.26 21:06 // {broad generalities future}

Hacking Sawdust, Part I: Atoms? Or Bits?

or, One Way To Use And Enjoy The Carvewright/Compucarve Wood Printer

Atoms? or Bits? This is one of my favorite subjects, since it relates to all the big questions. Brain versus soul, love versus sex, and should I get rid of all my clutter except for this here computer?

Atoms, or bits?

In The Future they’ll be nearly interchangeable. To merely describe a thing, verbally, will be enough to cause its rendering in whatever form strikes your fancy (and budget I suppose). As you speak with the Shop Of The Future you’ll tell it what kind of clothes or telephone you like, and there they’ll be, made to order. Or if you sit down in front of your Television Of The Future it will compose a cinematic masterpiece tailored precisely to your interests and desires, with biometric feedback guiding the story-arc. (Surely, a cinematic masterpiece. No doubt of it.)

Vernor Vinge suggests that this will happen before The Singularity; the classic cinematic masterpiece Forbidden Planet portrays it as the root cause.

Along the way we’ll encounter such hazards as cheap and plentiful “techno” music, and entire villages which look like poorly designed web sites.

But enough about risks, I am but a mere fetishistic technological dabbler, and I’m here to share some of the details of the dabbling with you. For now, at least, a verbal description (into the microphone, please, and enunciate) is not enough, and hackery is still needed.

Suppose you wanted to make one of these:


[stop][go][-][+]

It’s a block of wood carved with some, um, spheres or something. It’s a little hard to tell. Anyway, it came out of a primitive replicator which can in fact be purchased at Sears. But that’s really the among last steps of the process. Before that, a bit of hackery may be enjoyed.

See next entry.

oh, i dont know. what do you think?


Read part one first, please!

Bad Code
The experience of Bad Code comes from the following dissonance:

  • You want to use this code, either as a library or perhaps to improve or fix it. (In some settings it may be that you have to use it.)
  • It resists being used.

In extreme cases, a body of source code doesn’t build. But even if it does, if you can’t discover a way to use it then it has become Bad Code.

I believe there’s two things which contribute the most vigorously to the badness of Bad Code. I’ll enumerate these, and then offer a speculation on how this comes about.

Badness 1: No Examples
Examples can come in many forms. For something downloaded from the interwebs it might be a folder named “Examples”. Nothing wrong with that.

But if it’s a library from the guy in the next cube, it might just be an email with some stuff pasted in, or even some whiteboard scribblings. Remember, I said Good Code lets you get something done in 20 minutes. Talking to the author isn’t “cheating”.

Also, as I’ve previously babbled, unit tests are great. This is another place where an example might be found.

But the key point here is that there are examples of use. And you can find them.

Badness 2: External Dependencies
Here is a recurring property of Bad Code: it depends on everything else being “just right.” That may mean that lots of other libraries have to be in place in some nonobvious way, or that files have to be in certain spots, or that environment or property variables have to be just so. And the perp will innocently say: “But why would you ever run it without all the other stuff?”

Because, my friend, that’s what makes Good Code good.

How Does This Happen?
In my recent experience, this comes about just one way: programmers following a spec.

I know it sounds crazy… but I’ll attempt to explain it in abstract pretty pictures. Here’s a spec, derived from some whiteboard discussions and some anecdotal customer feedback:

And here is the Bad Code implementation of that spec:

It looks just like the spec! Right down to every little kink and error. Of course you can’t use it for something in 20 minutes. Your product took years to develop, and this implementation knows every nook and cranny of that work and depends upon it.

And here’s my vague and unsupportable visualization of the Good Code implementation:

The spec has been deconstructed into a rational architecture. The implementation includes the spec but is not damaged by the spec. Ah, if only pretty pictures could actually be true…

Make It Look Easy
In part one I presented the Mozilla Rhino interpreter as an example of Good Code. It was self-contained and had examples, and was relatively easy to set up and run. And one could say, “Oh but that was a particularly easy case. Of course it can run standalone!” The trick is to make it look easy.

There’s an artist/mathematician named Scott Kim who is known for creating “inversions,” text art like this:


It has 180 degree rotational symmetry. A wise person once pointed out to me that, “Each of Kim’s inversions looks like it was a particularly easy one, don’t you think?” There’s always some little thing that makes it trivial. But it’s not. The trick is to make it look easy.

If it doesn’t look easy, you haven’t worked hard enough.

That’s the art.

In part three I’ll offer a couple of tips that might, just might make your code usable by someone, for example, me, in twenty minutes.

2 comments
Douglas Jones // Thu 2006.09.7 07:457:45 am

That reminds me of a quote I heard about 10 years ago. “If you can’t explain it clearly then you don’t understand it well enough.”

David Van Brink // Thu 2006.09.7 14:522:52 pm

I agree with that!

Though… the implicit full claim would be: “If you can’t explain it clearly then you don’t understand it well enough for me to understand it.” Some people are very comfortable with complexity and transverbal software… but I don’t want to inherit their code… if their comfort level exceeds mine.

Yet another humorous retelling of approximately the same thing: http://www.gnu.org/fun/jokes/pasta.code.html.

Nearly every software professional has heard the term spaghetti code as a pejorative description for complicated, difficult to understand, and impossible to maintain, software. However, many people may not know the other two elements of the complete Pasta Theory of Software.
Lasagna code is used to describe software that has a simple, understandable, and layered structure. Lasagna code, although structured, is unfortunately monolithic and not easy to modify. An attempt to change one layer conceptually simple, is often very difficult in actual practice.
The ideal software structure is one having components that are small and loosely coupled; this ideal structure is called ravioli code. In ravioli code, each of the components, or objects, is a package containing some meat or other nourishment for the system; any component can be modified or replaced without significantly affecting other components.
We need to go beyond the condemnation of spaghetti code to the active encouragement of ravioli code.
— Raymond J. Rubey

The problem is that we each of us can read these sentiments and think, Oh yes, of course I do that!

oh, i dont know. what do you think?


Well, I’ve been holed up in my dank apartment these last 3 weeks, canvas and plastic stapled over all the windows. I’ve been writing furiously. Red-pencil scribbles cover tablet after yellow Big Chief writing tablet with my profound wisdom and observations. I feel myself following in a great tradition… Dear reader, allow me to share with you some morsels which you might find entertaining or even informative. This is to be the first of a three part epic on the subject of Bad Code.

Introduction
What makes “Bad Code”? I feel like I’m tormented and dogged by Bad Code. Some of it is my own. Naturally I’m less bothered b my own Bad Code than my other people’s bad code, because I have at least some insight into the perverse intent of the code when it’s my own. But it’s still Bad Code.

What makes Bad Code?

Oh, there’s endless modern kid-stuff about good practices and code smell and all that nonsense. It’s my experience that even good kids who learn all about test-driven development and favoring composition over inheritance and all that rubbish and follow it to the letter still write Bad Code.

What makes Bad Code bad?

First of all, it has to be code. You wouldn’t call it Bad Code if you experience it as an application or tool or whatever. You’d call it a bad app, or a bad web page. I’m talking about Bad Code. You typically experience code in the form of a library that you want to use or source code that you’re called upon to modify.

Here’s my definition of Bad Code: If you can’t load it into your IDE and make it do something interesting under your control in twenty minutes, it’s Bad Code.

Let me justify this first with a counterexample of some Good Code. Oh yes. Cranky am I, but praise is possible.

Some Good Code
One of Mozilla’s open source projects is Rhino, a JavaScript interpreter. (Actually it is officially called ECMAScript now, but whatever.) Why is this Good Code? Let me count the ways:

  1. It’s easy to find: http://mozilla.org/rhino/.
  2. It was easy to download. A full source drop was 1.7M.
  3. Although it wasn’t an Eclipse project, it imported perfectly into Eclipse as a “Java Project from Existing Source” with almost no errors. A fast look reveals that all the errors are in one package implementing XML stuff, and its referring to org.apache.xmlbeans. On a whim, I remove that entire subpackage and apparently nothing else was depending on it.
  4. There is clearly marked “examples” directory…
  5. The examples are named, have a few comments which are enough to get the lay of the land.
  6. I create a blank .java file, and start copying bits and pieces from the example into my new file. Soon, I have a tiny piece of code which I think I understand pretty well, and does something explicable

Here’s some code. I know it’s a bother, but give it a read. It’s short. It would mean a lot to me. And remember — it took me less than 20 minutes to get here.

public class DvbScript {
    public static void main(String args[])
    {
        Context cx = Context.enter();
        try {
            Scriptable scope = cx.initStandardObjects();
            String s;

            s = "var abc = 13/7;";
            cx.evaluateString(scope,s,null,0,null);

            s = "var xyz = Math.sin(1.33) + "*****";";
            cx.evaluateString(scope,s,null,0,null);
            
            Object abc = scope.get("abc",null);
            Object xyz = scope.get("xyz",null);
            System.out.println("abc is " + abc.toString() + " and is a " + abc.getClass().getName());
            System.out.println("xyz is " + xyz.toString() + " and is a " + xyz.getClass().getName());
        } finally {
            Context.exit();
        }
    }
}
Produced this output: abc is 1.8571428571428572 and is a java.lang.Double xyz is 0.9711483779210446***** and is a java.lang.String

In that brief bit of code, I managed to successfully exercise the library and begin to understand the internal scheme of the interpreter.

Why It Was Good
It wasn’t a completely bump-free ride. I had to slice out part of the source code as downloaded… I deleted a whole lobe of the source tree that appeared to be all about XMLBeans or some such. But it was painless. Their one dubious external dependency on org.apache.* was isolated and optional.

The examples were easy to find, and they ran. At first they produced exceptions, but then I read the source code comments and knew what to pass on the command-line and all was well.

Fundamentally, as a user of this library, this Good Code, I felt like I was the target audience. Someone had considered that I would be sitting here today trying to run their stuff.

Now, here’s the thing of it: Bad Code feels the same way. It feels like someone has consciously considered that I, David Van Brink, would one day try to use their stuff, and has premeditated ingenious ways to thwart that goal.

In part two I’ll be cheerfully exposing some of the strategies that Bad Code takes to torment me.

oh, i dont know. what do you think?


David Van Brink // Tue 2006.08.1 23:21 // {broad generalities code}

ST Development

In which dvb considers “named software development methodologies” to each be passing fads… But testing, aah, there’s something to that.

The Claim

A few well-placed tests in your flow can offer benefit far out of proportion to the investment required.

Discovering Testing

There’s lately much chatter about “development methodologies”. At my workplace there was all sorts of endless noise — mostly amongst those not coding — about pair programming and how using XP will guarantee that you can ship your product any day you like, and there’s no need for Alpha or Beta testing, and possibly cure Morgellon’s disease, and such the like. Then the product development cycle began and it was business as usual, fortunately.

One significant change did come from all that pointyhaired murmuring though, and that was the mandate for unit tests. Using unit tests has improved the process immeasurably. No… that’s not right. It’s improved the process measurably.

You’ve probably heard the ritual: “Write the test first.” I don’t know about that… occasionally I do that. But I can explain the concept much more approachably, if perchance you’re not already a believer.

Here’s what I used to do. I’d write some new subroutine (we used to call them that), and then I’d write a little test for it:

int main(int argc,char **argv)
{
	printf("I get: %d\n",newSubroutine(17));
	exit(0);
	// note to self -- dont check in the above!!
	initApplication();
	checkUserPreferences(argc,argv);
	eventLoop();
	exit(0);
}

I’d build the application, make sure it printed out the right answer, and then delete the test. Delete the test! A “unit test” is just something you keep around, instead.

When I first tried out some Java unit tests with junit, it was profoundly obviously a good thing. (Junit is approximately a tool that runs all the methods named “testSomething” and counts up the ones that programmatically assert a “failTest” method. If you’re coding Java, just use it. End of story.)

Testing QT_Tools

It’s also crept into my personal projects. That’s how right it is.

For my personal projects I don’t use “test-driven development”. I don’t write tests first, or make sure that every case is covered, even really ensure that they’re “unit tests” per se. But I have started to run some tests. I do this as part of my Makefile, and it improves my confidence enormously, even minor tests. And you don’t need any big testing infrastructure, just another target that runs.

I think of this as “ST Development” for “Some Testing.” It turns out to be infinitely better than no testing. (Do the math.) And it’s ever so much more civilized than relying solely on manual testing.

For qt_tools (a freeware Mac OS X product of mine) I run a Perl script to check that everything built correctly and that a few simple cases work. I don’t use any formal testing framework… I just ape junit with simple ad-hoc Perl functions like:

      sub assertEquals($$$)
      {
          my ($what,$want,$got) = (@_);
          die "ERROR $what: $want != $got" if $want != $got;
          print("good: $what == $got\n");
          $assertCount++;
      }

I now keep a link to the test results right on the qt_tools front page. I like to think it lends a professional aura to the affair.

Here’s the Perl qt_tools testing script:

Testing a WordPress Plugin

In developing the WordPress plugin used to show code on this blog I found myself going through the following cycle: Edit the plugin, run “make” to copy it into the blog tree, and then manually edit a draft post to see if it worked.

More often than not, I’d get a PHP error page due to a syntax error, much less a proper result from the plugin. And the cycle time was ridiculous! Hitting reload in the browser and typing a fresh post… come now!

One of the characteristics of a “plugin” is that it lives in a well-defined environment and follows a well-defined contract. This is perfect for unit testing. I created a PHP program that invokes the plugin with a few simple cases, checks the result for sanity, and returns a Unix error code appropriately. In the Makefile, the “test” target is a dependency of the “all” target. This means that the Makefile won’t even copy it if there’s a syntax error. Just running the thing for syntax has saved me countless tedious browser reloads! And checking the plugin for correctness was at first just icing on the cake, but became essential as I loaded more and more features atop. Again, there’s no “testing framework” or any of that, just some handrolled “assert” methods that count up correct and incorrect responses.

Here’s the PHP test:

And here’s the Makefile:

Conclusion

I don’t aim to give an explicit “how to” for testing. The message I’m trying to convey is that no matter how tight your schedule is — my personal projects are squeezed in an hour or three here and there — a few thoughtfully-placed tests in your flow are well worth the effort. Absolutely.

1 comments
Daniel Jalkut // Sat 2006.09.23 17:245:24 pm

I somehow glossed over this article when you first published it. I am also a member of the “ST Development” club. I have not been able to bite the hook of test-first development, but I rely on and appreciate test suites in some of my Cocoa code – specifically where I expect there to be a lot of vulnerability to failure.

For instance, in FastScripts, I have code that pays attention to the state of the user’s script directory and updates on the fly, reacting to files being moved, deleted, added or modified. It would be way stressful to try to think about this all the time, so I just wrote a test suite that puts the code through “all the usual cases.” It gives me great confidence after tweaking something down deep in the code, that all the tests show up green in Xcode.

I like the idea of testing for syntax in a web plugin situation. That’s a great idea, and something I’ll try to integrate into my WordPress/Xcode environment.

oh, i dont know. what do you think?



(c) 2003-2011 omino.com / contact poly@omino.com