TEAM-ADA Archives

Team Ada: Ada Programming Language Advocacy


Options: Use Forum View

Use Monospaced Font
Show Text Part by Default
Condense Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
"Team Ada: Ada Advocacy Issues (83 & 95)" <[log in to unmask]>
Wed, 15 Apr 1998 12:31:44 -0400
"Robert I. Eachus" <[log in to unmask]>
"Robert I. Eachus" <[log in to unmask]>
text/plain; charset="us-ascii"
text/plain (65 lines)
At 07:05 PM 4/13/98 -0700, Al Christians wrote:
>One thing that you might want to look at is the 'rule of Demeter'.
>This is a rule that is supposed to improve program quality that
>prohibits most forms of multi-level indirection A -> B -> C;

   I'll emphasize the "One thing," but yes, violations of the Rule of
Demeter in Ada result in additional withs on package bodies.  Sometimes the
violations are necessary because the formal interface to the components of
a class excludes necessary operations.  But most violations you find in
large projects are gratuitous.  To create a trival example to explain the
issue, lets say we have a record type message:

     with Ada.Calendar; with Text_Operations; with People;
     package Messages is
       type Message is private;
       function Body(M: in Message) return Text_Operations.Text;
       -- other operations on Message...
       type Message is
         Timestamp: Calendar.Time;
         Author: Person;
         To: Destination_List;
         Contents: Text;
       end Message;
     end Messages;

     --Type Text is defined in a different package:

     with Ada.Strings.Bounded;
     package Text_Operations is
        type Text is private;
        -- operations on Text type including:
        function Line(Object: Text; Index: Integer) return String;
        package Lines is new Ada.Strings.Bounded.Generic_Bounded_Length(80);
        type Line_Array is array(Positive range <>) of Lines.Bounded_String;
        type Text(Lines: Natural) is record
          Body: Line_Array(1..Lines);
        end record;
     end Text_Operations;

     Notice that this is good (TM) Ada design.  Types Message and Text are
private so that even the temptation for a user of the Message abstraction
to "reach in" to the Message to extract the year written or the name of the
Author will be avoided.  But in the body of Messages, there is a potential
problem.  The function Messages.Body is not required to use just operations
in Text_Operations, it could use the primitives provided by Text_Operations
to pull apart the Text object and operate on components of the Text object,
such as a looping through the lines to make a copy of the Message.  Now in
this example, you wouldn't need additional withs to access type String, so
such a violation of the Law of Demeter might be overlooked.  But picking
apart the date by calling Calendar would show up.

     In general, given the choice, you should extend the interface to
package Messages by operations that deal directly with components, but be
careful about giving/making the user of the abstraction continue to
decompose it.   Operations should be high level and meaningful in the at
the same level of abstraction as the rest of the package.

                                        Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...