A Programmer in King Arthur's Court

Occasional commentary about software, software construction, and the business of software.

Thursday, June 22, 2006

Code is hard to read.

In the beginning, code was hard to write, too, but we seem to have solved that difficulty with the invention of high-level languages(HLLs). Now, a developer need merely conjure up the right ideas and write them down in order that a computer might follow the plan and achieve the desired result. High-level languages, therefore, are a major accomplishment in the field.

Nowadays, we suffer from a glut of write-only code. I'm not just talking about perl here. Every computer programming language I can think of is dramatically easier to write in than it is to read.

Others have written extensively on this issue. An Extreme Programming principle says to trust only code; comments can lie but code can only ever tell the truth. There are books [Spinellis] and even college lectures about how to read code effectively. Joel Spolski compared it to reading Talmud. And who hasn't heard "Use the Source, Luke?"

The code reader seeks first to understand what the code writer understood at the time of writing, and second, to find what changes are necessary to solve the problem of the day. To a large extent, the rise in HLLs has helped. It's much easier to read C than assembler, and many times easier still to read Python or PHP.

Yet there is much to be desired. The epic struggle between the commenters and the anti-commenters shows that code doesn't convey the whole mind of the programmer. A decision, once made, does not communicate its reasoning.

I think that the next major improvements in programmer productivity will not come from making code easier to write. Rather, they will come from making code easier and more productive to read.

First steps in this direction include IDEs that highlight keywords. The brain can use color information to good advantage when processing what is, at root, a foreign and terse scripture. Folding editors also help some by collapsing subprograms from view, which helps a person see the larger structure of what he's working on. But these are baby steps. I'm done with crawling; I want to fly!

Let us start from a principle of programs which are easy to read. Let them be easy for anyone to read, not just the author. Then in that case, we must stop writing code per se and instead communicate concepts with a computer, where those concepts just happen to be about a planned computation.

It might be instructive to translate a computer program into a foreign language. I don't mean internationalizing the program. I mean writing out the ifs and thens and fors and nexts, the variable and function names, and everything, in Spanish or French or German. Your typical programming language borrows words from English, so perhaps a Mexican programmer might be more comfortable in Spanish. Why deny him of this convenience, and why deny yourself the utility of his company?

What would it take to let Mexican programmers work in Spanish while American programmers work in English? If we can solve that, then we can end the stupid arguments over whitespace and brace placement.

Saturday, June 17, 2006

Securities Fraud is a big problem on the internet these days. You've seen the e-mails that promise big gains in share prices over the next few days. Well, these are connected to scammers. The con game is to buy up some penny stock, then advertise it, and sell once the victims have also bought in and so inflated the price. Once the con artist sells his relatively large holdings, the price plummets again and the victims are left with much less capital than they started with. It's hard to detect at the market-wide level because dramatic price variation is common in penny stocks.

I'd like to see a way to prosecute these offenders for securities fraud, but I suspect that this particular game is perfectly legal. (I am not a lawyer.) In any case, might it be possible to develop a legal doctrine to fight this? Suppose I give out trading advice to the general public. Should I not then be legally required to be a licensed broker? And since I am not so licensed, should there not be some statute imposing penalties, such as requiring me give all my assets to the state?

It's presently illegal to practice law without a license. That has a specific definition: I can quote the law without penalty, but I may not give someone advice on a particular case. Trading is a little different matter. You're responsible for your own money, and if you trade unwisely, it's your fault. However, I still think that it's blatantly unethical to manipulate markets by spreading lies. The scam artist is not qualified to predict the price of a stock, but makes a purposely false representation that he is, and then profits from it. To my way of thinking, that is fraud. Whether the authorities agree, I don't know. At least one person has been charged with a related crime, in which he faked an internal memo about a company's poor financial situation, then sold the stock short and gained as the price dropped. However, I don't know what exactly they got him for. Al Capone was finally caught for tax evasion, after all.

If the authorities agree to define market-spamming as a crime against the state, then what would it take to catch such people or cut off their revenue streams? Do we even need legal intervention, or is there something that internet companies can do? Will a collection of technologies prove effective, or is there a social education movement that might dramatically diminish the potential returns from this scam?

Sunday, June 11, 2006

A stab at application event dispatch

Javascript in browsers, and more specifically the DOM, provide near-limitless means to build interactive and dynamic client-side software systems. People are scripting the DOM, invoking other services like XMLHTTPRequest, and making lots of pretty coolness happen on their web sites these days.

But there's a bit of a problem. We don't have any standard way to deal with event dispatch within the innards of an application.

Why should I care?

Because you can connect blobs of intelligent behaviour together with a reasonable event dispatch system, so that it's easier to factor out these behaviors into reusable components.

How to do it with as little cruft as possible:

We should isolate the idea of event dispatch from everything else about how events are used. That way, the system is as general as possible, without being too general.

A single event queue for a single type of event from a single source object is probably the simplest, most atomic unit of glue for this project. Here's some javascripty pseudo code:
function Q() {
this.q = []
this.lock = false
}
Q.prototype = {
add: function(fn) {
if (fn not in this.q) this.q.push(fn)
},
del: function(fn) {
# remove fn from this.q, if it's there.
},
dispatch: function(evt) {
if (this.lock) complain about an event broadcast cycle, else:
this.lock = true
for (k in this.q) this.q[k](evt)
this.lock = false
}
}
We can then write:
foo.onbar = new Q()
foo.onquux = new Q()
and later on:
foo.onquux.add(function() {alert('QUUX ALERT!')})
and eventually:
foo.onquux.dispatch()

