How I See Software Systems

May 14th, 2009
Comments Off

I’m pretty sure that I have a knack for designing software systems that make sense. This might be because I have a ridiculously inflated sense of self worth, but I choose to ignore this possibility.

Rather than try to establish any kind of track record or credentials that establish that I am honestly entitled to lecturing about anything, I am going to try to explain what properties I consider to be important in a well-built software system, and take a stab at explaining what benefits are to be had from them. (further disclaimer: I make no claim whatsoever that any of these ideas are the least bit novel)

So, without further delay…

Well-Constructed Software Systems are Object Oriented

Controversy!

I am not going to try to say that building a procedurally-styled system will directly cause a nuclear war with Russia. There are lots of smart folk out there who have figured out a large number of successful ways to build software.

I will, however, say that objects are a super-robust, structured way to parameterize behaviours, and that hiding implementations behind polymorphic interfaces is fantastic for simplifying TDD. I think these things are super-important and I derive oodles of joy from working with code that is built this way. Unless I totally screw this blog post up, the reasoning will become apparent in a few paragraphs.

Well-Constructed Software is Unit Testable

There are people out there who have built amazing software without any automated testing, and there are people who just go for full-on integration tests all the time, and there are even people who do lots of complicated algebra to prove that their application is correct in all cases. In my opinion, the best camp to be in is the one where you carpet your application with a thick nest of unit tests, and throw in integration tests wherever it feels good. (and whenever you fix a bug)

This is a great situation to be in because unit tests are very, very fast, and they are the only kind of automated test that you can really count on to be 100% reliable. Further, once you get good at them, you can punt your slow, unreliable (but oh-so-handy) functional tests on some build slaves somewhere else, so they do not intrude upon your continuous integration/deployment/stuff.

Well-Constructed Software Systems Mostly Form a Directed Acyclic Graph

The previous point was actually sort of a precursor to this one. Objects and interfaces were exciting 20 years ago maybe, but we are in the distant future (the year 2000!) now and that means that OO is passe.

A much more interesting and useful claim to make, I think, is that the references your object system has should mostly form a DAG. What does that mean? In short, it means that you have classes “at the top” of your application (you might have one called Application or MainWindow, to pick an example), and, from there, the references mostly trickle “down” to implementation details like file handles, sockets, and textures.

More to the point, it means that your “down” classes do not hold references that go “up”. If you show me a design that requires that your Texture class hold a reference to its Application, my instinct will be that something is not right.

Further, it means that you really want to avoid having “sibling” objects that form a circular relationship. Thar be dragons. And no, I’m completely incapable of articulating why. If cornered, about the best I can do is mumble some incoherent bullshit about how it offends my senses and how it will, at the least, throw more than a few garbage collection implementations for a loop. (which, I should point out, can become particularly serious if the cycle spans different programming runtimes, like Python and C++)

This is a great property for a software system to have because you can test your “lower” types without even needing to construct the “higher” ones at all. This means that individual unit tests need to execute less code, which means easier maintenance, higher orthogonality, and faster tests.

There’s a catch with this one, of course. When I say “mostly,” I really do mean mostly. All too often, you’re going to be in some situation where you really need to attach a listener or a lambda or whatever. Don’t sweat it, but you really want to take a closer look at those upward-pointing references. You might want to make them weak references instead of strong, and, if you’re coding in a statically-typed language, you almost certainly want that reference to have an interface type, rather than a concrete class. Sometimes, you can even clip those references entirely by leveraging method return values.

Well-Constructed Software Systems Do Not Depend on Global State

Remember the bit about the Directed Acyclic Graph? Global state is like having an object that is referred to by every other object and function in your entire application. It’s a ridiculously bad idea.

That being said, I periodically break this all the time because I’m lazy as hell and I’m always so sure that I’ll get away clean this time. If there’s anything I love to cut, it’s corners. Most of the time, I hurt dearly for my transgressions. I fail to learn my lesson because I’m retarded.

The thing is, I really like test-driven development, and if there’s anything that wrecks TDD, it’s unreliable tests. And if there’s anything that makes tests unreliable, it’s state that leaks in from outside the test harness. That’s what global variables are.

