Ada Quality and Style: Guidelines for Professional Programmers SPC-91061-CMC VERSION 02.01.01 December 1992 Ada Quality and Style: Guidelines for Professional Programmers SPC-91061-CMC VERSION 02.01.01 December 1992 SOFTWARE PRODUCTIVITY CONSORTIUM, INC. SPC Building 2214 Rock Hill Road Herndon, Virginia 22070 Copyright 1989, 1991,1992 Software Productivity Consortium, Inc., Herndon, Virginia. Permission to use, copy, modify and distribute this documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both this copyright notice and this permission notice appear in supporting documentation, and that the name Software Productivity Consortium not be used in advertising or publicity pertaining to distribution of the guidelines without the specific, written prior permission of the Consortium. Software Productivity Consortium, Inc. makes no representations about the suitability of the guidelines described herein for any purpose and they are provided "as is" without express or implied warranty. ----- Ada-ASSURED is a trademark of GrammaTech, Inc. IBM is a registered trademark of International Business Machines Corporation. VAX is a registered trademark of Digital Equipment Corporation. PREFACE This version of Ada Quality and Style: Guidelines for Professional Programmers was updated under contract to the Department of Defense (DoD) Ada Joint Program Office (AJPO). Considerable effort was placed on improving the coverage of portability and reusability issues, so the majority of changes can be found in those chapters. A new chapter has been included to address performance issues. The most visible change, however, involves the capitalization issue. The guideline has not changed, but the instantiation now recommends mixed-case identifiers with upper-case abbreviations and lower-case reserved words. Several informal surveys and the general consensus of the reviewers showed strong support for this change. The Complete Examples chapter includes two new examples which highlight portability and the use of tasking. Each of the examples in this chapter are intended to be compilable and executable. The Consortium invites comments on this guidebook to continue enhancing its quality and usefulness. We will consider suggestions for current guidelines and areas for future expansion. Examples that highlight particular points are most helpful. Please direct comments to: Technology Transfer Division - AQS Software Productivity Consortium SPC Building 2214 Rock Hill Road Herndon, Virginia 22070-4005 (703) 742-7211 DoD activities and Defense contractors can obtain copies of this document through the Defense Technical Information Center: DTIC Cameron Station Alexandria, VA 22314 (703) 274-7633 The general public can order copies through the National Technical Information Service: NTIS, Commerce Dept. 5285 Port Royal Rd. Springfield, VA 22161 (703) 487-4650 Electronic copies are available for downloading from the Ada IC Bulletin Board, (703) 614-0215, and from the AJPO host (ajpo.sei.cmu.edu) on the Defense Data Network. AUTHORS AND ACKNOWLEDGEMENTS The editor for this third version of Ada Quality and Style: Guidelines for Professional Programmers is Doug Smith. Kent Johnson managed the update project and the DoD Ada Joint Program Office provided the funding. As part of this update, a panel of distinguished reviewers was chosen from academia, government, and industry. Their contributions and efforts to improve this document are greatly appreciated: Ms. Christine Braun GTE Federal Systems Dr. Charles B. Engle, Jr. Department of Computer Science Florida Institute of Technology Dr. Michael B. Feldman Department of Electrical Engineering and Computer Science George Washington University Dr. Robert Firth Software Engineering Institute Carnegie-Mellon University Ms. Eileen S. Quann FASTRAK Training, Inc. Dr. Charles H. Sampson Computer Sciences Corporation Mr. Ed Seidewitz NASA, Goddard Space Flight Center Lisa Finneran, Rick Kirk, and Eric Marshall also served as Software Productivity Consortium reviewers. Mike Cochran made the majority of changes to the Concurrency chapter and Alex Blakemore authored or rewrote several guidelines for this version. Lyn Uzzle helped fix the menu-driven interface example. Public comment was invited, and Fred J. Roeber and Bob Crispen provided a considerable amount of suggestions. Susan Robanos provided technical editing, Debra Morgan provided word processing, and Tina Medina provided clean proofing. A special thanks to GrammaTech, Inc. who made their Ada-ASSURED product available. All of the examples were formatted in whole or in part using their tool. This version builds on the success of the authors and contributors to previous versions. The acknowledgements from those efforts are included here. The authors for the second edition were Kent Johnson, Elisa Simmons, and Fred Stluka. Contributors were Alex Blakemore and Robert Hofkin. Reviewers included Alex Blakemore, Rick Conn, Tim Harrison, Dave Nettles, and Doug Smith. Additional support was provided by Vicki Clatterbuck and Leslie Hubbard. The following people contributed to an instantiation of the first edition's guidelines: Richard Bechtold, Pete Bloodgood, Shawna Gregory, Tim Powell, Dave Nettles, Kevin Schaan, Doug Smith, and Perry Tsacoumis. Special thanks are extended to Loral for providing feedback in the form of their Software Productivity Laboratory Ada Standards. The Consortium would also like to acknowledge those involved in the first edition. The authors were Richard Drake, Samuel Gregory, Margaret Skalko, and Lyn Uzzle. Paul Cohen managed the project. The contributors and reviewers were Mark Dowson, John Knight, Henry Ledgard, and Robert Mathis. Additional supporters included Bruce Barnes, Alex Blakemore, Terry Bollinger, Charles Brown, Neil Burkhard, William Carlson, Susan Carroll, John Chludzinski, Vicki Clatterbuck, Robert Cohen, Elizabeth Comer, Daniel Cooper, Jorge Diaz-Herrera, Tim Harrison, Robert Hofkin, Allan Jaworski, Edward Jones, John A.N. Lee, Eric Marshall, Charles Mooney, John Moore, Karl Nyberg, Arthur Pyster, Samuel Redwine, Jr., William Riddle, Lisa Smith, Fred Stluka, Kathy Velick, David Weiss, and Howard Yudkin. CONTENTS CHAPTER 1 Introduction 1 1.1 HOW TO USE THIS BOOK 2 1.2 TO THE NEW Ada PROGRAMMER 2 1.3 TO THE EXPERIENCED Ada PROGRAMMER 3 1.4 TO THE SOFTWARE PROJECT MANAGER 3 1.5 TO CONTRACTING AGENCIES AND STANDARDS ORGANIZATIONS 4 CHAPTER 2 Source Code Presentation 5 2.1 CODE FORMATTING 5 2.2 SUMMARY 15 CHAPTER 3 Readability 17 3.1 SPELLING 17 3.2 NAMING CONVENTIONS 20 3.3 COMMENTS 24 3.4 USING TYPES 35 3.5 SUMMARY 37 CHAPTER 4 Program Structure 41 4.1 HIGH-LEVEL STRUCTURE 41 4.2 VISIBILITY 46 4.3 EXCEPTIONS 50 4.4 SUMMARY 52 CHAPTER 5 Programming Practices 55 5.1 OPTIONAL PARTS OF THE SYNTAX 55 5.2 PARAMETER LISTS 58 5.3 TYPES 60 5.4 DATA STRUCTURES 63 5.5 EXPRESSIONS 66 5.6 STATEMENTS 69 5.7 VISIBILITY 77 5.8 USING EXCEPTIONS 80 5.9 ERRONEOUS EXECUTION 83 5.10 SUMMARY 87 CHAPTER 6 Concurrency 91 6.1 TASKING 91 6.2 COMMUNICATION 96 6.3 TERMINATION 104 6.4 SUMMARY 107 CHAPTER 7 Portability 109 7.1 FUNDAMENTALS 110 7.2 NUMERIC TYPES AND EXPRESSIONS 113 7.3 STORAGE CONTROL 116 7.4 TASKING 117 7.5 EXCEPTIONS 118 7.6 REPRESENTATION CLAUSES AND IMPLEMENTATION-DEPENDENT FEATURES 119 7.7 INPUT/OUTPUT 122 7.8 SUMMARY 124 CHAPTER 8 Reusability 127 8.1 UNDERSTANDING AND CLARITY 128 8.2 ROBUSTNESS 130 8.3 ADAPTABILITY 136 8.4 INDEPENDENCE 147 8.5 SUMMARY 151 CHAPTER 9 Performance 153 9.1 IMPROVING EXECUTION SPEED 153 9.2 SUMMARY 156 CHAPTER 10 Complete Examples 157 10.1 MENU-DRIVEN USER INTERFACE 157 10.2 LINE-ORIENTED PORTABLE DINING PHILOSOPHERS EXAMPLE 165 10.3 WINDOW-ORIENTED PORTABLE DINING PHILOSOPHERS EXAMPLE 170 APPENDIX A Map from Ada Language Reference Manual to Guidelines 179 REFERENCES 185 BIBLIOGRAPHY 189 INDEX 193 CHAPTER 1 Introduction This book is intended to help the computer professional produce better Ada programs. It presents a set of specific guidelines for using the powerful features of Ada in a disciplined manner. Each guideline consists of a concise statement of the principles that should be followed, and a rationale explaining why following the guideline is important. In most cases, an example of the use of the guideline is provided, and in some cases a further example is included showing the consequences of violating the guideline. Possible exceptions to the application of the guideline are explicitly noted, and further explanatory notes, including notes on how the guideline could be automated by a tool, are provided where appropriate. Many of the guidelines 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. These issues are discussed in Section of this introduction. Other sections of the introduction discuss how this book should be used by various software development personnel. 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. Clear, readable, understandable source text eases program evolution, adaptation, and maintenance. First, such source text is more likely to be correct and reliable. Second, effective code adaptation is a prerequisite to code reuse, a technique that has the potential for drastic reductions in system development cost. Easy adaptation requires a thorough understanding of the software; this is considerably facilitated by clarity. Finally, since 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; the investment of writing readable, understandable code is thus well worthwhile. Many of the guidelines in this book are designed to promote clear source text. There are two main aspects of code clarity: 1) Careful and consistent layout of the source text on the page or the screen can enhance readability dramatically; 2) Careful attention to the structure of code can make it 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. Comments in source text are a controversial issue. There are arguments both for and against the view that comments enhance readability. The biggest problem with comments in practice is that people often fail to update them when the associated source text is changed, thereby making the commentary misleading. Commentary should be reserved for expressing needed information that cannot be expressed in code and highlighting cases where there are overriding reasons to violate one of the guidelines. If possible, source text should use self-explanatory names for objects and program units; and it should use simple, understandable program structures so that little additional commentary is needed. The extra effort in selecting (and entering) appropriate names and the extra thought needed to design clean and understandable program structures are fully justified. Programming texts often fail to discuss overall program structure; Chapter 4 addresses this. The majority of the guidelines in that chapter are concerned with the application of sound software engineering principles such as information hiding and separation of concerns. The chapter is neither a textbook on nor an introduction to these principles; rather, it indicates how they can be realized using the features of Ada. A number of other guidelines are particularly concerned with reliability and portability issues. They counsel avoidance of language features and programming practices that either depend on properties not defined in Ada or on properties that may vary from implementation to implementation. Some of these guidelines, such as the one forbidding dependence on expression evaluation order, should never be violated. Others may have to be violated in special situations such as interfacing to other systems. This should only be done after careful deliberation, and such violations should be prominently indicated. Performance constraints are often offered as an excuse for unsafe programming practices; this is rarely a sufficient justification. Software tools could be used to enforce, encourage, or check conformance to many of the guidelines. At present, such tools for Ada primarily consist of code formatters or syntax directed editors. Existing code formatters are often parameterizable and can be instantiated to lay out code in a way consistent with many of the guidelines in this book. This book is intended for those involved in the actual development of software systems written in Ada. The following subsections discuss how to make the most effective use of the material presented. Readers with different levels of Ada experience and different roles in a software project will need to use the book in different ways. Specific comments to three broad categories of software development personnel are addressed: inexperienced Ada programmers, experienced Ada programmers, and software development managers. 1.1 HOW TO USE THIS BOOK There are a number of ways in which this book can be used: as a reference on good Ada style; as a comprehensive list of guidelines which will contribute to better Ada programs; or as a reference work to consult about using 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, and 4 and Chapter 5 up to Section 5.7. Some of the material is quite difficult (for example, Section 4.2 which discusses visibility), but it covers issues which are fundamental to the effective use of Ada and is important for any software professional involved in building Ada systems. The remainder of the book covers relatively specific issues. Exceptions and erroneous execution is covered at the end of Chapter 5; and tasking, portability, and reuse is covered in Chapters 6, 7, and 8 respectively. You should be aware of the content of this part of the book. You may be required to follow the guidelines presented in it, but you could defer more detailed study until needed. Meanwhile, it can serve as useful reference material about specific Ada features; for example, the discussion of floating point numbers in the chapter on portability. 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 such as Barnes (1989) or Cohen (1986). The Ada Language Reference Manual (Department of Defense 1983) should be regarded as a crucial companion to this book. The majority of guidelines reference the sections of the Ada Language Reference Manual that define the language features being discussed. Appendix A cross references sections of the Ada Language Reference Manual to the guidelines. Throughout the book, references are given to other sources of information about Ada style and other Ada issues. The references are listed at the end of the book, followed by a bibliography which includes them and other relevant sources consulted during the book's preparation. 1.2 TO THE NEW Ada PROGRAMMER 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. The guidelines in this book forbid the use of few Ada features. Rather, they show how the features can be systematically deployed to write clear, high-quality programs. Following the guidelines will 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 another programming language 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. Note that each chapter ends with a summary of the guidelines it contains. The rationale for many of the guidelines help 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. 1.3 TO THE EXPERIENCED Ada PROGRAMMER As an experienced 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. Another important reason for general adoption of common guidelines is consistency. 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, within-project code reuse, 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. 1.4 TO THE SOFTWARE PROJECT MANAGER 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 them. A number of guidelines indicate a range of decisions, but they do not prescribe a particular decision. For example, the second guideline in the book (Guideline ) advocates using a consistent number of spaces for indentation and indicates in the rationale that 2 to 4 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 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 which 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 improve 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 use 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. Probably the most important aspect of this is gaining the wholehearted commitment of your programming staff to use them. 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. Consistent coding standards work well with automatic tool support. If you have a tools group in your project or organization, they can be tasked to acquire or develop tools to support your standards. It is very cost effective to use tools to enforce standards. Where tools cannot be used to automatically modify code to conform to standards, they can often be used to at least check conformance. See the automation notes sections associated with many of the guidelines. Some general issues concerning the management of Ada projects are discussed by Foreman and Goodenough (1987). 1.5 TO CONTRACTING AGENCIES AND STANDARDS ORGANIZATIONS The guidelines in this document are not intended to stand alone as a standard. It is not even clear in some cases that a guideline could be enforced since 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 can be considered for 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 guideines are practiced. In isolation, a guideline may have little or no benefit. CHAPTER 2 Source Code Presentation The physical layout of source text on the page or screen has a strong effect on its readability. This chapter contains source code presentation guidelines intended to make the code more readable. In addition to the general purpose guidelines, specific recommendations are made in the "instantiation" sections. If you disagree with the specific recommendations, you may want to adopt your own set of conventions that still follow the general purpose guidelines. Above all, be consistent across your entire project. An entirely consistent layout is hard to achieve or check manually. Therefore you may prefer to automate layout with a tool for parameterized code formatting or incorporate the guidelines into an automatic coding template. Some of the guidelines and specific recommendations presented in this section cannot be enforced by a formatting tool because they are based on the semantics, not the syntax, of the Ada code. More details are given in the "automation notes" sections. 2.1 CODE FORMATTING The "code formatting" of Ada source code affects how the code looks, not what the code does. Topics included here are horizontal spacing, indentation, alignment, pagination, and line length. The most important guideline is to be consistent throughout the compilation unit as well as the project. 2.1.1 Horizontal Spacing guideline o Use consistent spacing around delimiters. o Use the same spacing as you would in regular prose. instantiation Specifically, leave at least one blank space in the following places, as shown in the examples throughout this book. More spaces may be required for the vertical alignment recommended in subsequent guidelines. - Before and after the following delimiters and binary operators: + - * / & < = > /= <= >= := => | .. : <> - Outside of the quotes for string (") and character (') literals, except where prohibited. - Outside, but not inside, of parentheses. - After commas (,) and semicolons (;). Do not leave any blank spaces in the following places, even if this conflicts with the above recommendation. - After the plus (+) and minus (-) signs when used as unary operators. - After a function call. - Inside of label delimiters (<< >>). - Before and after the apostrophe (') and period (.) - Between multiple consecutive opening or closing parentheses. - Before commas (,) and semicolons (;). When superfluous parentheses are omitted because of operator precedence rules, spaces may optionally be removed around the highest precedence operators in that expression. example Default_String : constant String := "This is the long string returned by" & " default. It is broken into multiple" & " Ada source lines for convenience."; type Signed_Whole_16 is range -2**15 .. 2**15 - 1; type Address_Area is array (Natural range <>) of Signed_Whole_16; Register : Address_Area (16#7FF0# .. 16#7FFF#); Memory : Address_Area ( 0 .. 16#7FEC#); Register(Pc) := Register(A); X := Signed_Whole_16(Radius * Sin(Angle)); Register(Index) := Memory(Base_Address + Index * Element_Length); Get(Value => Sensor); Error_Term := 1.0 - (Cos(Theta)**2 + Sin(Theta)**2); Z := X**3; Y := C * X + B; Volume := Length * Width * Height; rationale It is a good idea to use white space around delimiters and operators because they are typically short (one or two character) sequences that can easily get lost among the longer keywords and identifiers. Putting white space around them makes them stand out. Consistency in spacing also helps make the source code easier to scan visually. However, many of the delimiters (commas, semicolons, parentheses, etc.) are familiar as normal punctuation marks. It is distracting to see them spaced differently in a computer program than in normal text. Therefore, they should be spaced the same (no spaces before commas and semicolons, no spaces inside of parentheses, etc.). exception The one notable exception is the colon (:). In Ada, it is useful to use the colon as a tabulator or a column separator (see Guideline ). In this context, it makes sense to put spaces before and after the colon, rather than only after as in normal text. automation notes The guidelines in this section are easily enforced with an automatic code formatter. 2.1.2 Indentation guideline o Indent and align nested control structures, continuation lines, and embedded units consistently. o Distinguish between indentation for nested control structures and for continuation lines. o Use spaces for indentation, not the tab character (Nissen and Wallis 1984, w2.2). instantiation Specifically, the following indentation conventions are recommended, as shown in the examples throughout this book. Note that the minimum indentation is described. More spaces may be required for the vertical alignment recommended in subsequent guidelines. - Use the recommended paragraphing shown in the Ada Language Reference Manual (Department of Defense 1983). - Use three spaces as the basic unit of indentation for nesting. - Use two spaces as the basic unit of indentation for continuation lines. A label is outdented three spaces. A continuation line is indented two spaces: begin <