From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fac41,2c6139ce13be9980 X-Google-Attributes: gidfac41,public X-Google-Thread: 103376,3d3f20d31be1c33a X-Google-Attributes: gid103376,public X-Google-Thread: 1108a1,2c6139ce13be9980 X-Google-Attributes: gid1108a1,public X-Google-Thread: f43e6,2c6139ce13be9980 X-Google-Attributes: gidf43e6,public From: mheaney@ni.net (Matthew Heaney) Subject: Re: Separation of IF and Imp: process issue? Date: 1997/09/04 Message-ID: #1/1 X-Deja-AN: 269958751 References: <33E9ADE9.4709@flash.net> Organization: Estormza Software Newsgroups: comp.object,comp.software-eng,comp.lang.ada,comp.lang.eiffel Date: 1997-09-04T00:00:00+00:00 List-Id: In article , doylep@ecf.toronto.edu (Patrick Doyle) wrote: >>But this is not quite the same thing as the relationship between a module >>specification and its body. > > Ok, I'll boil my position down into one question: What does a separate >interface file do for a class that an abstract superclass can't do? True, an abstract superclass would specify the characteristics common to every subclass in that derivation tree, but an interface file ("package spec") describes the characteristics of a specific class. For example, given an abstract queue superclass: generic type Queue_Item is private; package Queues_G is type Root_Queue is abstract tagged private; procedure Add (Item : in Queue_Item; To : in out Root_Queue) is abstract; end; Now let's subclass, and create a balking queue: generic packages Queues_G.Balking_G is type Balking_Queue is new Root_Queue with private; procedure Add (Item : in Queue_Item; To : in out Balking_Queue); procedure Remove_Item (From : in out Balking_Queue; At_The_Position : in Positive); private type Balking_Queue is ...; end; The module interface is separate from its body, and can therefore be configured separately. Any changes to the spec have to be coordinated with the clients of the package. Suppose I wanted to change the position from Positive to Natural, because for some strange reason I decide I'd rather count starting from 0. This change can't be made indiscriminately, because clients already depend on certain behavior (count starting from 1). A change to the body can of course be made painlessly, because no one can depend on what's in the body. But the spec is a contract that can't be changed without notifying all parties involved. If one only had a module body, without a separate spec, then it would look like generic packages Queues_G.Balking_G is type Balking_Queue is new Root_Queue with private; procedure Add (Item : in Queue_Item; To : in out Balking_Queue) is begin To.Items := Item & To.Items; To.Length := To.Length + 1; end; procedure Remove_Item (From : in out Balking_Queue; At_The_Position : in Positive) is Node : Item_Node_Access := To.Items; begin for Index in Positive range 2 .. At_The_Position loop Node := Node.Next; end loop; end; private type Balking_Queue is ...; end; But now it's not so obvious how to separate the changes made to the bodies of the operations from the contract itself. Just think how much simpler it is using existing configuration management technology to freeze a specification, if it's a different text file from the text file containing the body. By putting spec and body together, the configuration management tool has to be smart enough to determine which part is the specification of the routines and which is the body - much more sophistication than a CM tool that need only treat everything as mere text. The change affects only the Balking_Queue subclass - not the abstract superclass. That's why I'm not clear how freezing the spec of the root type really solves anything. Yes, clients who manipulate classwide queue objects, ie procedure Op (Queue : in out Root_Queue'Class) is ... would have a guarantee about the characteristics available for objects of type Root_Queue'Class, if the abstract superclass were frozen, but I'm talking about a client who depends on behavior specific to a balking queue: The_Queue : Balking_Queue; ... Remove_Item (From => The_Queue, At_The_Position => N); It just seems simpler to have a different text file for the spec. That way changes to the body can be made with impunity, and the compiler will check that you haven't changed the contract in any way (because the contract is kept separate). There are probably some Eiffel subtleties that I've missed, but I hope I've been able to explicate the Ada philosophy with respect to separation of spec and body. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant (818) 985-1271