I'm solving two problems in advance here.

First, many uses of event queues wish to send notification data along the path, so it's possible to include an argument to further describe the details, such as a pixel coordinate or whatever.

Second, it's almost certainly a bug if, while processing one event, another is dispatched along the same channel. Most times, this means that you've got an infinite loop. Other times, it might mean a logical flaw. In any case, the toolmaker doesn't know what to do here. The detection method is crude, but it should work in the single-threaded VM that browsers seem to have.

A fleshed out version of this code would help to separate concerns in development. One component can process the business logic, and rely on event dispatch to let a presentation layer control the various parts of the browser. Indeed, components written with this model can be stacked to any degree without too much programmer brainpower, which is the real point of such a system.

The main drawback is that this isn't completely consistent with DOM methods for adding event listeners to the base UI widgets. However, I don't think that's important. DOM nodes are only exposed to a small portion of the code in the presentation layer, and if you need the generality, you can write a wrapper class.

Thursday, June 08, 2006

Brass Bullets

Have you read "No Silver Bullet"? It's kind of long, but here's a super-quick summary:

Programming is difficult. There are two reasons: difficulty in expressing ideas to the computer, and difficulty determining what to express in the first place. High-level languages have taken most of the work out of expressing ideas (vs. machine code), so the remaining difficulty is almost entirely one of figuring out what exactly to program.

The idea of a "Silver Bullet" develops from the first paragraph of the paper, where Fred Brooks compares the problem of software complexity with werewolves, mythical monsters that only die when shot with silver bullets.

Software complexity is no joke, but it's also not mythical in proportion. It's just one reagent in a system of constraints. Frankly I think people are much more complex than software, but thousands of years of history has taught our society some good ways to manage that complexity which is known as human behavior. Thus, we don't think of it much.

Another constraint is the difficulty of expressing a concept in a format that the computer can process. Higher level languages make the biggest difference here, but libraries and environments also contribute their fair share to getting the job done.

The essential constraint which Fred Brooks so verbosely gets around to is deciding what to program in the first place. If you can solve that, then you have your silver bullet. There is no complete solution, but a sound design method can help quite a bit here. Brooks was sweet on top-down development, but a more current practitioner might vote for extreme programming.

But lo! We already have our silver bullets. I have just described them, but they go unnoticed and dismissed as mere brass bullets, destined for inadequacy in the larger scope.

Let us look forward from a vantage point in the past and trace history as it happened. Way back when programming meant writing machine code, it took some brilliance to even contemplate writing the program which writes programs which we now call a language compiler. Still, that made all the difference. Barring ubergeeks, programmers no longer thought about hardware, but instead of a mathematical model of computation. This made life much easier.

Fast forward to the weeks before structured programming was academically described. (Or think about using BASIC with line numbers.) There were conventions for how to do iteration or recursion on explicit or implicit stacks, and it was cool to be able to write a program to solve the Towers of Hanoi problem. Structured programming takes these conventions away from the programmer and places them instead in the hands of the computer and the compiler, such that the programmer no longer thinks of them. Instead, there are loops and functions and procedures and logical branches as fundamental elements of expression. Soon enough, rolling your own control structures with GOTO became outlawed. Again, we took a convention, which involved active thought to follow it, and we turned it into a computer program, which required no thought.

Now in larger systems, programmers naturally found themselves organizing modular structures that acted a lot like what we finally formalized in object oriented programming. That's probably why Simula never gained the popularity of C++ and Java. A critical mass of programmers had not developed a convention yet, so only the prophetically gifted could see the benefits of automating that portion of the code generation which we now call a class hierarchy. Bjarne picked the right time, place, and circumstances to play ubergeek, didn't try to blow up the universe, and instigated a sea change in software development.

Each time the common paradigm changes, programmers gain access to the resources needed to manage dramatically more complex systems than before, while carrying on only incrementally more thought processes. Code size goes down, and consequent productivity goes up.

When Ericsson, a telephone switching system vendor, found its software complexity system untennable, they did a lot of introspection and research. The result was the new programming system called "Erlang", which is a language and a runtime designed around a set of core ideas that fit well with the general problems that Ericsson had to solve, both technical and human.

Ericsson's first product to use this new programming system was delivered with a tenth of the effort and with something like no bugs. So as compared to working in C or C++ or whatever it was, this would constitute a silver bullet. Of course, it did take time and brilliance to develop the E language in the first place.

Obviously, Erlang isn't for everyone, but I think we can learn from their experience. Is your programming language forcing you to do more to express yourself than you should?

To get programming power, there's really only one route: minimize the number of things that a programmer has to think about to get a working system. There are many ways to approach that, but I think that this unified approach should guide the further advancement of our field.

IBM says that machines should work, and people should think. But if programming is thinking work, then the ideal programmer makes the machine do the thinking. In a future article, I'll explore some ways I've made the computer do the thinking.