optional parts of the syntax
- Associate names with loops when they are nested (Booch 1986, 1987).
- Associate names with any loop that contains an
- Associate names with blocks when they are nested .
- Use loop names on all
exitstatements from nested loops.
- Include the defining program unit name at the end of a package specification and body.
- Include the defining identifier at the end of a task specification and body.
- Include the entry identifier at the end of an
- Include the designator at the end of a subprogram body.
- Include the defining identifier at the end of a protected unit declaration.
- Name formal parametername formal parameters descriptively to reduce the need for comments .
- Use named parameter association in calls of infrequently used subprograms or entries with many formal parameters .
- Use named association when instantiating generics.
- Use named association for clarification when the actual parameter is any literal or expression.
- Use named association when supplying a nondefault value to an optional parameter.
- Provide default parameters to allow for occasional, special use of widely used subprograms or entries.
- Place default parameters at the end of the formal parameter list.
- Consider providing default values to new parameters added to an existing subprogram.
- Show the mode indication of all procedure and entry parameters (Nissen and Wallis 1984).
- Use the most restrictive parameter mode applicable to your application.
- Use existing types as building blocks by deriving new types from them.
- Use range constraints on subtypes.
- Define new types, especially derived types, to include the largest set of possible values, including boundary values.
- Constrain the ranges of derived types with subtypes, excluding boundary values.
- Use type derivation rather than type extension when there are no meaningful components to add to the type.
- Avoid anonymous array types.
- Use anonymous array types for array variables only when no suitable type exists or can be created and the array will not be referenced as a whole (e.g., used as a subprogram parameter).
- Use access parameters and access discriminants to guarantee that the parameter or discriminant is treated as a constant.
- Derive from controlled types in preference to using limited private types.
- Use limited private types in preference to private types.
- Use private types in preference to nonprivate types.
- Explicitly export needed operations rather than easing restrictions.
- Use access-to-subprogram types for indirect access to subprograms.
- Wherever possible, use abstract tagged types and dispatching rather than access-to-subprogram types to implement dynamic selection and invocation of subprograms.
- When declaring a discriminant, use as constrained a subtype as possible (i.e., subtype with as specific a range constraint as possible).
- Use a discriminated record rather than a constrained array to represent an array whose actual values are unconstrained.
- Use records to group heterogeneous but related data.
- Consider records to map to I/O device data.
- Use access types to class-wide types to implement heterogeneous polymorphic data structures.
- Use tagged types and type extension rather than variant records (in combination with enumeration types and case statements).
- Record structures should not always be flat. Factor out common parts.
- For a large record structure, group related components into smaller subrecords.
- For nested records, pick element names that read well when inner elements are referenced.
- Consider using type extension to organize large data structures.
- Differentiate between static and dynamic data. Use dynamically allocated objects with caution.
- Use dynamically allocated data structures only when it is necessary to create and destroy them dynamically or to be able to reference them by different names.
- Do not drop pointers to undeallocated objects.
- Do not leave dangling references to deallocated objects.
- Initialize all access variables and components within a record.
- Do not rely on memory deallocation.
- Deallocate explicitly.
- Use length clauses to specify total allocation size.
- Provide handlers for
- Use controlled types to implement private types that manipulate dynamic data.
- Avoid unconstrained record objects unless your run-time environment reliably reclaims dynamic heap storage.
- Unless your run-time environment reliably reclaims dynamic heap
storage, declare the following items only in the outermost, unnested
declarative part of either a library package, a main subprogram, or
a permanent task:
- Access types
- Constrained composite objects with nonstatic bounds
- Objects of an unconstrained composite type other than unconstrainedrecords
- Composite objects large enough (at compile time) for the compiler to allocate implicitly on the heap
- Unless your run-time environment reliably reclaims dynamic heap
storage or you are creating permanent, dynamically allocated tasks,
avoid declaring tasks in the following situations:
- Unconstrained array subtypes whose components are tasks
- Discriminated record subtypes containing a component that is an array of tasks, where the array size depends on the value of the discriminant
- Any declarative region other than the outermost, unnested declarative part of either a library package or a main subprogram
- Arrays of tasks that are not statically constrained
- Minimize the use of aliased variables.
- Use aliasing for statically created, ragged arrays (Rationale 1995, §3.7.1).
- Use aliasing to refer to part of a data structure when you want to hide the internal connections and bookkeeping information.
- Use access discriminants to create self-referential data structures, i.e., a data structure one of whose components points to the enclosing structure.
- Use modular types rather than a Boolean arrays when you create data
structures that need bit-wise operations, such as
'Lastinstead of numeric literals to represent the first or last values of a range.
'Rangeor the subtype name of the range instead of
'First .. 'Last.
- Use array attributes
'Lengthinstead of numeric literals for accessing arrays.
- Use the
'Rangeof the array instead of the name of the index subtype to express a range.
'First .. 'Lastto express a range.
- Use parentheses to specify the order of subexpression evaluation to clarify expressions (NASA 1987).
- Use parentheses to specify the order of evaluation for subexpressions whose correctness depends on left to right evaluation.
- Avoid names and constructs that rely on the use of negatives .
- Choose names of flags so they represent states that can be used in positive form.
- Use short-circuit forms of the logical operators to specify the order of conditions when the failure of one condition means that the other condition will raise an exception.
>=in relational expressions with real operands instead of
- Minimize the depth of nested expressions (Nissen and Wallis 1984).
- Minimize the depth of nested control structures (Nissen and Wallis 1984).
- Try using simplification heuristics.
- Use slices rather than a loop to copy part of an array.
- Minimize the use of an
otherschoice in a
- Do not use ranges of enumeration literals in
casestatements rather than
if/elsifstatements, wherever possible.
- Use type extension and dispatching rather than
casestatements, if possible.
forloops, whenever possible.
whileloops when the number of iterations cannot be calculated before entering the loop but a simple continuation condition can be applied at the top of the loop.
- Use plain loops with
exitstatements for more complex situations.
- Minimize the number of ways to exit a loop.
exitstatements to enhance the readability of loop termination code (NASA 1987).
exit when ...rather than
if ... then exitwhenever possible (NASA 1987).
- Consider specifying bounds on loops.
- Consider specifying bounds on recursion.
- Do not use
- Minimize the number of
returnstatementsfrom a subprogram (NASA 1987).
returnstatements with comments or white space to keep them from being lost in other code.
- Use blocks to localize the scope of declarations.
- Use blocks to perform local renaming.
- Use blocks to define local exception handlers.
- Use an aggregate instead of a sequence of assignments to assign values to all components of a record
- Use an aggregate instead of a temporary variable when building a record to pass as an actual parameter
- Use positional association only when there is a conventional ordering of the arguments.
- When you need to provide visibility to operators, use the
- Avoid/minimize the use of the
useclause (Nissen and Wallis 1984).
- Consider using a package
renamesclause rather than a
useclause for a package.
- Consider using the
useclause in the following situations:
- When standard packages are needed and no ambiguous references are introduced
- When references to enumeration literals are needed
- Localize the effect of all
- Limit the scope of a renaming declaration to the minimum necessary scope.
- Rename a long, fully qualified name to reduce the complexity if it becomes unwieldy.
- Use renaming to provide the body of a subprogram if this subprogram merely calls the first subprogram.
- Rename declarations for visibility purposes rather than using the use clause, except for operators .
- Rename parts when your code interfaces to reusable components originally written with nondescriptive or inapplicable nomenclature.
- Use a project-wide standard list of abbreviations to rename common packages.
- Provide a
use typerather than a
renamesclause to provide visibility to operators.
- Limit overloading to widely used subprograms that perform similar actions on arguments of different types (Nissen and Wallis 1984).
- Preserve the conventional meaning of overloaded operators (Nissen and Wallis 1984).
- Use "
+" to identify adding, joining, increasing, and enhancing kinds of functions.
- Use "
-" to identify subtraction, separation, decreasing, and depleting kinds of functions.
- Use operator overloading sparingly and uniformly when applied to tagged types.
- Define an appropriate equality operator for private types.
- Consider redefining the equality operator for a private type.
- When overloading the equality operator for types, maintain the properties of an algebraic equivalence relation.
- When it is easy and efficient to do so, avoid causing exceptions to be raised.
- Provide handlers for exceptions that cannot be avoided.
- Use exception handlers to enhance readability by separating fault handling from normal execution.
- Do not use exceptions and exception handlers as
- Do not evaluate the value of an object (or a part of an object) that has become abnormal because of the failure of a language-defined check.
- When writing an exception handler for
others, capture and return additional information about the exception through the
Exception_Informationsubprograms declared in the predefined package
othersonly to catch exceptions you cannot enumerate explicitly, preferably only to flag a potential abort.
- During development, trap
others, capture the exception being handled, and consider adding an explicit handler for that exception.
- Handle all exceptions, both user and predefined .
- For every exception that might be raised, provide a handler in suitable frames to protect against undesired propagation outside the abstraction .
- Do not rely on being able to identify the fault-raising, predefined, or implementation-defined exceptions.
- Use the facilities defined in
Ada.Exceptionsto capture as much information as possible about an exception.
- Use blocks to associate localized sections of code with their own exception handlers.
erroneous execution and bounded errors
Ada.Unchecked_Conversiononly with the utmost care (Ada Reference Manual 1995, §13.9).
- Consider using the
'Validattribute to check the validity of scalar data).
- Ensure that the value resulting from
Ada.Unchecked_Conversionproperly represents a value of the parameter's subtype.
- Isolate the use of
Ada.Unchecked_Conversionin package bodies.
- Isolate the use of
Ada.Unchecked_Deallocationin package bodies.
- Ensure that no dangling reference to the local object exists after exiting the scope of the local object.
- Minimize the use of the attribute
Unchecked_Access, preferably isolating it to package bodies.
- Use the attribute
Unchecked_Accessonly on data whose lifetime/scope is "library level."
- Use address clauses to map variables and entries to the hardware device or memory, not to model the FORTRAN "equivalence" feature.
- Ensure that the address specified in an attribute definition clause is valid and does not conflict with the alignment.
- If available in your Ada environment, use the package
Ada.Interruptsto associate handlers with interrupts.
- Avoid using the address clause for nonimported program units.
- Do not suppress exception checks during development.
- If necessary, during operation, introduce blocks that encompass the smallest range of statements that can safely have exception checking removed.
- Initialize all objects , including access values, prior to use.
- Use caution when initializing access values.
- Do not depend on default initialization that is not part of the language.
- Derive from a controlled type and override the primitive procedure to ensure automatic initialization.
- Ensure elaboration of an entity before using it.
- Use function calls in declarations cautiously.
- Ensure that values obtained from
Ada.Sequential_IOare in range.
- Use the
'Validattribute to check the validity of scalar values obtained through
- Prevent exceptions from propagating outside any user-defined
Adjustprocedure by providing handlers for all predefined and user-defined exceptions at the end of each procedure.
- Do not invoke a potentially blocking operation within a protected entry, a protected procedure, or a protected function.
- Do not use an asynchronous select statement within abort-deferred operations.
- Do not create a task that depends on a master that is included entirely within the execution of an abort-deferred operation.
This page of the "Ada Quality and Style Guide" has been adapted from the original work at https://en.wikibooks.org/wiki/Ada_Style_Guide, which is licensed under the Creative Commons Attribution-ShareAlike License; additional terms may apply. Page not endorsed by Wikibooks or the Ada Style Guide Wikibook authors. This page is licensed under the same license as the original work.