Topic : A Critique of C++
Author : Ian Joyner
Page : << Previous 2  Next >>
Go to page :


   It is a misconception that consistency checks are 'training wheels'
for student programmers, and that 'syntax' errors are a hindrance to
professional programmers.  Languages that exploit techniques of schema
checking are often criticised as being restrictive and therefore
unusable for real world software.  This is nonsense and misunderstands
of the power of these languages.  It is an immature conception; the best
programmers realise that programming is difficult.  As a whole, the
computing profession is still learning to program.

   Another example of consistency checking comes from the user interface
world.  Instead of correcting a user after an erroneous action, a good
user interface will not offer the action as a possibility in the first
place.  It is cheaper to avoid error than to fix it.  Most people drive
their cars with this principle in mind.  Smash repair is time consuming
and expensive.

   Program development is a dynamic process.  A program description is
constantly modified during development.  Modifications often lead to
inconsistencies and error.  Languages and compilers that provide
consistency checks help prevent such 'bugs', which can creep into a
previously working system.  These checks help verify that as a program
is modified, previous decisions and work are not invalidated.

   It is interesting to consider how much checking could be integrated
in an editor.  The focus of many current generation editors is text.
What happens if we change this focus from text to program components?
Such editors might check not only syntax, but semantics.  Alerting
programmers of potential errors earlier and interactively will shorten
development times.  Future languages should be defined very cleanly in
order to enable such editor technology.

   A programming language should provide a formal notation.  During
requirements analysis and design phases, formal and semi-formal
notations are required.  Notations used in analysis, design, and
implementation phases should be complementary, rather than
contradictory.  Currently, analysis, design and modelling notations are
too far removed from programming, while programming languages are in
general too low level.  Both designers and programmers must compromise
to fill the gap.  Current notations provide difficult transition paths
between stages.  This 'semantic gap' contributes to errors and omissions
between the requirements, design and implementation phases.  Future
programming languages will be an implementation extension of the high
level notations used for requirements analysis and design.  This will
lead to improved consistency between analysis, design and
implementation.  Object-oriented techniques emphasise the importance of
this, as abstract definition and concrete implementation can be
separate, yet provided by the same syntax.

   Programming languages also provide notations to formally document a
system.  Program source is the only reliable documentation of a system,
so a language should explicitly support documentation.  As with all
language, the effectiveness of communication is dependent upon the skill
of the writer.  Good program writers require languages that support the
role of documentation.  They require that the syntax of a language is
perspicuous, and easy to learn.  Those not trained in the skill of
'writing' programs, can read them to gain understanding of the system.
After all, it is not necessary for newspaper readers to be journalists.

   Chris Reade [Reade 89] gives the following explanation of programming
and languages. "One, rather narrow, view is that a program
is a sequence of instructions for a machine. We hope to show that
there is much to be gained from taking the much broader view that
programs are descriptions of values, properties, methods, problems
and solutions. The role of the machine is to speed up the manipulation
of these descriptions to provide solutions to particular problems.
A programming language is a convention for writing descriptions
which can be evaluated."

   [Reade 89] also describes programming as being a "Separation of
concerns".  He says:

   "The programmer is having to do several things at the same time,

   (1)    describe what is to be computed;
   (2)    organise the computation sequencing into small steps;
   (3)    organise memory management during the computation."

   Reade continues, "Ideally, the programmer should be able to
concentrate on the first of the three tasks (describing what is to be
computed) without being distracted by the other two, more
administrative, tasks.  Clearly, administration is important but by
separating it from the main task we are likely to get more reliable
results and we can ease the programming problem by automating much of
the administration.

   "The separation of concerns has other advantages as well.  For
example, program proving becomes much more feasible when details of
sequencing and memory management are absent from the program.
Furthermore, descriptions of what is to be computed should be free of
such detailed step-by-step descriptions of how to do it if they are to
be evaluated with different machine architectures.  Sequences of small
changes to a data object held in a store may be an inappropriate
description of how to compute something when a highly parallel machine
is being used with thousands of processors distributed throughout the
machine and local rather than global storage facilities.

   "Automating the administrative aspects means that the language
implementor has to deal with them, but he/she has far more opportunity
to make use of very different computation mechanisms with different
machine architectures."

   These quotes from Reade are a good summary of the principles from
which I criticise C++.  What Reade calls administrative tasks, I call
bookkeeping.  C and C++ are often criticised for being cryptic.  The
reason is that C concentrates on points 2 and 3, while the description
of what is to be computed is obscured.  High level languages describe
'what' is to be computed.  This is the problem domain.  'How' a
computation is achieved is in the low-level machine- oriented domain.
The conflict between these aspects recurs frequently throughout this
critique.  Automating the bookkeeping tasks enhances correctness,
compatibility, portability and efficiency.  Bookkeeping tasks arise from
having to specify 'how' a computation is done.  Specifying 'how' things
are done in some environments hinders portability to other platforms.

   The industry should be moving towards these ideals.  They will help
in the economic production of software, rather than the costly
techniques of today.  We should consider what we need, and assess the
problems of what we have against that.  Object-orientation provides one
solution to these problems.  Its effectiveness, however, depends on the
quality of its implementation.

   It is relevant to ask if grafting OO concepts onto a conventional
language realises the full benefits of OO? Perhaps a biblical quote can
be considered: "No one sews a patch of unshrunk cloth on to an old
garment; if he does, the patch tears away from it, the new from the old,
and leaves a bigger hole.  No one puts new wine into old wineskins; if
he does, the wine will burst the skins, and then wine and skins are both
lost.  New wine goes into fresh skins." Mark 2:22

   We must abandon disorganised and error-prone practices, not adapt
them to new contexts.  How well can hybrid languages support the
sophisticated requirements of modern software production? Surely a basic
premise of object-oriented programming is to enable the development of
sophisticated systems through the adoption of the simplest techniques
possible? Software development technologies and methodologies should not
impede the production of such sophisticated systems.

2.1.  Safety and Courtesy Concerns

   This critique makes two general types of criticism, about 'safety'
concerns and 'courtesy' concerns.  These themes recur throughout this
critique, as C and C++ have flaws that compromise them frequently.
Safety concerns affect the external perception of the quality of the
program.  Failure to meet safety concerns results in unfulfilled
requirements and program crashes.

   Courtesy concerns affect the internal  view of the quality of a
program in the development and maintenance process. Courtesy concerns
are usually stylistic and syntactic, whereas safety concerns
are semantic. The two often go together. It is courtesy for an airline
to keep its fleet well maintained. This courtesy concern is
also very much a safety concern.

   Courtesy issues are even more important in the context of reusable
software.  Reusability depends on the clear communication of the purpose
of a module.  Courtesy is important to establish social interactions,
such as communication.  Courtesy implies inconvenience to the provider,
but provides convenience to others.  Courtesy issues include choosing
meaningful identifiers, consistent layout and typography, meaningful and
non-redundant commentary, etc.  Courtesy issues are more than just a
style consideration.  A language design should directly support courtesy
issues.  A language, however, cannot enforce courtesy issues, and it is
often pointed out that poor, discourteous programs can be written in any
language.  But this is no reason for being careless about the languages
that we develop and choose for software development.

3.  C++ Specific Criticisms

3.1.  Virtual Functions

   Polymorphism is a key concept of OOP.  Virtual functions are one way
to implement polymorphism.  A language designer's choice is whether this
should be specified in the parent or the inheriting class.  Is

Page : << Previous 2  Next >>