It sounds really painful, but what you really should be doing is injecting all your dependencies. In practice, it really is painful, but only until you realize that globe-spanning dependencies are generally a sign that your design has other problems.

What this means is that your objects always work with whatever you give them. If you’re in a test and you give an object fakes, you have pretty good assurance that it’s only going to talk to fakes.

One testing practice I have had great success with is only mocking out the hardware level stuff: Filesystem, network, sound, video, windowing, and so on. These are ultimately the things that make tests slow and frail, so they clearly have no place in my unit tests. Once the hardware stuff is faked out, the other objects in the system cease to pose a threat to testability: are just bits swimming around in memory. When all your dependencies are explicit, formal parameters, this is very easy to accomplish.

so…

There’s a reason for all of these painful rules, and it basically boils down to this:

def testMyCrap(self):
    hw = FakeHardwareServices()
    o = MyCrap(hw)
    self.assertEqual('something', o.doSomething())

Bam. That’s it, right there.

Looks like the toy example everyone uses to introduce TDD, right? Sure, but there’s a trick: I have gone out of my way to ensure that all of my objects accept their dependencies as formal parameters, and I have ensured that none of my objects gank or poke random global objects. I’ve also ensured that none of my objects require ridiculous heavy upstream dependencies to clutter everything up.

I know that I can test every single class in my application from this template, and I can do it in a way that will run instantly and pass 100% of the time.

Uncategorized

The Vingean Programmer Archaeologist

February 25th, 2009
Comments Off

First, if you have never read Vernor Vinge’s A Fire Upon the Deep, you are missing out on a truly outstanding science fiction novel. Go ahead and read it. I’ll wait.

Secondly, if you still haven’t read it, the “Programmer Archaeologist” is but one of a great many cool science fiction concepts that occur in this book. The basic premise is that faster-than-light travel and information exchange set the stage for an intragalactic Internet that is so vast, and so old, that it has literally outlived every civilization currently using it. This is an internet that is literally hundreds of billions of years old, cobbled together from a billion spacefaring civilizations using at least as many layers of virtual machines, emulators, and natural language translators. History records extend back just as far, if you can find the right combination of indexing engines and language translators to turn the records into something you can use.

In such a setting, essentially all useful software really has been written already. In order to do useful work, it follows then that you do not really need to write code anymore: you have to find code that already does what you want, and stitch it together with other code to make it do what you need. The sheer vastness and complexity of the computer systems make it virtually impossible to manage these systems any other way. (imagine trying to reimplement a 10-billion-line codebase!)

Thus is born the concept of a Programmer Archaeologist: a person whose vocation is to find and patch bits of code together to adapt software to new requirements.

It’s a wonderful concept, but it’s more than that: it’s a direct extrapolation of today’s state of the art.

To pick an example I know well, IMVU’s service is a combination of a large number of independently authored technologies: Apache for HTTP, MySQL for relational storage, Perl, memcached, Mogile, PHP, Python, Flash, Win32, PIL, and on and on and on.

Large, uniform, designed ivory tower projects still exist, of course. Mozilla, to name one, has reached somewhere around 30 million lines of code, and it is all highly internally consistent.[citation needed] For the most part, though, we are the Programmer Archaeologists, today. (at least, we probably are if we’re getting useful work done!)

Uncategorized

Scheme as the Language of the Internet

February 24th, 2009
Comments Off

One thing that has always bugged me about the web is that it is composed of so many discordant technologies, all cobbled together as best as the original architects could manage. We write our web pages in Java and PHP and Perl and sometimes even in C++ to generate a particular dialect of SGML, style it all up with a special one-off syntax that has nothing in common with anything else, and script the client in JavaScript. It works, and experience has taught me that the state of the art will always follow this pattern, however much one might wish for a unified, ivory tower solution to wrap it all up.

Despite this, I’ve always been interested in the possibilities of replacing all of the above technologies with a single language: Scheme.

