Ada 95 Quality and Style Guide Chapter 1
Style is an often overlooked but very critical attribute of writing.
The style of writing directly impacts the readability and understandability
of the end product. The style of programming, as the writing of
source code in a computer language, also suffers from this neglect.
Programs need to be readable and understandable by humans, not
just comparable by machines. This requirement is important in
the creation of quality products that not only meet user needs
but also can be developed on schedule and within estimated cost.
This book is intended to help the computer professional produce
better Ada programs. It presents a set of specific stylistic guidelines
for using the powerful features of Ada 95 (Ada Reference Manual
1995) in a disciplined manner.
Each guideline consists of a concise statement of the principles
that should be followed and a rationale for following the
guideline. In most cases, an example of the use of the
guideline is provided, and, in some cases, a further example is
included to show the consequences of violating the guideline.
Possible exceptions to the application of the guideline
are explicitly noted, and further explanatory notes are
provided, where appropriate. In some cases, an instantiation
is provided to show more specific guidance that could be enforced
as a standard. In selected cases, automation notes discuss
how one could automate enforcement of the guideline.
Ada was designed to support the development of high-quality, reliable,
reusable, and portable software. For a number of reasons, no programming
language can ensure the achievement of these desirable objectives
on its own. For example, programming must be embedded in a disciplined
development process that addresses requirements analysis, design,
implementation, verification, validation, and maintenance in an
organized way. The use of the language must conform to good programming
practices based on well-established software engineering principles.
This book is intended to help bridge the gap between these principles
and the actual practice of programming in Ada.
Many of the guidelines in this book are designed to promote clear
source text. The goal of these guidelines is to improve the ease
of program evolution, adaptation, and maintenance. Understandable
source text is more likely to be correct and reliable. Easy adaptation
requires a thorough understanding of the software; this is considerably
facilitated by clarity. Effective code adaptation is a prerequisite
to code reuse, a technique that has the potential for drastic
reductions in system development cost. Finally, because maintenance
(really evolution) is a costly process that continues throughout
the life of a system, clarity plays a major role in keeping maintenance
costs down. Over the entire life cycle, code has to be read and
understood far more often than it is written; thus, the investment
in writing readable, understandable code is worthwhile.
The remaining sections of this introduction discuss the organization
of this book and how the material presented can be used by people
in different roles, including new Ada programmers, experienced
Ada programmers, object-oriented programmers, software project
managers, contracting agencies, standards setting organizations,
and planners of the transition to Ada 95 from existing Ada 83
(Ada Reference Manual 1983) programs.
The format of this book follows the well-received guideline format
of the Ada Quality and Style: Guidelines for Professional Programmers,
version 02.01.01 (AQ&S 83) (Software Productivity Consortium
1992). The style guide is divided into sections that map to the
major decisions that each programmer must make when creating high-quality,
reliable, reusable, and portable Ada software. Some overlap exists
in the sections because not all programming decisions can be made
independently.
Individual chapters address source code presentation, readability,
program structure, programming practices, concurrency, portability,
reusability, and performance, and a new chapter addresses object-oriented
features. Each chapter ends with a summary of the guidelines
it contains. The last chapter shows a complete implementation
of the Dining Philosophers example, provided by Dr. Michael B.
Feldman and Mr. Bjorn Kallberg. Many of the guidelines in this
book were used to create this example. An appendix provides a
cross-reference matrix between the Ada Reference Manual (1995)
sections and the guidelines in this style guide.
This book is written using the general software engineering vocabulary
developed over the last 20 years. Software engineering is a rapidly
evolving discipline with relatively new concepts and terminology.
However, to establish a common frame of reference, needed definitions
are extracted from the Ada Reference Manual (1995) and Rationale
(1995).
Throughout the book, references are made to other sources of information
about Ada style and other Ada issues. The references are listed
at the end of the book. A bibliography is also provided.
In this book, the term "Ada" refers to the latest Ada
standard, released in February 1995 (sometimes also known as Ada
95). References to the earlier Ada standard are clearly denoted
as "Ada 83."
1.1.1 Source Code Presentation and Readability
Chapters 2 and 3 directly address the issues of creating clear,
readable, and understandable source text. Chapter 2 focuses on
code formatting, and Chapter 3 addresses issues of use of comments,
naming conventions, and types.
There are two main aspects of code clarity: (1) careful and consistent
layout of the source text on the page or the screen, covered
by Chapter 2, that can enhance readability dramatically; (2) careful
attention to the structure of code, covered by Chapter
3, that can make the code easier to understand. This is true both
on the small scale (e.g., by careful choice of identifier names
or by disciplined use of loops) and on the large scale (e.g.,
by proper use of packages). These guidelines treat both layout
and structure.
Code formatting and naming convention preferences tend to be very
personal. You must balance your personal likes and dislikes with
those of other engineers on the project so that you can agree
to a consistent set of conventions that the whole project team
will follow. Automatic code formatters can help in enforcing this
kind of consistency.
1.1.2 Program Structure
Chapter 4 addresses overall program structure. Proper structure
improves program clarity. This is analogous to readability on
lower levels and includes issues of high-level structure, in particular
the use of packages and child packages, visibility, and exceptions.
The majority of the guidelines in this chapter are concerned with
the application of sound software engineering principles, such
as information hiding, abstraction, encapsulation, and separation
of concerns.
1.1.3 Programming Practices
Chapter 5 presents guidelines that define consistent and logical
language feature usage. These guidelines address optional parts
of the syntax, types, data structures, expressions, statements,
visibility, exceptions, and erroneous execution.
1.1.4 Concurrency
Chapter 6 defines the correct use of concurrency to develop predictable,
reliable, reusable, and portable software. The topics include
tasking, protected units, communication, and termination. One
major area of enhancement of the Ada language has been better
support for shared data. The task mechanism had been the only
available approach to protecting shared data. The guidelines in
this chapter support the use of protected types to encapsulate
and synchronize access to shared data.
1.1.5 Portability and Reusability
Chapters 7 and 8 address issues of designing for change from slightly
different perspectives. Chapter 7 addresses the fundamentals of
portability, the ease of changing software from one computer system
or environment to another, and the impact of specific feature
usage on portability. Chapter 8 addresses code reusability, the
extent to which code can be used in different applications with
minimal change.
The portability guidelines discussed in Chapter 7 need careful
attention. Adherence to them is important even if the need to
port the resulting software is not currently foreseen. Following
the guidelines improves the potential reusability of the resulting
code in projects that use different Ada implementations. You should
insist that when particular project needs force the relaxation
of some of the portability guidelines, nonportable features of
the source text are prominently indicated.
The reusability guidelines given in Chapter 8 are based on the
principles of encapsulation and design for change. These guidelines
stress that understanding and clarity, robustness, adaptability,
and independence are useful and desirable, even when reuse is
not expected, because the resulting code is more resistant to
both planned and unplanned change.
1.1.6 Object-Oriented Features
Chapter 9 defines a set of guidelines in common objected-oriented
terms that exploit some of the features of Ada 95 that are not
in Ada 83. The guidelines discuss the use of the new Ada features
of type extension (tagged types), abstract tagged types, and abstract
subprograms to implement single inheritance, multiple inheritance,
and polymorphism.
1.1.7 Performance
Chapter 10 defines a set of guidelines intended to enhance performance.
It is recognized that some approaches to performance are at odds
with maintainability and portability. Most of the guidelines in
this chapter read ". . . when measured performance indicates."
"Indicates" means that you have determined that the
benefit in increased performance to your application in your environment
outweighs the negative side effects on understandability, maintainability,
and portability of the resulting code.
This book is intended for those involved in the actual development
of software systems written in Ada. The following sections discuss
how to make the most effective use of the material presented.
Readers with different levels of Ada experience or different roles
in a software project will need to use the book in different ways.
There are a number of ways in which this book can be used: as
a guide to good Ada style; as a comprehensive list of guidelines
that will contribute to better Ada programs; or as a reference
work to consult for usage examples of and design-tradeoff discussion
on specific features of the language. The book contains many guidelines,
some of which are quite complex. Learning them all at the same
time should not be necessary; it is unlikely that you will be
using all the features of the language at once. However, it is
recommended that all programmers (and, where possible, other Ada
project staff) make an effort to read and understand Chapters
2, 3, 4, and Chapter 5 up to Section 5.7. Some of the material
is quite difficult (e.g., Section 4.2, which discusses visibility),
but it covers issues that are fundamental to the effective use
of Ada and is important for any software professional involved
in building Ada systems.
This book is not intended as an introductory text on Ada or as
a complete manual of the Ada language. It is assumed that you
already know the syntax of Ada and have a rudimentary understanding
of the semantics. With such a background, you should find the
guidelines useful, informative, and often enlightening.
If you are learning Ada, you should equip yourself with a comprehensive
introduction to the language. Two good introductory texts on Ada
83 are Barnes (1989) and Cohen (1986). Both authors have published
new books that cover Ada 95 (Barnes 1996, Cohen 1996). Once you
become familiar with these texts, you are encouraged to use them
in conjunction with Rationale (1995). The Ada Reference Manual
(1995) should be regarded as a companion to these books. The majority
of guidelines reference the sections of the Ada Reference Manual
(1995) that define the language features being discussed. Appendix
A cross references sections of the Ada Language Reference Manual
to the guidelines.
At first sight, Ada offers a bewildering variety of features.
It is a powerful tool intended to solve difficult problems, and
almost every feature has a legitimate application in some context.
This makes it especially important to use Ada's features in a
disciplined and organized way. Following the guidelines can make
learning Ada easier and help you to master its apparent complexity.
From the beginning, you can write programs that exploit the best
features of the language in the way that the designers intended.
Programmers experienced in using other programming languages are
often tempted to use Ada as if it were their familiar language
but with irritating syntactic differences. This pitfall should
be avoided at all costs; it can lead to convoluted code that subverts
exactly those aspects of Ada that make it so suitable for building
high-quality systems. You must learn to "think Ada."
Following the guidelines in this book and reading the examples
of their use will help you to do this as quickly and painlessly
as possible.
To some degree, novice programmers learning Ada have an advantage.
Following the guidelines from the beginning helps in developing
a clear programming style that effectively exploits the language.
If you are in this category, it is recommended that you adopt
the guidelines for those exercises you perform as part of learning
Ada. Initially, developing sound programming habits by concentrating
on the guidelines themselves and their supporting examples is
more important than understanding the rationale for each guideline.
The rationale for many of the guidelines helps experienced programmers
understand and accept the suggestions presented in the guideline.
Some of the guidelines themselves are also written for the experienced
programmer who must make engineering tradeoffs. This is especially
true in the areas of portability, reusability, and performance.
These more difficult guidelines and rationale will make you aware
of the issues affecting each programming decision. You can then
use that awareness to recognize the engineering tradeoffs that
you will eventually be asked to make when you are the experienced
Ada programmer.
As an experienced Ada programmer, you are already writing code
that conforms to many of the guidelines in this book. In some
areas, however, you may have adopted a personal programming style
that differs from that presented here, and you might be reluctant
to change. Carefully review those guidelines that are inconsistent
with your current style, make sure that you understand their rationale,
and consider adopting them. The overall set of guidelines in this
book embodies a consistent approach to producing high-quality
programs that would be weakened by too many exceptions.
Consistency is another important reason for general adoption of
common guidelines. If all the staff of a project write source
text in the same style, many critical project activities are easier.
Consistent code simplifies formal and informal code reviews, system
integration, code reuse within a project, and the provision and
application of supporting tools. In practice, corporate or project
standards may require deviations from the guidelines to be explicitly
commented, so adopting a nonstandard approach may require extra
work.
Some of the guidelines in this book, particularly in the chapters
on concurrency, portability, reusability,
As an experienced object-oriented programmer, you will appreciate
the effort that has gone into elegantly extending the Ada language
to include powerful object-oriented features. These new features
are integrated tightly with the existing language features and
vocabulary. This book is intentionally written to provide a view
from the perspective of style; therefore, Ada object-oriented
features are used throughout the book. Disciplined use of these
features will promote programs that are easier to read and modify.
These features also give you flexibility in building reusable
components. Chapter 9 addresses object-oriented programming and
the issues of inheritance and polymorphism. Earlier chapters cross
reference the Chapter 9 guidelines.
You will find it easier to take advantage of many of the concepts
in Chapter 9 if you have done an object-oriented design. The results
of an object-oriented design would include a set of meaningful
abstractions and hierarchy of classes. The abstractions need to
include the definition of the design objects, including structure
and state, the operations on the objects, and the intended encapsulation
for each object. The details on designing these abstractions and
the hierarchy of classes are beyond the scope of this book. A
number of good sources exist for this detail, including Rumbaugh
et al. (1991), Jacobson et al. (1992), the ADARTS Guidebook
(Software Productivity Consortium 1993), and Booch (1994).
Technical management plays a key role in ensuring that the software
produced in the course of a project is correct, reliable, maintainable,
and portable. Management must create a project-wide commitment
to the production of high-quality code; define project-specific
coding standards and guidelines; foster an understanding of why
uniform adherence to the chosen coding standards is critical to
product quality; and establish policies and procedures to check
and enforce that adherence. The guidelines contained in this book
can aid such an effort.
An important activity for managers is the definition of coding
standards for a project or organization. These guidelines do not,
in themselves, constitute a complete set of standards; however,
they can serve as a basis for standards. Several guidelines indicate
a range of decisions, but they do not prescribe a particular decision.
For example, the second guideline in the book (Guideline 2.1.2)
advocates using a consistent number of spaces for indentation
and indicates in the rationale that two to four spaces would be
reasonable. With your senior technical staff, you should review
each such guideline and arrive at a decision about its instantiation
that will constitute your project or organizational standard.
Two other areas require managerial decisions about standardization.
Guideline 3.1.4 advises you to avoid arbitrary abbreviations in
object or unit names. You should prepare a glossary of acceptable
abbreviations for a project that allows the use of shorter versions
of application-specific terms (e.g., FFT for Fast Fourier Transform
or SPN for Stochastic Petri Net). You should keep this glossary
short and restrict it to terms that need to be used frequently
as part of names. Having to refer continually to an extensive
glossary to understand source text makes it hard to read.
The portability guidelines given in Chapter 7 need careful attention.
Adherence to them is important even if the need to port the resulting
software is not currently foreseen. Following the guidelines improves
the potential reusability of the resulting code in projects that
use different Ada implementations. You should insist that when
particular project needs force the relaxation of some of the portability
guidelines, nonportable features of the source text are prominently
indicated. Observing the Chapter 7 guidelines requires definition
and standardization of project- or organization-specific numeric
types to be used in place of the (potentially nonportable) predefined
numeric types.
Your decisions on standardization issues should be incorporated
in a project or organization coding standards document. With coding
standards in place, you need to ensure adherence to them. Gaining
the wholehearted commitment of your programming staff to use the
standards is critical. Given this commitment and the example of
high-quality Ada being produced by your programmers, it will be
far easier to conduct effective formal code reviews that check
compliance to project standards.
Some general issues concerning the management of Ada projects
are discussed by Hefley, et al. (1992).
Many of the guidelines presented here are specific enough to be
adopted as corporate or project programming standards. Others
require a managerial decision on a particular instantiation before
they can be used as standards. In such cases, a sample instantiation
is presented and used throughout the examples. Such instantiations
should be recognized as weaker recommendations than the guidelines
themselves. In some cases, where the examples are extracted from
a published work, the author's style is used unchanged.
Other guidelines presented in this book are intentionally phrased
in terms of design choices to consider. These guidelines cannot
be instantiated as hard-and-fast rules that a project must follow.
For example, you should not interpret Guidelines 6.1.1 and 6.1.2
to mean that a project is forbidden to use tasks. Rather, these
guidelines are intended to help the designer make the tradeoffs
between using protected objects and tasks, thus leading the designer
to make a more informed choice between these features.
The guidelines in this document are not intended to stand alone
as a standard. In some cases, it is not clear that a guideline
could be enforced because it is only intended to make the engineer
aware of tradeoffs. In other cases, a choice still remains about
a guideline, such as how many spaces to use for each level of
indentation.
When a guideline is too general to show an example, the "instantiation"
section of each guideline contains more specific guidelines. These
instantiations can be considered a standard and are more likely
to be enforceable. Any organization that attempts to extract standards
from this document needs to evaluate the complete context. Each
guideline works best when related guidelines are practiced. In
isolation, a guideline may have little or no benefit.
Transitioning issues fall into two major categories: the incompatibilities
between the languages, in particular, upward compatibility, and
exploitation of new language features.
Upward compatibility of Ada 95 was a major design goal of the
language. The small number of incompatibilities between Ada 83
and Ada 95 that are likely to occur in practice are easily overcome
(see Ada 95 Rationale [1995] Appendix X entitled Upward Compatibility).
Detailed information on compatibility issues can be found in Taylor
(1995) and Intermetrics (1995).
The transition planner can gain insight from this book into the
exploitation of language features in two ways. First, Table 1
shows the impact of new Ada 95 language features on style guide
chapters. Second, Appendix A maps Ada Reference Manual (1995)
sections to specific style guidelines.
This style guide uses the following typographic conventions:
Serif font General presentation of information.
Italicized serif font Publication titles and emphasis.
Boldfaced serif font Section headings.
Boldfaced sans serif font Subheadings for guideline, instantiation,
example, rationale, notes, exceptions, automation notes, caution,
and subheadings in Summary sections.
Typewriter font Syntax of code.
1.1 ORGANIZATION OF THIS BOOK
1.2 HOW TO USE THIS BOOK
1.3 TO THE NEW Ada PROGRAMMER
1.4 TO THE EXPERIENCED Ada PROGRAMMER
object-oriented features, and performance, focus on design tradeoffs.
These guidelines ask you to consider whether
using an Ada feature is an appropriate design decision for your
application. There are often several ways to implement a particular
design decision, and these guidelines discuss the tradeoffs you
should consider in making your decision.
1.5 TO EXPERIENCED OBJECT-ORIENTED PROGRAMMERS
1.6 TO THE SOFTWARE PROJECT MANAGER
1.7 TO CONTRACTING AGENCIES AND STANDARDS ORGANIZATIONS
1.8 TO Ada 83 TO Ada 95 TRANSITION PLANNERS
1.9 TYPOGRAPHIC CONVENTIONS
In This Guide:
Table of Contents
Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5
Chapter 6
Chapter 7
Chapter 8
Chapter 9
Chapter 10
Chapter 11
Appendix
References
Bibliography
Index