|Ada 95 Quality and Style Guide||Chapter 4|
4.2.3 Restricting Visibility
Consider using private child packages in lieu of nesting.
Restrict the visibility of program units as much as possible by nesting them inside package bodies (Nissen and Wallis 1984) if you cannot use a private child package.
Minimize nesting program units inside subprograms and tasks.
Minimize the scope within which withclauses apply.
Only with those units directly needed.
This program illustrates the use of child library units to restrict visibility. The procedure Rational_Numbers.Reduce is nested inside the body of Rational_Numbers to restrict its visibility to the implementation of this abstraction. Rather than make the text input/output facilities visible to the entire rational number hierarchy, it is only available to the body of the child library Rational_Numbers.IO. This example is adapted from the Ada Reference Manual (1995), §§7.1, 7.2, and 10.1.1):------------------------------------------------------------------------- package Rational_Numbers is type Rational is private; function "=" (X, Y: Rational) return Boolean; function "/" (X, Y: Integer) return Rational; -- construct a rational number function "+" (X, Y: Rational) return Rational; function "-" (X, Y: Rational) return Rational; function "*" (X, Y: Rational) return Rational; function "/" (X, Y: Rational) return Rational; -- rational division private ... end Rational_Numbers; package body Rational_Numbers is procedure Reduce (R :in out Rational) is . . . end Reduce; . . . end Rational_Numbers; package Rational_Numbers.IO is procedure Put (R : in Rational); procedure Get (R : out Rational); end Rational_Numbers.IO; with Ada.Text_IO; with Ada.Integer_Text_IO; package body Rational_Numbers.IO is -- has visibility to parent private type declaration procedure Put (R : in Rational) is begin Ada.Integer_Text_IO.Put (Item => R.Numerator, Width => 0); Ada.Text_IO.Put ("/"); Ada.Integer_Text_IO.Put (Item => R.Denominator, Width => 0); end Put; procedure Get (R : out Rational) is . . . end Get; end Rational_Numbers.IO;
Restricting visibility of a program unit ensures that the program unit is not called from some part of the system other than that which was intended. This is done by nesting it inside the only unit that uses it, by hiding it inside a package body rather than declaring it in the package specification, or by declaring it as a private child unit. This avoids errors and eases the job of maintainers by guaranteeing that a local change in that unit will not have an unforeseen global effect.
Restricting visibility of a library unit by using with clauses on subunits rather than on the entire parent unit is useful in the same way. In the example above, it is clear that the package Text_IO is used only by the Listing_Facilities package of the compiler.
Nesting inside subprograms and tasks is discouraged because it leads to unreusable components. These components are essentially unreusable because they make undesirable up-level references into the defining context. Unless you truly want to ensure that the program unit is not called from some unintended part of the system, you should minimize this form of nesting.
See also Guideline 4.2.1 for a discussion of the use of child units.
One way to minimize the coverage of a with clause is to use it only with subunits that really need it. Consider making those subunits separate compilation units when the need for visibility to a library unit is restricted to a subprogram or two.
|< Previous Page||Search||Contents||Index||Next Page >|