Linux and the Unix Philosophy

2.2 Software engineering made easy

It has often been said that Unix offers the world's richest environment for programmers. One reason is that tasks that can be difficult, if not impossible, to accomplish on other operating systems are comparatively easy to accomplish under Unix. Could it be that small programs make such tasks easy? Absolutely.

2.2.1 Small programs are easy to understand

The "all-business" approach of small programs keeps fluff to a minimum, focusing instead on performing one function well. They contain only a few algorithms, most of which relate directly to the job involved.

Large programs, on the other hand, lean toward complexity and present barriers to understanding. The bigger a program becomes, the more it gets away from its author. The sheer number of code lines becomes overwhelming. For example, the programmer may forget which files the program's subroutines are found in or have trouble cross-referencing variables and remembering their usage. Debugging the code becomes a nightmarish task.

Some programs can be difficult to understand, whatever their size, simply because the nature of the function they perform is inherently obscure. Such programs are rare, however. Even programmers with moderate experience readily understand most small programs. This is a distinct advantage small programs have over their larger counterparts.

At this juncture, you may be wondering at what point a small program becomes a large program. The answer is, it depends. Large programs in one environment may be considered average for another. What is spaghetti code to one programmer may be daily pasta to the next. Here are some signs that suggest that your software may be departing from the Unix approach:

These warning signs are likely to ruffle the feathers of some programmers, namely those in the "big is better" camp. Not every program can be made small, they say. This world is a pretty big place, and there are some pretty big problems out there that we're trying to solve with some pretty big computers. These problems require that we write some pretty big programs.

That's a pretty big misconception.

There exists a kind of software engineer who takes pride in writing large programs that are impossible for anyone but himself to comprehend. He considers such work "job security." You might say that the only thing bigger than his ego is his last application program. Such software engineers are far too common in traditional software engineering environments.

The problem with this approach to job security is that the companies they work for inevitably realize that these engineers will eventually move on, leaving their companies holding the bag. The wiser companies take steps to prevent that. They hire individuals who understand that easily maintained software is more valuable.

No longer can the software designer say, "Heaven help the next guy." Good designers must go out of their way to make their software easy to maintain. They comment their code thoroughly—but not too thoroughly. They keep subroutines short. They pare the code down to what is absolutely necessary. This usually results in small programs that are easier to maintain.

2.2.2 Small programs are easy to maintain

Since a small program is usually easy to understand, it is likely to be easy to maintain as well, for understanding a program is the first step in maintaining it. No doubt you've heard this before, but many programmers ignore the subject of maintenance. They figure that if they took the time to write a program, then someone else will be just as willing to take the time to maintain it after them.

Most software engineers are not satisfied with maintaining other peoples' programs for a living. They believe—perhaps rightfully so—that the real money is made in writing new programs, not fixing past mistakes. Unfortunately, users don't see it quite the same way. They expect software to work the first time. If it doesn't, they get very upset with the program's vendor. Companies that fail to maintain their software do not remain in business for long.

Since maintaining software is not very glamorous work, programmers seek out ways to make the task easier or even avoid it altogether. Most cannot eliminate this duty entirely, however. If they're lucky, they probably could turn over maintenance chores to a junior individual. But more often than not, software support responsibilities usually fall upon the original author, who must settle for making the task more palatable any way he or she can. Small programs meet this need quite nicely.

2.2.3 Small programs consume fewer system resources

Because their executable images occupy very little memory, the operating system finds it much easier to allocate space for them. This greatly reduces the need for swapping and paging, often resulting in significant performance gains. A popular term in the Unix world is "lightweight" (i.e., small programs are often considered lightweight processes).

Large programs, with their huge binary images, extract a heavy price from the operating system when loaded. Paging and swapping commonly occur, causing performance to suffer. Operating system designers, aware of the resource requirements of large programs, attempt to deal with this issue by building enhancements such as dynamic loading and sharable runtime libraries. These address the symptom, not the problem.

A computer hardware engineer I met in the early days of my career often joked, "All programmers ever want is more core! All we need to stop your whining is to give you another memory board." He was partly right, of course. Give a programmer more memory, and the programs will run faster and take less time to write, greatly increasing productivity.

Reflect upon the "more core" cure for a moment. My hardware engineer friend unwittingly based his statements on the tendency of the programmers in his sphere to write large, complex programs. It's not surprising. The operating system we were using for applications development then was not Unix.

Had we been using Unix and embracing its small-program philosophy, the need for more memory would have been less evident. The joke would have been, "All programmers ever want is more MIPS!" (MIPS stands for millions of instructions per second, a popular though not necessarily accurate measure of CPU performance.)

Why has the metric of MIPS become such a hot issue in the computer world today? Because as Unix usage has become more prevalent, the use of small programs has proliferated as well. Small programs, although they usurp little system memory when executing, derive the most benefit from the injection of additional CPU horsepower. Load them into memory, and they do their job quickly, freeing up the memory for use by other small programs. Obviously, if the CPU capacity is lacking, then each program must spend a longer time in memory before the next small program can be loaded to do its job.

Systems employing small programs benefit from additional memory, too. Larger amounts of memory allow more small programs to remain in the kernel buffer cache longer, reducing reliance on secondary storage. Smaller programs can also be laid out in the buffer cache more easily. As we shall see later, the more small programs you can run at once, the higher the overall system performance. This forms the basis of a tenet of the Unix philosophy that we'll be discussing later.

2.2.4 Small programs can easily be combined with other tools

Anyone who has ever worked with large, complex programs knows this. Monolithic programs are worlds unto themselves. In trying to provide every feature that anyone could possibly want in a single program, they build barriers that hinder easy interfacing with other applications.

What about a large application that offers many conversions to other data formats? Isn't it really more valuable than a small program that allows only one data format? On the surface, that sounds like a plausible assumption. As long as the format needed happens to be one that the application already supports, you'll get along just fine. What happens when the application must interface with a data format that it wasn't equipped to handle?

Software developers generally write large programs under the mistaken notion that they have dealt with all contingencies (i.e., their program can interface with whatever data formats exist today). This can be a problem. Although the developers can deal with today's data formats, they have no idea what new formats may come along that would render their applications obsolete. Writers of large, complex programs operate under the egotistical assumption that the future is not only predictable, it's not going to differ much from today.

Authors of small programs, on the other hand, implicitly avoid foretelling the future. The only assumption they make about tomorrow is that it will be different from today. New interfaces appear. Data formats evolve. Styles of interaction rise or fall from public favor. New hardware renders old algorithms obsolete. Change is inevitable.

In summary, you enjoy distinct advantages by writing small programs instead of large ones. Their simplicity makes them easier to write, understand, and maintain. In addition, both people and machines find them more accommodating. Most importantly, you will equip your programs to deal with situations you couldn't possibly have anticipated when you wrote them.

Look to the future. It will be here sooner than you think.

Категории