Friday, June 22, 2007

When you're smiling...

Greetings! They come in various flavours, depending on how well you know the person you're greeting and the time since the last greeting. I came across a funny one today.

In descending order of warmness, there's the hug, the informal "hi!" or "hey!", the slight nod of the head, and then there's the funny smile. It's not a real smile. The real smile is reserved for people you can't say hi to because they're on the phone or for people you're flirting with.

The funny smile is the kind of smile where you consciously try to move the corners of your mouth a little bit upwards while keeping the lips pressed together. The meaning is something like, "I see and acknowledge you but a real greeting is not warranted".

The funny thing about it is the way it looks. I haven't thought about it before, but someone sent me such a funny smile while I was on my bicycle to work. And you surely appear to be sucking your lips into your mouth, like the archetypal toothless old witch.

Think about that next time you funny-smile someone.

Saturday, June 2, 2007

Software design, part I

What makes a good software design?

I have been thinking about this for some time. The more I think about it, the simpler I come to think it is. Forget all the -tion, -ability, -ance words that are usually used to describe properties of good designs. In my mind a good design is one that is easy to understand.

As developers we think that ease of use/understanding is something that first and foremost applies to our users. We are used to horribly complicated IDEs, command lines that requires memorizing half a dictionary of cryptic commands, debuggers that speak assembler, etc. I argue that as a program grows from 50-100 lines of code to several thousands lines, the only thing that really matters is that you're not lost when you read and navigate it. And not whether you could squeeze a couple of lines out of it by some obscure technique you recently read about in a blog post.

Why? Because you need to understand the code in order to extend it, to fix bugs, to avoid introducing errors, to be able to estimate effects of changes, and in a sort of self-referential way, to still keep the design ease to understand.

In my mind, there are three goals with programming. In order of importance: to get the thing running the way it is intended to as fast as possible, to have as few bugs as possible, and to have as much fun as you can in the process. These are complementary - the faster you proceed, the more fun it usually is, at least if you are attracted to the creative dimension of programming. And the fewer bugs you have, the faster you can proceed. A non-existing defect that you don't have to try to reproduce, debug and then release a fix for is a real time-saver. Likewise, the more fun it is, the better you can concentrate and the faster you will go along.

Easy-to-understand code generally supports all three of these goals. If the code is difficult to understand, it will slow down the process immensely. And it will increase the risk of subtle bugs of the kind where the logic is faulty in corner cases. Even a clever compiler can't help with you out of those. Finally, it is simply more fun to work with code you understand.

How do you make a design easy to understand? I believe at the code level itself it is very much about using clear language and avoiding cryptic, non-descriptive names. Especially over time. If an identifier changes it meaning, even in a subtle way, so that its name is no longer descriptive, it's important to rename even if you have to change code all over the place.

At the design level it's on one hand about keeping things together that belong together and on the other hand about splitting up the code into smaller chunks so that the reader is not overwhelmed. Two opposing forces.

It's not that complicated really. To be able to understand something, it helps that the lines of code are sitting right next to each other. If you have to look them up in different places, you've lost your overview - and how do you know you found all the places unless the issue is easily greppable? But also, the piece of code needs to be small enough to fit in your brain, else you have to break it down yourself through analysis which is time-consuming and takes away the focus on what you really are trying to accomplish.

Keep things together that belong together. If you are designing a database application, don't put the logic that decides how the screen widgets should look like in the code that computes stuff from data received from the database. Likewise, don't put code that performs complicated computations in GUI code which is already busy with presenting an intuitive interface that prevents people from doing unnecessary damage to their data.

When you program, violations of this principle might be easy to see if you look at the dependencies. So the database code had to explicitly import a GUI module? Maybe it has more concerns than the database itself then. But sometimes violations are more difficult to spot. I think a main culprit here is the decision making.

Code is all about making decisions. In fact a computer program is at heart just a long series of decisions - first I'll do this, then I'll do that, then if this happens, I'll do this again. Most of these decisions are not important decisions, however, more like minor tweaks. It's not easy to see this in the code itself. One statement looks as good as the other, even though the first might decide what the user is going to look at and the other just adds a 2 pixel space around the border.

But what you usually want to do is to keep decisions about the same kind of things together. Then it's easy to understand. What fundamental things does the user see on screen? The answer should be along the lines of, take a look at this piece of code and you can see all of it. Not, well, grep for XYZ in these 40 source files. That's why lowly GUI code which is often preoccupied with tweaking spacing and interactive behaviour shouldn't be allowed to do much on its own, but immediately transfer control to somewhere else when anything less than trivial is to be done.

Since the programming language does not directly help with arranging the decision making in a sensible way, you should explicitly take it into account in the design, e.g. by forbidding certain parts of the code to do certain things or by designing modules that are explicitly made responsible for nothing more than high-level decision making. Or by arranging a calling structure that makes it easier to delegate decisions to upper management, e.g. by means of signals/callbacks/hooks/events/delegates.

Sometimes it means more hassle to follow this principle. But no pain, no gain. In most situations the long-term consequences of understandability are much more important than whether it takes an extra minute to code.

I have much more to say about this, but for now I'll conclude with this remark: When you start working on a new aspect of program, one that you haven't worked on before in another project so that you have a design already, it's easy to become irresolute, to get stuck on how to proceed in the best possible way. But if you simply design to keep things together that belong together while splitting the code into chunks that are small enough to be understood, it's probably going to be a healthy design and the details are less important. So just go ahead and see what happens.

