Ada 95 Quality and Style Guide Chapter 4

Chapter 4: Program Structure - TOC - 4.2 VISIBILITY

4.2.1 Minimization of Interfaces

guideline

  • Put only what is needed for the use of a package into its specification.
  • Minimize the number of declarations in package specifications.
  • Do not include extra operations simply because they are easy to build.
  • Minimize the context (with) clauses in a package specification.
  • Reconsider subprograms that seem to require large numbers of parameters.
  • Do not manipulate global data within a subprogram or package merely to limit the number of parameters.
  • Avoid unnecessary visibility; hide the implementation details of a program unit from its users.
  • Use child library units to control the visibility of parts of a subsystem interface.
  • Use private child packages for those declarations that should not be used outside the subsystem.
  • Use child library units present different views of an entity to different clients.
  • Design (and redesign) interfaces after having worked out the logic of various expected clients of the interface.

  • example
    -------------------------------------------------------------------------
    package Telephone_Book is
       type Listing is limited private;
       procedure Set_Name (New_Name : in     String;
                           Current  : in out Listing);
       procedure Insert (Name    : in     String;
                         Current : in out Listing);
       procedure Delete (Obsolete : in     String;
                         Current  : in out Listing);
    private
       type Information;
       type Listing is access Information;
    end Telephone_Book;
    -------------------------------------------------------------------------
    package body Telephone_Book is
       -- Full details of record for a listing
       type Information is
          record
             ...
             Next : Listing;
          end record;
       First : Listing;
       procedure Set_Name (New_Name : in     String;
                           Current  : in out Listing) is separate;
       procedure Insert (Name    : in      String;
                         Current : in out  Listing) is separate;
       procedure Delete (Obsolete : in     String;
                         Current  : in out Listing) is separate;
    end Telephone_Book;
    -------------------------------------------------------------------------
    

    rationale

    For each entity in the specification, give careful consideration to whether it could be moved to a child package or to the parent package body. The fewer the extraneous details, the more understandable the program, package, or subprogram. It is important to maintainers to know exactly what a package interface is so that they can understand the effects of changes. Interfaces to a subprogram extend beyond the parameters. Any modification of global data from within a package or subprogram is an undocumented interface to the "outside" as well.

    Minimize the context clauses on a specification by moving unnecessary clauses to the body. This technique makes the reader's job easier, localizes the recompilation required when library units change, and helps prevent a ripple effect during modifications. See also Guideline 4.2.3.

    Subprograms with large numbers of parameters often indicate poor design decisions (e.g., the functional boundaries of the subprogram are inappropriate or parameters are structured poorly). Conversely, subprograms with no parameters are likely to be accessing global data.

    Objects visible within package specifications can be modified by any unit that has visibility to them. The object cannot be protected or represented abstractly by its enclosing package. Objects that must persist should be declared in package bodies. Objects whose value depends on program units external to their enclosing package are probably either in the wrong package or are better accessed by a subprogram specified in the package specification.

    Child library units can provide distinct views of the hierarchical library. The engineer can provide a different view for the client than for the implementor (Rationale 1995, §10.1). By creating private child packages, the engineer can provide facilities that are only available inside the subsystem rooted at the parent library unit. The declarations inside a private child package specification are not exported outside the subsystem. Thus, the engineer can declare utilities needed to implement an abstraction in a private child package (e.g., debugging utilities [Cohen et al. 1993]) and be certain that users of the abstraction (i.e., the clients) cannot access these utilities.

    Different clients may have different needs for essentially the same resource. Instead of having multiple versions of the resources, consider having child units that export different views for different purposes.

    Designing an interface based strictly on predicting what clients "might" need can produce a bloated and inappropriate interface. What then happens is that clients try to "live" with the interface and work around the inappropriate interfaces, repeating code that logically should be part of the shared abstraction. See Guideline 8.3.1 for a discussion of interfaces from the reusability perspective.

    notes

    In some cases, subroutine libraries look like large, monolithic packages. In such cases, it may be beneficial to break these up into smaller packages, grouping them according to category (e.g., trigonometric functions).


    < 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