                          The Eiffel/S Library 


   Copyright 

   Copyright SiG Computer GmbH, 1991.  All rights reserved. No part of 
   this document may be reproduced in any form without written consent 
   of the publisher. 


   Eiffel is a registered trademark of NICE 

   Authors 

   Michael Schweitzer, Lambert Strether 



Chapter 1 
=========


Introduction 


1.1 The objectives 

   Writing  reusable  libraries  is  a  demanding  and time--consuming 
   undertaking. The classes in such  libraries should ideally have the 
   following properties. They should be: 

 * Easy and intuitive to use. 

 * Readily applicable in widely varying software systems. 

 * As efficient as current technology permits. 

 * Thoroughly tested and reliable. 

 * Well documented. 

 * Platform--independent. 


     Some  of  these criteria  are  hard to  meet  simultaneously. For 
   example, it can happen  that the most general  algorithm is not the 
   most efficient in many special but frequently encountered cases. 

   Ease of use  has several aspects. One  of these has  to do with the 
   sheer number of classes. If there  are many very similar classes in 
   a library, it  can be difficult  for the software  designer to pick 
   the right class for the job  at hand. It is generally preferable to 
   have a  smaller number  of nearly  orthogonal classes,  each with a 
   clearly defined role and each doing its job in an optimal fashion. 

   Another  aspect of  ease  of use  has  to do  with  the conventions 
   followed. Routines  with analogous  semantics should  have the same 
   name and as far  as possible the same  ordering of their arguments. 
   For example in all the different kinds of container classes (lists, 
   tables, stacks, queues) the routine for  adding a new object to the 
   container should  always be  called add. Then  the user  of such a 
   class does  not need  to stop  to think  about what  the routine is 
   called or worse still look it up in the manual. 

   Sometimes such analogies reach further than one might at first have 
   expected. In  the Eiffel/S libraries,  for example, the  idea of an 
   iterator  is all--pervasive.  Iterators  turn up  in  the container 
   classes, in  the graph  classes and  even in  the pattern matchers. 
   These iterators are always used in  the same way --- the same idiom 
   in the most varied situations. 

   The characteristic of wide applicability of a class is particularly 
   difficult to achieve. The classes one develops in connection with a 
   particular project tend to be tailored to the special needs of that 
   project. If  they are  to be  reused in  a later  project they will 
   often  need  to  be  reworked. The  writer  of  a  general library, 
   however, must try to imagine a wide variety of applications for his 
   classes and to form them so that they can be readily applied in all 
   these situations. 

   Seldom is  the goal of  wide applicability achieved  right from the 
   start. Only  long experience  with a  class or  cluster will reveal 
   where one has made assumptions that are too restrictive. 

   Achieving maximum efficiency  requires on the  one hand familiarity 
   with  the  theoretical  literature in  the  application  area being 
   implemented  and  on  the other  hand  experimentation  with actual 
   implementations. However, as we remarked above, the wish to achieve 
   optimal  efficiency  is often  complicated  by the  aim  to achieve 
   greatest possible generality. Sometimes  algorithm A is much better 
   in situation 1 and algorithm B  is superior in situation 2. In such 
   cases it may be best after  all to provide two similar classes, one 
   encapsulating   algorithm  A   and  the  other   algorithm  B.  The 
   documentation must then make it clear which class is appropriate in 
   which situations. 

   The documentation has many more duties than the one just mentioned. 

 * Listing the features of a class with their pre-- and postconditions 
   is only the beginning. 

 * The documentation  must also give  clear guidelines for  the use of 
   the  classes, showing  typical  application situations  and typical 
   idioms for use. 

 * Wherever possible  it must  state clearly  what the  space and time 
   requirements of the routines are  so that the software designer can 
   decide whether the classes will meet his or her needs. 

 * If the algorithms  employed are not obvious  or trivial they should 
   probably be described  or literature cited  where information about 
   them can be found. 

 * In cases where the  inheritance structure of a  group of classes is 
   non--trivial it should be described. Guidelines should be given for 
   creating   new  classes  that  can  fit  smoothly  into  the  given 
   structure. 

     Finally  there  is  the  matter  of  platform--independence. This 
   requirement  sometimes  stands  in  conflict  with  the  demand for 
   maximum efficiency.  If one  makes use  of special  properties of a 
   particular   platform  one  can   often  make  software  work  more 
   efficiently. 

   The library designer  should, however, resist  this temptation. All 
   such  specialization  drastically reduces  the  reusability  of the 
   resulting   libraries.   Even  assumptions   about  the  underlying 
   operating system should be avoided or  buried in a low layer of the 
   library software. 

   This last point  has cost the  authors of the  Eiffel/S libraries a 
   great  deal  of  thought  and  effort.  It  is  not  easy  to  find 
   abstractions  that  will  be implementable  on  a  wide  variety of 
   operating systems. But if one succeeds, the reward for the users of 
   the library is considerable:  software that is immediately portable 
   to a large variety of platforms. 


   In developing the Eiffel/S libraries we have endevoured to keep the 
   above  goals  continually in  mind.  We  trust the  users  of these 
   libraries will be  able to confirm  that we at  least came close to 
   reaching them. 




