Ada 95 Quality and Style Guide Chapter 3

Chapter 3: Readability - TOC - 3.2 NAMING CONVENTIONS

3.2.4 Naming of Tagged Types and Associated Packages

guideline

  • Use a consistent naming convention for tagged types and associated packages.

  • instantiation

    Naming conventions spark "religious wars"; therefore, two different instantiations are presented. The first instantiation integrates the use of object-oriented features. Except for two special cases, it applies the same naming conventions to declarations, independent of whether they use an object-oriented feature:

    - Name tagged types no differently than subtype names (see Guideline 3.2.2).
    - Use the prefix Abstract_ for packages that export an abstraction for which you intend to provide multiple implementations (see Guideline 9.2.4).
    - Use the suffix _Mixin for packages that provide units of functionality that can be "mixed in" to core abstractions.

    The second instantiation highlights the use of object-oriented features through special names or suffixes:

    - Name class packages after the object they represent, without a suffix (Rosen 1995).
    - Name mixin packages after the facet they represent, appending the suffix _Facet (Rosen 1995).
    - Name the main tagged type Instance (Rosen 1995).
    - Follow the declaration of the specific type with a subtype named Class for the corresponding class-wide type (Rosen 1995).

    example

    The following two-part example from the Rationale (1995, §§4.4.4 and 4.6.2) applies the naming conventions of the first instantiation.

    For the first part of this example, assume the type Set_Element was declared elsewhere:

    package Abstract_Sets is
       type Set is abstract tagged private;
       -- empty set
       function Empty return Set is abstract;
       -- build set with 1 element
       function Unit (Element: Set_Element) return Set is abstract;
       -- union of two sets
       function Union (Left, Right: Set) return Set is abstract;
       -- intersection of two sets
       function Intersection (Left, Right: Set) return Set is abstract;
       -- remove an element from a set
       procedure Take (From    : in out Set;
                       Element :    out set_Element) is abstract;
       Element_Too_Large : exception;
    private
       type Set is abstract tagged null record;
    end Abstract_Sets;
    with Abstract_Sets;
    package Bit_Vector_Sets is   -- one implementation of set abstraction
       type Bit_Set is new Abstract_Sets.Set with private;
       ...
    private
       Bit_Set_Size : constant := 64;
       type Bit_Vector is ...
       type Bit_Set is new Abstract_Sets.Set with
          record
             Data : Bit_Vector;
          end record;
    end Bit_Vector_Sets;
    with Abstract_Sets;
    package Sparse_Sets  -- alternate implementation of set abstraction
       type Sparse_Set is new Abstract_Sets.Set with private;
       ...
    private
       ...
    end Bit_Vector_Sets;
    

    The second part of this example applies the naming convention to mixin packages that support a windowing system:

    -- assume you have type Basic_Window is tagged limited private;
    generic
       type Some_Window is abstract new Basic_Window with private;
    package Label_Mixin is 
       type Window_With_Label is abstract new Some_Window with private;
       ...
    private
       ...
    end Label_Mixin;
    generic
       type Some_Window is abstract new Basic_Window with private;
    package Border_Mixin is 
       type Window_With_Label is abstract new Some_Window with private;
       ...
    private
       ...
    end Border_Mixin;
    

    The following example applies the naming conventions of the second instantiation, as discussed in Rosen (1995):

    package Shape is
       subtype Side_Count is range 0 .. 100;
       type Instance (Sides: Side_Count) is tagged private;
       subtype Class is Instance'Class;
       . . .
       -- operations on Shape.Instance
    private
       . . .
    end Shape;
    with Shape; use Shape;
    package Line is
       type Instance is new Shape.Instance with private;
       subtype Class is Instance'Class;
       . . .
       -- Overridden or new operations
    private
       . . .
    end Line;
    with Shape; use Shape;
    generic
       type Origin is new Shape.Instance;
    package With_Color_Facet is
       type Instance is new Origin with private;
       subtype Class is Instance'Class;
       -- operations for colored shapes
    private
       . . .
    end With_Color_Facet;
    with Line; use Line;
    with With_Color_Facet;
    package Colored_Line is new With_Color_Facet (Line.Instance);
    

    Sample declarations might look like:

    Red_Line : Colored_Line.Instance;
    procedure Draw (What : Shape.Instance);
    

    The above scheme works whether you use full names or a use clause. As long as you use the same name for all the specific types (i.e., type Instance) and class-wide types, the unqualified names will always hide one another. Thus, the compiler will insist you use full name qualification to resolve the ambiguity introduced by the use clause (Rosen 1995).

    rationale

    You want to use a naming scheme that is consistent and readable and conveys the intent of the abstraction. Ideally, the naming scheme should be uniform in how it handles the different ways in which tagged types are used to create classes. If the naming convention is too rigid, however, you will write code fragments that appear stilted from a readability point of view. By using a similar naming convention for type extension through derivation and through generic mixin (see also Guideline 9.5.1), you achieve readable declarations of objects and procedures.

    notes

    A naming convention for classes draws a hard line between object-oriented abstractions and other kinds of abstractions. Given that engineers have been defining abstract data types in Ada 83 (Ada Reference Manual 1983) for over 10 years, you may not want to change the naming convention just for the sake of using type extension with a type. You must consider how important it is to call out uses of inheritance in the overall use of abstractions in your program. If you prefer to emphasize abstraction, in general, over the mechanism used to implement the abstraction (i.e., inheritance, type-extension, and polymorphism), you may not want to impose such a stringent naming convention. You do not hamper quality by favoring a smoother transition in naming conventions from abstractions developed without inheritance to those developed with inheritance.

    If you choose a naming convention that highlights the use of object-oriented features and later decide to change the declaration to one that does not use an object-oriented feature, the change may be expensive. You must naturally change all occurrences of the names and must be careful not to introduce errors as you update the names. If you choose a naming convention that prohibits the use of suffixes or prefixes to characterize the declaration, you lose the opportunity to convey the intended usage of the declared item.


    < Previous Page Search Contents Index Next Page >
    1 2 3 4 5 6 7 8 9 10 11
    TOC TOC TOC TOC TOC TOC TOC TOC TOC TOC TOC
    Appendix References Bibliography