Scheme has basically all the features you could ever want, plus the one feature that lets you build all the rest. Further, its super-regular syntax makes it an outstanding data description language. In other words, it’s the omni-purpose DSL.

Basically, the way it would work is that your scripts would generate a document tree. Consuming this script, and transforming it into HTML, CSS, and JavaScript would be relatively straightforward. It might even be feasible to do enough static analysis to generate AJAX services for server logic that is initiated by client events.

So, to randomly djinn up an example, we’d be able to do something like this*:

(link (label "Send")
      (style
       (image-src "button.png")
       (mouseover
        (image-src "button-mouseover.png")))
      (onclick
       (lambda ()
        (do
         (mysql-query
          (concat "INSERT INTO messages (text) VALUES ("
                  (get-element-value 'text-box)
                  ")"))
         (show-dialog "Your message has been sent")))))

There are a few things that make this not quite the Greatest Idea Ever. The first one is that I don’t think Scheme is the most pleasurable language in the world to write.

The second one only came to me recently while revisiting the idea, and it’s the really important one: why bother? Such a system would mean abandoning all of the tools and expertise out there, and all for what? Sure, it’s theoretically cool, but, even if you could mix your client and server logic with your layout and presentation, would you really want to?

* I don’t remember how to do things in Scheme at all anymore. I am probably butchering the syntax. Sorry!

Uncategorized

Why are you trying to solve this problem?

February 23rd, 2009
Comments Off

I tend to be an Answer Guy. People like to ask me questions about technical things because I like to help them solve problems. It cool because it inflates my ego and gives me an outlet for my chronic intellectualism.

Most of the time, the questions I get are of the “How come doing Ridiculous Thing X doesn’t work?” variety, and while I’m not always quite perfect at recognizing the fact, the first thing I should be doing is to ask “Why are you trying to do this?”

To pick an example, a friend today asked me “Why does calling SetCursorPos() to the center of my window instead move it to its bottom edge?”

We never did figure out what was going on, (I am not as smart as Raymond Chen) but we didn’t need to. Upon asking the fellow why he is doing this, everything snapped into place:

“I’m doing mouselook [for a game].”

Now the solution becomes very simple: instead of trying to rig the mouse up so that it is stuck in the middle of the window, he can just use DirectInput to poll its motion directly.

So, the next time you find yourself banging your head against a hard problem that feels like it should be easy, before you go to your own answer guy, you should ask yourself “Why am I trying to do this?” and reconsider all the assumptions that lead you down the path you’re on.

And if you are still stuck, be sure to let your own Answer Guy know what your goal is, so he can help you figure out what the right problem is.

Uncategorized

Time Out

February 22nd, 2009
Comments Off

Back on February 6th, I somehow let myself get sucked into a project: blog about something every day for a month.

Having, in the past, blogged on and off about various random technical things, I thought it would be fun, and it has been, but never in my wildest dreams did I imagine that it would be so soul-rendingly exhausting.

Sometime in the coming weeks, I will figure out a more relaxed schedule that I can actually sustain. I think I want to take a crack at writing a web application in a functional language. Perhaps Haskell.

Until then, so long, and thanks for all the fish!

Uncategorized

Filler: That Feeling of Dread You Get When You’re About to do Something Stupid

February 21st, 2009

One problem I frequently run into while writing a bit of code is that, while I have The Way The World Should Be mapped out in perfect detail, and I can see all of the possible links and interactions, I will have trouble encoding those ideas in tests because, well, ChildWindow really has to be able to call methods on TopLevelWindow, even though this necessitates a circular dependency which is bad and so on and so forth. (this particular example is kind of lame, but I hope it carries the point)

By this point, I haven’t even actually started coding anything, and I am already feeling squeamish about actually doing it. I have two options: pace around, think, and maybe talk to the smartest guy within arm’s reach about it until an appealing structure presents itself, or I can stop being such a bitch and write the code that gets the job done so that I can get paid.

By now, I have run across the circular reference problem enough times to know exactly what happens if I take the “suck it up” approach: Testing ChildWindow now requires that I construct a TopLevelWindow (which is a much heftier class), which slows my tests down and bloats my test boilerplate. If the objects in question are not implemented in the same language, it is very easy to create a memory leak in this way, and let me tell you, tracking down a reference leak created by a cycle between C++ and Python objects sucks to track down until you’ve done it a few times. (PROTIP: if gc.get_referrers(o) returns an empty list, your object is being kept alive by something that is not a Python object. This, unfortunately is the happy path for such a scenario)

I think I have a pretty good handle on this particular “oh shit this can go south” situation, but I am always on the lookout for more, and I am very glad for that feeling of dread I get whenever I am about to do something stupid.

Uncategorized

Random Information: C++ Function Pointer Syntax

February 20th, 2009
Comments Off

C++ pointer syntax is many things, but is not pretty. It is so un-pretty that, around the office, I have somehow wound up the local expert in the field of typing them out.

The syntax is really arbitrary and complicated, but, if you strip it down, it’s pretty basic.

Non-class-method pointers are pretty familiar. They come up all the time in C, and they look like this:

ReturnType (CALLING_CONVENTION *NAME)(Arg, Arg, ...)

CALLING_CONVENTION is going to be something like __stdcall, __cdecl, __fastcall, or whatever. It is optional.
The “NAME” bit is the confusing part. That’s where the name of the type or the variable goes. For instance:

// declare a variable named 'ptr', that points to a
// function that takes an int, and returns an int
int (*ptr)(int);

// Make a typedef for a pointer to a function that takes no arguments,
// and returns a double
typedef double (*DoubleFunction)();

Pointer-to-method

These are almost the same, but you have a class name and a ::

// A variable named 'ptr' that is a method of type T,
// takes no arguments, and returns void
void (T::*ptr)();

// Declare a typedef for a method on the IDirect3D8 interface.
// (all COM methods use the __stdcall calling convention)
typedef HRESULT (__stdcall IDirect3D8::*D3D8Function)();

That’s about all the useful information there is to have about typing out function pointers that do various things. Just for kicks, let’s dive into insanity:

Function References

There is also a such a thing as a function reference. They’re just like other kinds of C++ references. ex:

void call_a_function_reference(void (__cdecl &this_is_the_parameter_name)(int)) {
    this_is_the_parameter_name(0);
}

const

oh god what the hell is going on here

void try_to_clobber_a_const_function_pointer(void (* const parameter_name)()) {
    parameter_name = 0; // illegal because this parameter is const
}

Uncategorized

Testable Web UI VII: Postback

February 19th, 2009
Comments Off

Last time, we got a bit derailed by some issues that were getting in the way of effective tests. Now that that’s all wrapped up, let’s implement selecting equipment.

The primary requirement here is that we have to display the player’s equipment, and when they select an item by clicking on it, we post to the server to save the player’s selection.

First, I populate the inventory list with the result of another JSON service. This is nothing new, really, so I will skip the details. However, I will need the __renderInventory function for the next step:

__renderInventory : function(inventory) {
    var n = this.__getChild('inventory');
    while (n.firstChild) {
        n.removeChild(n.firstChild);
    }

    for (var index in inventory) {
        var i = inventory[index];
        var li = document.createElement('li');
        li.setAttribute('class', 'inventory-item item-' + index);
        li.innerHTML = i.name;
        li.onclick = function(self, index) {
            self.__equipItem(index);
        }.bind(self, index);
        n.appendChild(li);
    }
},

__equipItem : function(index) {
    // TODO!
},

To write this test, I expanded FakeNetwork a bit, to encompass the ability to make POST requests as well as GET:

function FakeNetwork() {
    this.requests = {};
}

FakeNetwork.prototype = {
    asyncRequestJson : function(url, onComplete) {
        this.requests[url] = [null, onComplete];
    },

    post : function(url, data, onComplete) {
        this.requests[url] = [data, onComplete];
    },

    isRequestPending : function(url) {
        return url in this.requests;
    },

    getRequestData : function(url) {
        Assert.isTrue(this.isRequestPending(url), 'FakeNetwork: "' + url + '" has no data, as it is not pending');
        return this.requests[url][0];
    },

    completeRequest : function(url, result) {
        Assert.isTrue(this.isRequestPending(url), 'FakeNetwork: "' + url + '" is not pending.');
        this.requests[url][1](result);
        delete this.requests[url];
    },
};

This allows me to write the test:

testClickInventoryPostsToEquipService : function() {
    var sw = new StatusWidget('avatar-1', this.net);
    YAHOO.util.UserAction.click(getNode('avatar-1', 'equipment'));

    this.net.completeRequest('getInventory.json', [
        {name:'Clown Shoes', kickboxing: 9001}
    ]);

    Assert.isFalse(this.net.isRequestPending('updateEquipment.php'));
    YAHOO.util.UserAction.click(getNode('avatar-1', 'inventory-item item-0'));

    Assert.isTrue(this.net.isRequestPending('updateEquipment.php'), 'Service not dispatched');
    Assert.areEqual('Clown Shoes', this.net.getRequestData('updateEquipment.php').name);
},

The implementation is so simple as to be boring:

__equipItem : function(index) {
    this.net.post('updateEquipment.php', {name:this.inventory[index].name});
},

The last gap that is missing is that our real Network object can’t POST yet, but that is not sufficiently exciting to post here. (also, I don’t know how to write a functional test without writing some kind of CGI service, so I am going to cop out :D)

At this point, we’ve covered just about all of the major sticking points: introspecting CSS and the DOM at runtime, test isolation, asynchronous logic, mocking the network, and, of course, tests that are both reliable and really bloody fast: I ended with a pretty modest test suite of 7 tests that take (on my machine) 381ms to run. I’m about to call the experiment a raging success.

Tomorrow, I will talk about… something. It will be a surprise to everyone!

Source code

Uncategorized ,

Testable Web UI VI: The Evils of Shared State

February 18th, 2009
Comments Off

So, last time, we got to showing an inventory panel when clicking a menu item. Since I cheated last time and wrote the code to hide without a test, let’s start off by fixing our mistake:

testClickEquipmentTwiceHidesInventory : function() {
    YAHOO.util.UserAction.click(getNode("avatar-1", "equipment"));
    YAHOO.util.UserAction.click(getNode("avatar-1", "equipment"));

    Assert.areEqual(
        'none',
        getNode("avatar-1", "inventory").style["display"]
    );
}

Easy, right?

Wrong.

As written, this test fails because the initial state of the display is not what we expect it to be. In fact, we can’t rely on its state being anything because YUI Test explicitly states that it will run tests in whatever order it darn well pleases, and we’ve yet to do anything at all to try to clean up after ourselves.

We’ve come a fairly long way without bumping into this, but this always happens whenever your tests have some kind of external dependancy. Sooner or later, they start tromping all over each other, and you have to figure out what to do.

We have a few options:

  1. Make StatusWidget itself responsible for generating the HTML. This wouldn’t be bad from a design standpoint, but it means that the user might see an incomplete page if page loading takes too long.
  2. Write a setUp() function to initialize the state of our HTML to something that we expect. This isn’t quite as robust as destroying and recreating it every test run, but it will be fast and easy. The only catch is that we will have to keep changing our setup every time we add more to the markup.
  3. Wire the test setUp() to completely regenerate the HTML before every test is run. This is pretty good, as it doesn’t force us to make any design treadoffs that might not pan out, and it will be robust in the face of changes to our widget.

Generally speaking, you can usually assume that the scorched earth approach to setting up your testing data will be the right way. I’ll demonstrate why in a moment.

This, as it happens, is pretty easy. I’ll just put the HTML in a hidden ‘template’ div, and copy it before every test run:

setUp : function() {
    var t = document.getElementById('avatar-template');
    document.getElementById('avatar-1').innerHTML = t.innerHTML;
},

We also need to make a tiny change to the markup:

<div id="avatar-1" class="avatar"></div>

<div style="display:none">
    <div id="avatar-template" class="avatar">
        <div class="name">andy</div>
        <img class="avpic" src="avatar.png" />
        <div class="details">
            <div class="hitpoints_panel">HP:
                <span class="hit_point_score">5</span>
            </div>
            <div class="kickboxing_panel">Kickboxing:
                <span class="kickboxing_score">6</span>
            </div>
            <div class="linear_algebra_panel">Linear Algebra:
                <span class="linear_algebra_score">7</span>
            </div>
            <div class="cross_stitching_panel">Cross-stitching:
                <span class="cross_stitching_score">8</span>
            </div>
        </div>
        <div class="main_menu">
            <div class="equipment">Equipment</div>
        </div>
        <ul class="inventory"><li>Filler</li></ul>
    </div>
</div>

This still fails, though, and when I click the Equipment button manually, it fails to do anything. What gives?

This does:

testClickEquipmentExpandsInventory : function() {
    // Conspicuous lack of: var sw = new StatusWidget('avatar-1');
    YAHOO.util.UserAction.click(getNode("avatar-1", "equipment"));

    Assert.areEqual(
        'block',
        getNode("avatar-1", "inventory").style["display"]
    );
},

As you can see, test dependancies are insidious, and, if we hadn’t pulled out the big hammer and blown the DOM away before every test, we would never have noticed this particular bug.

Tomorrow, we’ll get to populating the inventory.

Source code

Uncategorized ,

Testable Web UI V: Clicky!

February 17th, 2009
Comments Off

Last time, I started diving into using a JSON service to pull statistics into an HTML widget. I stopped right after that point because I thought, at the time, that it was worth spending a moment to think about what the target design should be.

After spending a few minutes staring at the code, though, I think I’m okay: StatusWidget is fully complaint with the SRP, and whatever other rules I can think of. So, instead of pontificating on what separates a serviceable design from a superior design, I am instead going to code more things!

Let’s go back to the initial set of requirements:

  • I want to see my character’s picture, name, and statistics
  • I want to be able to pick some equipment for my character
  • I want to see how my character’s equipment affects its statistics

The first one seems to work fine, so let’s move on to selecting equipment. Time to start coding some interactivity!

What I’ll be doing next is a sort of ‘drawer’ interface: A “Show Inventory” button that, when clicked, will toggle between displaying and hiding an inventory view (that we also have to code)

The current pattern I have been running with is to just dump markup into the test file, which is probably not sustainable (TODO: figure this out), but for now, it seems to be scaling pretty well. Let’s throw a menu in:

<ul class="main_menu">
    <li class="equipment">Equipment</li>
</ul>
<ul class="inventory"><li>Filler</li></ul>

It doesn’t look like much, but we’ve just introduced another dependancy: we want the inventory to be hidden most of the time, so we need some CSS to do this:

.avatar > .inventory {
    display: none;
}

There. Now we can’t see the filler.

That was fun. Now let’s make the button toggle the visibility.

testClickEquipmentExpandsInventory : function() {
    YAHOO.util.UserAction.click(getNode("avatar-1", "equipment"));

    Assert.areEqual(
        'block',
        getNode("avatar-1", "inventory").style["display"]
    );
}

I spent almost an hour trying to figure out how to test whether the element was visible, and I have a feeling that even this is not quite airtight. (I will ask one of my HTML god friends about this later) Nevertheless, I get a red bar, so I am going to forge ahead!

Now to make my hard-earned test pass:

function StatusWidget() {
    /* stuff we've already seen before */

    var self = this;
    this.__getChild("equipment").onclick = function() {
        self.toggleInventoryDisplay();
    };
}

/* ... */
StatusWidget.prototype = {
    toggleInventoryDisplay : function() {
        var n = this.__getChild("inventory");
        if (n.style['display'] == 'block') {
            n.style['display'] = 'none';
        } else {
            n.style['display'] = 'block';
        }
    },

    /* stuff */
}

This test will consistently pass, but it suffers from a subtle, but very common problem that will wreck testing later. Identifying it is left as an exercise to the reader. (HINT: it has nothing to do with my terrible non-browser-compatible JS, or my pisspoor CSS. It is specifically a testability bug)

Tomorrow, I will fix it and (time permitting) populate the inventory list.

Source code

Uncategorized ,