1.2 The conventions 
===================

   In  documenting  the  classes  in  the  Eiffel/S  clusters  we have 
   followed certain conventions. 

 * In diagrams and section headings  the names of deferred classes are 
   marked with an asterisk. 

 * In classifying the features of a class we use the four designations 
   creation  procedure, procedure,  function  and state.  The first 
   three will be familiar  to anyone who knows  Eiffel. The term state 
   refers  equally well  to  an attribute  and  to a  function without 
   arguments. For the  user of a  class there is  really no difference 
   between  attributes and  functions without  arguments, so  it seems 
   best to use a terminology that does not distinguish between them. 



More or less informal description of the features. 

   In classes  with many features  or with  features requiring complex 
   explanations we use the following general scheme. 


   doomsday (n : INTEGER) : BOOLEAN 


Definition 

   True if and only if the end of the world is expected within n days. 


Preconditions 

   n >= 0 and then n <= Millenium 


Postconditions 

   None 


Complexity 

   Extreme 


Status 

   Effective function 


Remarks 

   The author of this function gives no guarantee for its accuracy. 


   Some of  the headings  in this scheme  may be  omitted for features 
   where they do not seem necessary or appropriate. 

 * The documentation  for each feature  should define  as precisely as 
   possible what the procedure represents or does. In addition it must 
   state clearly all the conditions the  user of the feature must meet 
   in order to use the feature successfully. In the formal description 
   of a feature  the definition section  and the preconditions section 
   are responsible for meeting these demands. 


   We  only list  the  postconditions of  a  routine when  they seemed 
   particularly significant. In most cases the precise definition of a 
   feature  says  more  fully  what  the  feature  represents,  so the 
   postconditions would merely be redundant. 

 * When a class  has a creation  procedure it is  mentioned before all 
   other features. Otherwise the features are listed alphabetically. 

 * The authors of  these libraries have  taken great care  to follow a 
   uniform  naming  convention  for features.  The  names  of features 
   should emphasize the analogies between classes. 


   For  this reason  the routine  for  inserting a  new object  into a 
   container class always is called add  --- even in cases where there 
   is a  more traditional  name such as  push for  stacks. This naming 
   convention may seem unusual at first, but the user will soon notice 
   how pleasant it  is never to have  to think about  what the name of 
   the routine for inserting elements is: it's always add. 


   For  the same  reason the  routine  for removing  an object  from a 
   container is always called  remove --- and not  pop for stacks. The 
   routine for looking for an element  in a container is always called 
   search. 


   For similar  reasons whenever a  data abstraction  shows a behavior 
   analogous to  that of iterators  we use  the iterator nomenclature: 
   first and forth resp. last and back. 


   The creation procedure of every class that has one is called make. 

 * The matter of class names is  a bit thornier. In principle we would 
   have liked to  choose class names  that say clearly  what the class 
   represents.  However, class  names have  something  to do  with the 
   names  of the  files containing  the  class text  and unfortunately 
   operating systems  often have  restrictions on  the length  of file 
   names. In particular MS--DOS limits the portion before the dot to 8 
   characters. 


   Theoretically  one can  give  the file  containing  a class  text a 
   different name from that of the  class and tell the Eiffel compiler 
   about  this in  the program  description  file. If  we do  this for 
   library classes, however, then every  user of these classes will be 
   forced to list the  names of their files in  all his or her program 
   description files --- very tedious. 


   Therefore we  have decided that  the names of  library classes must 
   coincide with the  names of their  files and these  may not be more 
   than  8 characters  long. That  often leads  to very  cryptic class 
   names  like  COLCTN  for  collections  or  TW_ITER  for  two  way 
   iterators. We regret this but see no acceptable alternative. 

 * In every case where the information  is nontrivial we report on the 
   complexity of  a feature:  time and  space. In  describing the time 
   complexity we  generally use  the traditional  big--O notation. The 
   reader not familiar with this notation  is referred to Ch. 1 of clr 
   . 


   To   describe  the  space  requirements  in  a  way  more  or  less 
   independent   of  the  underlying  machine  we  use  the  following 
   notation. 

   B = size of a BOOLEAN object in  bytes I = size of a INTEGER object 
   in bytes R = size of a REAL object in bytes P = size of a reference 
   (pointer) in bytes 

   In addition  we give  in parentheses  the size  in bytes  under the 
   assumption of the following (typical) values for B, I, R and P. 

   B = 4 (taking alignment into account!) I = 4 R = 8 P = 4 

   This should give at least a  rough idea of the space costs incurred 
   by a particular routine or object. 

 * In some cases the classes of  a cluster participate in a nontrivial 
   inheritance structure.  This is  partly done  to make  it easier to 
   extend the cluster with  further classes if needed.  If the user is 
   to be in a position to create such extensions himself, however, the 
   structure must be clearly explained. So  in some chapters we have a 
   section  ``Creating  a  new  ...  class''.  This  section  contains 
   guidelines for experienced programmers who want to extend a cluster 
   with classes of their own that fit into the given structure. 

