123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- .nr chapter 0
- .chapter "Introduction"
- .section "Motivation"
- In the development of our understanding of complex phenomena,
- the most powerful tool available to enhance our comprehension is
- abstraction. Abstraction arises from the recognition of similarities
- between certain objects or processes, and the decision to
- concentrate on these correspondences and to ignore, for the
- present, their differences [Hoare 72]. In focusing on similarities,
- one tends to regard them as fundamental and intrinsic, and to view
- the differences as trivial.
- Abstraction from all nonessentials can uncover the kernel of
- a subject matter and be of great aid in those cases where a
- decisive role is played by the properties picked out and
- preserved by the abstraction. But, chiefly, what we desire in an
- abstraction is a mechanism which permits the expression of
- relevant details and the suppression of irrelevant details
- [Liskov and Zilles 74]. In this manner, a good abstraction allows ont to
- concenetrate on the essentials of a task without regard to unimportant factors.
- One of the earliest recognized and most useful aids to
- abstraction in programming is the self-contained subroutine or
- procedure. Procedures appeared as early as 1945 in Zuse's
- programming language, Plancalculus [Knuth 76]. Besides, early
- developers of programming languages recognized the utility of the
- concept of a procedure. Curry, in 1950, described the advantages
- of including procedures in the programming languages being
- developed at that time by pointing out that the decomposition
- mechanism provided by a procedure would allow keener insight into
- a problem by permitting consideration of its separate, distinct
- parts [Curry 50].
- The existence of procedures goes quite far toward capturing
- the meaning of abstraction [Liskov and Zilles 74]. At the point
- of its invocation, a procedure may be treated as a "black box",
- which performs a specific function by means of an unprescribed
- algorithm. Thus, at the level of its invocation, a procedure
- separates the relevant detail of what it accomplishes from the
- irrelevant detail of how it is implemented. Furthermore, at the
- level of its implementation, a procedure facilitates understanding
- of how it accomplishes its task by freeing the programmer from
- considering why it is invoked.
- However, procedures alone do not provide a sufficiently rich
- vocabulary of abstractions [Liskov and Zilles 75]. Procedures,
- while well suited to the description of abstract processes or
- events, do not accommodate the description of abstract objects. To
- alleviate this problem the concept of a data abstraction was
- introduced. This comprises a group of related functions or
- operations which act upon a particular class of objects with the
- constraint that objects in this class can only be observed or
- modified by the application of its related operations [Liskov and
- Zilles 75].
- A typical example of a data abstraction is a "push down
- stack". Here, the class of objects consists of all possible stacks
- and the collection of related operations includes the usual stack
- operations, like push and pop, and an operation to create new
- stacks.
- A data abstraction provides the same aids to abstraction as a
- procedure and allows one to separate the implementation details of
- a data object from its behavior. At the level of its use or
- invocation, the data abstraction isolates the attributes that
- specify the names and define the abstract meaning of the associated
- operations. At the level of its implementation, the data
- abstraction isolates the attributes that describe the representation
- of objects and the implementation of the operations that
- act upon these objects. Though these different attributes of use
- and implementation are, in practice, highly interdependent, they
- represent logically independent concepts [Guttag 75].
- My main concern is the first group of attributes which deal
- with the specification of the data abstraction. Specification is
- important because it describes the abstract object which has been
- conceived in someone's mind. It can be used as a communication
- medium among designers and implementors to insure that an
- implementor understands the designer's intentions about the data
- abstraction he is coding [Liskov and Zilles 75].
- Moreover, if a formal specification technique, one with
- an explicitly and precisely defined syntax and semantics, is used,
- even further benefits can be derived. Formal specifications can be
- studied mathematically so that questions, such as the equivalence
- of two different specifications, may be posed and rigorously
- answered. Also, formal specifications can serve as the basis for
- proofs of correctness of programs. If a programming language's
- semantics are defined formally [Marcotty`76], properties of a
- program written in this language can be formally proved. The
- correctness of the program can then be proved by establishing the
- equivalence of these properties and the specification. Finally,
- formal specifications can be meaningfully processed by a computer
- [Liskov and Zilles 75], [Liskov and Berzins 76]. Since this processing
- can be done in advance of implementation, it can provide
- design and configuration guidelines during program development.
- .section "A Prelude to The Parnas Module Specification Technique"
- The information contained in the specification of a data
- abstraction can de divided into a syntactic part and a semantic
- part [Liskov and Zilles 75]. The syntactic part provides a vocabulary
- of terms or symbols which are used by the semantic part to
- express the actual meaning or behavior of the data abstraction.
- Two different approaches are used in capturing this meaning;
- either an explicit, abstract model is supplied for the class of
- objects and its associated operations are defined in terms of this
- model, or the class of objects is defined implicitly via descriptions
- of the operations [Liskov and Zilles 75].
- Parnas [Parnas 72b] has developed a technique and notation,
- called a Parnas module, for writing specifications based on the
- implicit approach. His specification scheme was devised with the
- following goals in mind [Parnas 72b]:
- .nofill_list
- 1) The specification must provide to the intended user
- all the information that he will need to correctly use
- the object specified, and nothing more.
- .next
- 2) The specification must provide to the implementor all
- the information about the intended use of the object
- specified that he needs to implement the specification,
- and no additional information.
- .next
- 3) The specification should discuss the object specified
- in the terms normally used by user and implementor alike
- rather than in some other area of discourse.
- .end_list
- When using the Parnas technique, each data object is viewed
- as the state of an abstract (and not necessarily finite) state
- machine and, in the Parnas module, this state set is implicitly
- defined. The basic idea is to separate the operations of the data
- abstraction into two distinct groups; those which do not change
- the state but allow some aspect of the state to be observed, the
- value returning or V-functions, and those which change the state,
- the operation or O-functions. The specifications are then written
- by stating the effect of each O-function on the result of each
- V-function. This implicitly defines the smallest set of states
- necessary to distinguish the variations in the results of the
- V-functions [Liskov and Zilles 75].
- A problem with this approach is that certain O-functions may
- have delayed effects on the V-functions. In other words, some
- property of the state will be observed by a V-function only after
- some O-function has been used. For example, consider a push down
- stack with the operations PUSH, POP and TOP. PUSH has a delayed
- effect on TOP in the sense that after a new element has been
- pushed on the stack, the former top of the stack element is no
- longer observable by TOP but it will be if POP is used.
- Parnas used an informal language to express these delayed
- effects [Parnas 72b,75]. In his specifications, he included a
- section, called Module Properties, for describing delayed effects
- in English, at times interlaced with simple mathematical formulae
- [Parnas 75]. For example, to specify the interaction of push and
- pop on a stack, Parnas used the phrase "The sequence PUSH(a);POP
- has no net effect if no error calls occur" [Parnas 75].
- One method to formally describe delayed effects is to introduce
- hidden V-functions to represent aspects of the state which
- are not immediately observable. For example, in the specification of a push down stack,
- one could introduce a hidden V-function to store the former top of the stack element.
- This approach has been followed
- by researchers at the Stanford Research Institute [Robinson
- 75a],[Spitzen 76]. However, their main concern with Parnas modules
- is their use in a general methodology for the design, implementation
- and proof of large software systems [Robinson 75b],
- [Neumann 74]. With this goal in mind, they have designed a
- specification language, called SPECIAL, for describing Parnas
- modules [Roubine 76]. But, no formal semantics have been provided
- for SPECIAL.
- An example of a Parnas module specification using hidden
- V-functions is given below in figure 1. Here, the data abstraction
- defined is a bounded integer stack with the following operations;
- .ls 1
- .nofill_list
- push pushes an integer on a stack
- .next
- pop pops the top of a stack
- .next
- top returns the integer on top of a stack
- .next
- depth returns the number of elements in a stack
- .end_list
- .begin_figure "Bounded Integer Stack"
- .ls 1
- .sp 2
- bounded_stack = 1Parnas_module is* push, pop, top, depth
- depth = 1non-derived V-function*( ) 1returns* integer
- 1Appl. Cond.: true*
- 1Initial Value*: 0
- 1end* depth
- stack = 1hidden V-function*(i:integer) 1returns* integer
- 1Appl. Cond.: true*
- 1Initial Value*: undefined
- 1end* stack
- top = 1derived V-function*( ) 1returns* integer
- 1Appl. Cond.*: ~(depth = 0)
- 1Derivation*: top = stack(depth)
- 1end* top
- pop = 1O-function*( )
- 1Appl. Cond.*: ~(depth = 0)
- 1Effects*: 'depth' = depth - 1
- 1end* pop
- push = 1O-function*(a:integer)
- 1Appl. Cond.*: depth < 100
- 1Effects*: 'depth' = depth + 1
- 'stack'(depth + 1) = a
- 1end* push
- 1end* bounded_stack
- .finish_figure
- A Parnas module specification consists of two parts; an
- interface description and a collection of function definitions.
- The interface description of a Parnas module provides a very
- brief description of the interface which the module presents to
- the outside environment. It consists of the name of the data
- abstraction being specified by the module and a list of the
- functions that users of the data abstraction may employ;
- bounded_stack = Parnas_module is push,pop,top,depth
- The name specified in the interface description, besides
- being the name of the data abstraction defined by the module, is
- also called, following [Guttag 75], the type of interest. Users
- of a particular Parnas module specification view objects of the
- type of interest as indivisible, non-decomposable entities.
- However, inside the module, objects are viewed as decomposable
- states of the abstract machine implicitly defined by the module.
- Notice that stack is not included in the interface description.
- This means it is hidden from users of the module and
- can not be accessed by them. Its inclusion in the body of the
- module is necessary to describe the delayed effects discussed
- above.
- The body of a Parnas module consists of the function
- definitions which specify the actions allowed on the type of
- interest. A function definition must be given for every action
- named in the interface description.
- There are two kinds of functions defined in the body of a
- Parnas module, V-functions and O-functions.
- A V-function is defined by first writing its name and then
- its mapping description;
- depth = V-function( ) returns integer
- The mapping description specifies the type of the function's
- parameters and the type of the values it returns. Note that
- certain V-functions such as depth and top require no parameters.
- Furthermore, the mapping description states which particular type
- of V-function, derived, non-derived or hidden, is being defined.
- A non-derived or hidden V-function is a primitive, intrinsic
- aspect of the type of interest. However, hidden V-functions
- differ from non-derived V-functions in that they can not be
- accessed by users of the type of interest. Furthermore, they may
- not appear in a module's interface description. In contrast,
- derived V-functions are not primitive aspects of the type of
- interest but are defined in terms of the other V-functions of the
- module.
- After the mapping description, the applicability condition
- of a V-function is defined. This is a Boolean expression which
- governs when a call of the V-function succeeds. This expression
- may not contain any derived V-functions and must evaluate to true
- for any call to succeed. Hidden V-functions are always applicable
- (their applicability condition must always be defined as true).
- The applicability condition may constrain a V-function so
- that it is only a partial function; i.e. it is not defined for
- all elements of its domain. When a V-function is passed a set of
- arguments for which it is not defined, an error condition is
- raised telling the user what has occurred. However, how the error
- condition is handled is viewed here as the responsibility of the
- user. The Parnas module only specifies when an error condition is
- raised.
- Finally, a section which determines the specific values
- returned by a V-function is given. For a non-derived or hidden
- V-function, this is the initial value section which specifies the
- value returned by calls of this particular V-function in the
- initial state of the abstract machine implicitly defined by the
- module. The initial value is the basis for the values returned by
- the V-function in the other states of the abstract machine.
- .keep
- For derived V-functions, a derivation section is given.
- Derivation: top=stack(depth)
- ..
- .end_keep
- This section defines the function in terms of the other
- non-derived and hidden V-functions of the module.
- An O-function is specified by first defining its name and
- mapping description
- push = O-function(a;integer)
- and then specifying its applicability condition. As with
- V-functions, a call of an O-function only succeeds if its
- applicability condition is satisfied, otherwise an error
- condition is raised. O-functions do not return any values. They
- only change the state of the abstract machine implicitly defined
- by the module.
- Now recall that objects of the type of interest are viewed
- inside the module as states of this abstract machine. This point
- helps to explain the interpretation of the quotes around the
- V-functions in an O-function's applicability condition and
- effects section. These quotes are used to represent the result
- returned by the V-function in the state of the machine before
- completion of an O-function call. An unquoted V-function
- represents the function in the new state produced after
- completion of the call. This new state is defined by the
- equations in an O-function's effects section which redefine the
- mappings of certain V-functions in terms of the previous state.
- Only non-derived or hidden V-functions may appear in an equation
- in an O-function's effects section. Furthermore, non-derived or
- hidden V-functions which do not appear on the left hand side of
- any equation remain unchanged in the new state.
- Together, the non-derived V-functions, hidden V-functions and
- the O-functions implicitly define the state set of a Parnas
- module. Note that since the derived V-functions are defined in
- terms of the other V-functions, they are not needed to define
- this state set. Their main use is to allow users of the module
- restricted access to the hidden V-functions. Thus, they help
- support Parnas's principle of information hiding [Parnas 72a].
|