Thursday, April 7, 2011

Yeah, but we can build things that barely stand up!

In college I remember taking a class at UC Davis in which the professor started a lecture one day saying that, "anyone can build a house. Throw enough materials at it, and it will be a suitable home."

Then, with a smile on his face he added, "but engineers can build a house that barely stands up." He said it as if he was proclaiming the cure for world hunger. Someone in the class murmured, "We can probably do better than that..."

That comment, plus a number of quizzacle looks on students' faces prompted him to explain, "We know how to build a strong house with the minimum amount of materials. Anyone can build a house, but usually it will contain a lot of wasted resources or won't be as strong."

That class was a general Engineering course. How does this apply to software engineering? Thinking back further, I remember reading something from Steve Gibson, whom created SpinRite and other apps, claiming that the efficiency of software had become a lost art, and that a program written to accomplish a fairly simple task now consumes a large amount of disk space, RAM, and processing power when it could have been accomplished within a few hundred kilobytes and under 100 megahertz.

Well okay, that's not an exact quote, what he was getting at is that we've thrown a lot of resources at a problem when the solution could be quite simple. Many programs written in Java are built to be interpreted and compiled on-the-fly, increasing application portability at the expense of size and processing power. Software contains interfaces and procedures for crunching data from other programs that the user may never use, and that would only be activated with the right complimenting technology. In the mean time, it consumes disk space and memory. Visual software development tools make it easy to develop a computer program, though the computer's interpretation of what was intended is sometimes ambiguous and opens security holes.

Entire libraries now have to be shipped with a product even when a few of those functions are used by the program. That's probably not such a big deal -- it's akin to leaving branches on the tree logs used to build your log cabin. A little unsightly, but it's not doing any harm, and there's nothing wrong with the part of the tree that's being used, right? Wrong - if some of the unused libraries are insecure and leverage the parts of the library in use, it would be like putting termites into those branches. Eventually they could reach the core of the house.

This is getting abstract, so let's come back to a real life example of software engineering sloppiness: A few years ago, Magellan sent out an update for its GPS devices that required the user to enter an activation code based on the serial number. The installer interpreted the serial number string as a number. The activation code generator interpreted the serial number as a text field. That wouldn't matter except that since the integer variables didn't bother to store the number of leading 0's in the serial number field, the activation code came out differently depending on whether the leading 0's were read or not.

Here's a security example: Stuxnet used a number of small holes and hooks to get where it needed to go. (http://www.isssource.com/tag/how-stuxnet-spread/) That included USB drives, print spooler services, autorun.inf, Siemens project files, and finally programmable logic controllers.

Put this way, it looks like as we make it easier to build software, we're all following the "anyone can do it" methodology. Software engineering becomes cheap. So going back to the beginning of this article, where's the engineering element of building it right? How do we build strong software with minimal resources? Should we all go back to building software with assembly?