Sunday, May 20, 2007

Human rights

I received the latest issue of Amnesty's Danish member magazine. A horrible and moving reading as usual. Hit by a cluestick: hey, there's a world around you!

The theme this time was Iraqi refugees. It didn't even go into much detail about the two million people who have left the country (two million people!), but instead explained how the Danish authorities are detaining the 519 who have come to Denmark in 2006. 47 of them have been let through and can restart their life.

The remaining are left in limbo. They have nothing to do, they are not allowed to get a job and do some meaningful work, their food is prepared to them so they can't choose what to eat, clothes and other personal stuff is only available at a local shop that operates by giving each refugee a number of points they are allowed to spend. According to one of them who has been living in the camp through her teenage years it's like living on a train station. Imagine growing up on a train station with nothing to do.

Meanwhile Sweden is letting 80% pass through. And Sweden didn't start the war.

The problem in Denmark appears to be the rule set. Imagine trying to codify compassion. It's a human trait, and an important one as well, maybe the one that makes us so successful compared to other species. But what is compassion anyway? How do you explain it in terms that a bureaucrat can understand and manage?

Apparently, the rule set the Danish authorities apply for accepting refugees requires that there is a personal element of prosecution. If your house has just collapsed from an American bomb and there are fightings in the street, is that personal? Maybe not. Do you have to move? Yes. And if you have the responsibility of taking care of others, if you have children, then you have a damn obligation to get away as fast as possible.

So the system is rotten. There are some hints for fixes in the magazine. The Danish association of doctors wants to examine the people living the in the camps. If they are getting provably ill in a medical sense, then they can declare the camps medically irresponsible.

Fixing the system itself is unfortunately not going to happen soon. That requires going to the politicians in charge - which in turns with the current aliens-generally-smell-rob-our-homes-and-rape-our-children political climate requires that the people starts changing it's collective mind. Appealing to the politicians themselves is not going to work.

So how do you change the mind of the people? I think the standard news stuff like "bomb in Iraq, 40 people killed" and then you see a smashed ruin covered with dust is part of the problem rather than of the solution because it gets people used to the sufferings. They start thinking, 40 persons killed, that's not so bad, it happened yesterday too.

I think we need more documentaries and even fictional movies about how it's like to having your house bombed and then come to Denmark and live at a train station with no freedom and lots of spare time for 5 years.

Oh, I almost forgot. The magazine also had an interview with Hans Blix, the former chief of the UN's weapons inspectors in Iraq. The US federal government wanted the war so badly that they even fabricated evidence (or let evidence be fabricated) about the famous non-existing weapons of mass destruction to convince people... Now two million Iraqi people have fled their homes and country.

Imagine being responsible for that. Of course the issue is more complex than that, but still. Two million people!

Monday, May 7, 2007

Algorithms

Just today I implemented bubble sort in Javascript to speed up the inner loop of a search algorithm. I think that's the first time I've actually implemented a sorting algorithm for real in spite of having read pages and pages about them. It's just one of the things that all real programming environments solved long before my time.

Of course, right after having implemented the bubble sort thing, I read on Wikipedia that it's actually considered inferior to insertion sort. So I then switched to insertion sort (I'm only sorting short sequences so asymptotic performance is irrelevant). It's my lucky day, two classic algorithms in such a short span of time...

The simple optimisation work did improve the running time by more than 400%, so that's cool.

When I think of algorithms I invariably come to think of the Knuth–Morris–Pratt algorithm, an algorithm for searching for occurrences of a search phrase in a larger text. A very famous string searching algorithm because it seems clever in theory and with toy examples. Your standard text book on algorithms probably does not mention this, but in practice it is not really an improvement over the simplest possible algorithm, because the issue it is trying to optimise, repeated examinations of the same character, almost never occurs when searching in natural language texts.

I found this out as an undergraduate when we were curious how KMP and the Boyer-Moore algorithm would stack up in practice. We discovered that KMP was only a 1% improvement in the number of characters compared, compared to the simple algorithm.

It's probably a great algorithm for searching DNA strings, though.

I added a note to the Wikipedia page. If I should die tomorrow, please consider it my contribution to the field of computer science.

Update

Long time, no post. I finished reading Naked Economics, it didn't take me more than a week. I still highly recommend it. It did have lots of interesting points on globalisation.

One is the notion of human capital. From a macro-economic point of view, one of the best thing a country can do is to invest in its people - education, health-care and the like. The return of investment as measured in cold cash is worth it.

One example of this is the fact that countries that are rich in natural resources don't fare particularly well in the long run - because they haven't had to invest in human capital. Another example is a research facility of well-educated engineers and scientists that has to close down. A local disaster in the short run, but the engineers and scientists are highly motivated individuals that soon find something else to do. If the facility is not simply bought by a large corporation that has no other interest in the facility than its human capital.

Another point concerns one of the dark sides of capitalism. Creative destruction - those who cannot compete cannot survive. Instead of fighting this built-in ground rule, the author suggests that the transition period be made less severe by retraining the involved workers and support from the authorities. Focusing on the future instead of the past.

From the point of view of the Far East sweatshops, the author notes that the people working in these shops would not be there if it weren't for the fact that they are better than the alternatives. I think that's simplifying things (*ahem*, did anyone mention the word "exploitation"?), but nevertheless an interesting point to ponder.

In other news, I upgraded to the new Ubuntu version at work. More incremental improvements, as always.