Monday, December 27, 2010

The Right Tool for the Job

No professional plumber will think of using a wrench instead of a hammer (although quite a few amateurs wouldn't think twice before doing so).  In fact, professionals avoid adjustable wrenches, using the appropriate fixed wrench for each task.

Developers are much less picky about the tools they use.  Take, for example, the C programming language.  It was designed for the development of the Unix operating system, and is well suited for that task.  It allows low-level access to the computer's resources, it can be efficiently compiled into efficient code, and requires very little run-time support while not being tied to any specific hardware platform.  In essence, it is a high level, machine independent, assembly language.  Of course, these properties, extremely desirable for writing system code, required the language designers to make various choices that make C extremely unsuitable for most other programming tasks.  For example, the desire for efficiency and free access to all memory led to unconstrained array access, without any runtime bounds checking.  This has enabled the infamous buffer-overrun attacks, so favored by writers of viruses and other malware.  In turn, these require extra care by application developers who use C or C++ (which, unfortunately, preserved this and many other undesirable properties of C), and necessitated the development of various tools for checking C/C++ programs for these kinds of errors.

Why did this happen?  There are several reasons why programmers don't always use the right tool for the job.  One is the generality of our tools.  Usually, the same application can be written using any general-purpose language.  One may be particularly well-suited for the task, but, with more effort, others can be used.  Another reason is the steep learning curve associated with our tools.  It takes a lot of time to learn all the intricacies of a programming language (or other tool), and a programmer who mastered one will be reluctant to start from scratch with another language just to perform one task.  Obviously, the developers of the Unix kernel were masters of the C language (and influenced or even participated in its evolution).  It was natural for them to write all other parts of the system, including user applications, in the same language.  The great success of Unix and C created a large body of programmers whose hammer was C, and all applications their nail.  As a result, the first really popular object-oriented language, C++, was built as an extension to C, inheriting all the properties that make it unsuitable for user-application development.

It took a long time until a successor appeared, in the form of Java, which rejected many of the assumptions underlying C and C++, and removed many of its undesirable properties.  (Of course, we are still stuck with the awful syntax, which is responsible for a whole set of problems by itself.)  First and foremost, Java challenged the assumption that the language must be compilable into extremely efficient code; this is in fact wrong for most application development work.  Yes, inner loops in database management systems, communications, cryptography, and similar software must be heavily optimized.  But it is much more important for business (and desktop) applications to be free from security vulnerabilities than for them to be a little faster.  In addition, development expenses, which include developer time as well as the cost of tools that attempt to find security vulnerabilities and other problems, often outweigh the benefits of application speed.  Of course, loss of customer trust as a result of security breaches can be devastating.

We saw two reasons why developers don't always use the right tool for the job: the overlap between tools due to their generality, and the difficulty of learning a new one.  These have a corollary, resulting from the nature of organizations.  While it is good to have experts in various kinds of technologies and tools, it is important for a cohesive organization to have a common set of tools, a lingua franca that everybody is familiar with, for the main part of the development work.  This is important for good communications, and also makes integration easier.  But it also leads to the use of the least common denominator, the language and tools that can support most of the work, even if they are not the best for any single purpose.  Thus I find myself these days programming in Java, although it may not be my first choice for the kinds of systems I develop.

There are more reasons why developers don't use the best tool for the job, and many other tools worth discussing.  But these will have to wait for later posts.

P.S. See the excellent book, C Traps and Pitfalls, for a list of syntactic and semantic issues you must be aware of if you develop in C or a derivative language.

No comments:

Post a Comment