|Level of Abstraction|
The level of abstraction that a programming language provides is all about tradeoffs. Lower level languages (I'll inaccurately call them 3GL's) supply a few small operations which can be combined with great flexibility to accomplish almost anything. The cost, of course, is in the time-consuming detail in which each and every bit of code must be cast. Conversely, high level languages (loosely, 4GL's) and application generators include meta-operations which provide much more functionality for a given amount of code. Once again, there is a cost. Here the big penalty is a loss of flexibility -- which is proportional to the size of the functional units. There are a prohibitively large number of ways in which a few small operations can be combined to create large ones. Therefore, only the most common of these large functions can be reasonably implemented in a high level language before the point of diminishing returns is reached. As the language integrates more large functions into its syntax, its complexity eventually reaches a point where a high level of skill is required to use it effectively.
The original distinction between 3GL and 4GL languages has long been blurred by the availability of prepackaged libraries. For example, there are a wide variety of special-purpose function and class libraries on the market for C and C++. These tools lets experienced programmers use their general-purpose language skills while adding only the specialized components needed to complete an application. The details of using the library follow the patterns that they already know, leaving them to learn only the minimum necessary to write their specialized program.
Meanwhile, programming with some application generators no longer resembles traditional coding -- but the same type of decisions are being made and the same kind of work is being done. The units of functionality are larger, of course, and the methods of manipulating the chunks of logic are usually different as well. Only if the generator is a good match for the application, however, will the potential productivity advantage of this approach be fully achieved. In selecting such a tool, the same tradeoffs that apply to the choice of 4GL's versus 3GL's must be considered. Application generators don't represent a fundamental change in the nature of programming but rather just another point in the continuum of low and high-level programming.
To blur the distinction further, the ability of some 4GL's to generate 3GL intermediate code would seem to give the developer the best of both worlds. It retains the productivity of high-level programming and provides access to the machine efficiency and low-level flexibility of a 3GL -- just as the libraries for 3GL's seem to do. While this approach should result in an environment that is as flexible as the 3GL alone, it comes with a tradeoff. To exercise the flexibility of the 3GL it becomes necessary to program in two languages, which increases maintenance costs and training requirements.
The Right Tool for the Job Versus Expertise
Further complicating the issue is the matter of expertise. A very specialized language may be the most productive for a particular application. However, experts in a more generalized language might complete the application on schedule more predictably than would neophytes with a special-purpose language. Of course, the practitioners of the general-purpose language get more opportunities to hone their skills.
Because of this effect, choosing the best language for each particular application might not always be the optimum overall strategy.
[The author codes in C and PHP and no longer uses COBOL, Atari BASIC, Visual BASIC, FORTRAN, ALGOL, Natural, RPG, or IBM 370 Assembly.]