Monday, November 28, 2011

The loss of WYSIWYG in programming languages

As programming languages have evolved, we have moved from static languages to dynamic languages. These new languages offer new capabilities, but at a price. That price includes performance (perhaps not a great cost, given advances in hardware) but also the ease of understanding code.

Early programming languages of FORTRAN and COBOL were quite easy to understand. They did not allow for recursion (the early versions, at least), and offered static, up-front at compile/link time memory layout. You knew (or the linker knew) the location of every variable and every subroutine when the program was built. You knew the destination of every jump and the meaning of every statement. (Yes, COBOL had the 'ALTER' keyword, and FORTRAN had the "assigned goto", but they were proscribed in civilized shops.)

Of all languages, BASIC (prior to Visual Basic) was probably the most easily understood. It had a specific set of keywords, no pre-processor, strongly-typed variables, and no dynamic aspects.

The C language was one of the last languages in which "what you saw was what you got". A colleague referred to his "cortex compiler" when discussing the clarity of C code. One could look at source code and know the actions performed by the computer. (I am ignoring the effects of the pre-processor here. Poorly-design -- or even well-designed -- #define macros can change the normal meaning of C code and stymie all but the most careful analysis.)

Things changed with object-oriented languages. In object-oriented languages, one can look at the source code, but the action taken by the computer is not always obvious. To understand polymorphic code one must understand the inheritance hierarchy. To understand operators one must understand the class and its ancestors. Multiple inheritance (multiple implementation inheritance, as in C++) is rife with ambiguity.

(I'm ignoring LISP in this sequence. LISP, which dates back to the days of FORTRAN and COBOL, offered the same flexibility and dynamic constructs that it does today. But most programmers ignored it then, too.)

Java kept object-oriented programming but mercifully implemented multiple interface inheritance (and not multiple implementation inheritance) and eliminated the pre-processor and operator overloading, all which made it more obvious than C++.

Dynamic languages are now in the ascendant. Perl allows for lots of un-obvious constructs (some will snarkily comment that the entire language is un-obvious). Ruby lets one define or modify classes -- even the "standard" classes -- during run-time. (The shades of COBOL's 'ALTER' haunt us still.)

The trend may be towards dynamic languages, but not everything is moving in that direction. The up-and-coming functional programming languages (Haskell, Erlang) take a different approach and enforce strict definitions of functions and their results. Their syntax and organization is different from object-oriented programs, and can be difficult for those trained in O-O programming constructs. Despite the differences, I expect that these languages will, in the long run, be considered the more "obvious".

And we may, once again, have programs that are obviously understood, capable of being processed by our "cortex compilers".

No comments:

Post a Comment