18 Global objects and constants ocalknowledge is not always enouh components of a sofware system may need to access global information.It is easy to think of examples:a shared value,such as the size of available memory;an error window,to which all the components of an interactive system must be able to output messages;the gateway to a database or network In classical approaches,it is not difficult to provide for global objects;you just declare them as global variables,owned by the main program.In the modular style of design made possible by object-oriented techniques,there is neither a main program nor global variables.But even if our software texts do not include global variables our software executions may still need to share objects. Such global objects pose a challenge to the method.Object technology is all about decentralization,all about modularity,all about autonomy.It has developed from the beginning of this presentation as a war of independence for the modules,each fighting for its freedom from the excesses of central authority.In fact,there is no central authority any more.How then do we satisfy the need for common institutions?In other words,how do we allow components to share data in a simple way,without jeopardizing their autonomy, flexibility and reusability? It will not work,of course,to pass shared objects as arguments to the modules that need them.This would soon become clumsy if too many components need them.Besides, argument passing assumes that one module owns the value and then passes it on to others; in the case of a truly shared value no one module can claim ownership. To find a better answer we will start from a well-known notion,which we need in object-oriented software construction just as much as we did in more traditional approaches:constants.What is,after all,a constant such as Pi if not a simple object shared by many modules?Generalizing this notion to more complex objects will provide a first step towards fully general constant and shared objects. 18.1 CONSTANTS OF BASIC TYPES Let us start with a simple notation to denote constant values
18 Global objects and constants Local knowledge is not always enough; components of a software system may need to access global information. It is easy to think of examples: a shared value, such as the size of available memory; an error window, to which all the components of an interactive system must be able to output messages; the gateway to a database or network. In classical approaches, it is not difficult to provide for global objects; you just declare them as global variables, owned by the main program. In the modular style of design made possible by object-oriented techniques, there is neither a main program nor global variables. But even if our software texts do not include global variables our software executions may still need to share objects. Such global objects pose a challenge to the method. Object technology is all about decentralization, all about modularity, all about autonomy. It has developed from the beginning of this presentation as a war of independence for the modules, each fighting for its freedom from the excesses of central authority. In fact, there is no central authority any more. How then do we satisfy the need for common institutions? In other words, how do we allow components to share data in a simple way, without jeopardizing their autonomy, flexibility and reusability? It will not work, of course, to pass shared objects as arguments to the modules that need them. This would soon become clumsy if too many components need them. Besides, argument passing assumes that one module owns the value and then passes it on to others; in the case of a truly shared value no one module can claim ownership. To find a better answer we will start from a well-known notion, which we need in object-oriented software construction just as much as we did in more traditional approaches: constants. What is, after all, a constant such as Pi if not a simple object shared by many modules? Generalizing this notion to more complex objects will provide a first step towards fully general constant and shared objects. 18.1 CONSTANTS OF BASIC TYPES Let us start with a simple notation to denote constant values
644 GLOBAL OBJECTS AND CONSTANTS $18.1 Using symbolic constants A rule of software style,the Symbolic Constant principle,states that when an algorithm "Mamifest and sym refers to a certain value-a number,a character,a string...-it should almost never use bolic constants". it directly.Instead,a declaration should associate a name with the value,so that the page 884.See also “odular continu- algorithm can use the name(known as a symbolic constant)rather than the value(known ity"page 44. as a manifest constant).Two reasons justify this principle: Readability:someone who reads your software may not understand what the value 50 is doing in a certain algorithm;if instead you use the symbolic constant US states count everything is clear. Extendibility:in practice,with a few exceptions (such as the value of n,unlikely to change soon),the only constant thing about constants is change.To update the value of a constant it suffices,if you have been using symbolic constants,to change one declaration.This is much nicer than having to chase throughout the software for all the places that may have relied on the earlier value. The principle permits using manifest constants(hence the word"almost"above)for zero elements of various operations,as in a loop from i:=/until i>n...iterating over the elements of an array whose numbering follows the default convention of starting at 1. (But n should be symbolic,not manifest.) Although few software developers apply the Symbolic Constant principle as systematically as they should,the benefits of declaring a symbolic constant are well worth the small extra effort.So we need a clear and simple way of defining symbolic constants in an O-O framework. Constant attributes A symbolic constant,like everything else,will be defined in a class.We will simply treat a constant value as an attribute which happens to have a fixed value,the same for all instances of the class. For the syntax,we can reuse the keyword is which already serves to introduce routines;only here it will be followed by a value of the appropriate type,rather than by an algorithm.The following examples include one for each of the basic types /NTEGER, BOOLEAN,REAL and CHARACTER: Zero:INTEGER is 0 Ok:BOOLEAN is True Pi:REAL is3.1415926524 Backslash:CHARACTER is' Backslash is of type CHARACTER,its value a single character.Constants of string type, denoting character strings of arbitrary length,will be discussed below. As these examples illustrate,the recommended style convention for names of constant attributes is to start with a capital letter,with the rest in lower case. A descendant may not redefine the value of a constant attribute
644 GLOBAL OBJECTS AND CONSTANTS §18.1 Using symbolic constants A rule of software style, the Symbolic Constant principle, states that when an algorithm refers to a certain value — a number, a character, a string… — it should almost never use it directly. Instead, a declaration should associate a name with the value, so that the algorithm can use the name (known as a symbolic constant) rather than the value (known as a manifest constant). Two reasons justify this principle: • Readability: someone who reads your software may not understand what the value 50 is doing in a certain algorithm; if instead you use the symbolic constant US_states_ count everything is clear. • Extendibility: in practice, with a few exceptions (such as the value of π, unlikely to change soon), the only constant thing about constants is change. To update the value of a constant it suffices, if you have been using symbolic constants, to change one declaration. This is much nicer than having to chase throughout the software for all the places that may have relied on the earlier value. The principle permits using manifest constants (hence the word “almost” above) for zero elements of various operations, as in a loop from i := 1 until i > n … iterating over the elements of an array whose numbering follows the default convention of starting at 1. (But n should be symbolic, not manifest.) Although few software developers apply the Symbolic Constant principle as systematically as they should, the benefits of declaring a symbolic constant are well worth the small extra effort. So we need a clear and simple way of defining symbolic constants in an O-O framework. Constant attributes A symbolic constant, like everything else, will be defined in a class.We will simply treat a constant value as an attribute which happens to have a fixed value, the same for all instances of the class. For the syntax, we can reuse the keyword is which already serves to introduce routines; only here it will be followed by a value of the appropriate type, rather than by an algorithm. The following examples include one for each of the basic types INTEGER, BOOLEAN, REAL and CHARACTER: Zero: INTEGER is 0 Ok: BOOLEAN is True Pi: REAL is 3.1415926524 Backslash: CHARACTER is '\' Backslash is of type CHARACTER, its value a single character. Constants of string type, denoting character strings of arbitrary length, will be discussed below. As these examples illustrate, the recommended style convention for names of constant attributes is to start with a capital letter, with the rest in lower case. A descendant may not redefine the value of a constant attribute. “Manifest and symbolic constants”, page 884. See also “Modular continuity”, page 44
$18.2 USE OF CONSTANTS 645 Like other attributes,constant attributes are either exported or secret;if they are exported,clients of the class may access them through feature calls.So if C is the class containing the above declarations and x,declared of type C,has a non-void value,then x.Backslash denotes the backslash character. Unlike variable attributes,constant attributes do not occupy any space at run time in instances of the class.So there is no run-time penalty for adding as many constant attributes as you need. 18.2 USE OF CONSTANTS Here is an example showing how clients may use constant attributes defined in a class: class FILE feature error code:INTEGER: --Variable attribute Ok:INTEGER is 0 Open_error:INTEGER is 1 open (file name:STRING)is --Open file of name file name --and associate it with current file object do error code:=Ok if“Something went wrong”then error code:=Open error end end ..Other features... end A client may call open and compare the resulting error code to any of the constants to test how the operation went: 大FILE,… f.open if f.error code =f.Open error then “Appropriate action else end Often,however,a group of constants is needed without being attached to any particular object.For example,a system performing physics computations may use some numerical constants;or a text editor may need character constants describing the character
§18.2 USE OF CONSTANTS 645 Like other attributes, constant attributes are either exported or secret; if they are exported, clients of the class may access them through feature calls. So if C is the class containing the above declarations and x, declared of type C, has a non-void value, then x ● Backslash denotes the backslash character. Unlike variable attributes, constant attributes do not occupy any space at run time in instances of the class. So there is no run-time penalty for adding as many constant attributes as you need. 18.2 USE OF CONSTANTS Here is an example showing how clients may use constant attributes defined in a class: class FILE feature error_code: INTEGER; -- Variable attribute Ok: INTEGER is 0 Open_error: INTEGER is 1 … open (file_name: STRING) is -- Open file of name file_name -- and associate it with current file object do error_code := Ok … if “Something went wrong” then error_code := Open_error end end … Other features … end A client may call open and compare the resulting error code to any of the constants to test how the operation went: f: FILE; … f ● open if f ● error_code = f ● Open_error then “Appropriate action” else … end Often, however, a group of constants is needed without being attached to any particular object. For example, a system performing physics computations may use some numerical constants; or a text editor may need character constants describing the character
646 GLOBAL OBJECTS AND CONSTANTS $18.3 keys associated with various commands.In such a case,the constants will still be grouped in a class(where else could they be?),but there will not be any instances of that class;it is simply used as parent for the classes that need to access the constants,as in class EDITOR CONSTANTS feature Insert:CHARACTER is'i Delete:CHARACTER is'd';--etc. end elass SOME CLASS FOR THE EDITOR inherit EDITOR CONSTANTS ..Other possible parents .. feature.… ..Routines of the class have access to the constants declared in EDITOR CONSTANTS... end A class such as EDITOR CONSTANTS is used only to host a group of related See"FACILITY constants,and its role as an "abstract data type implementation"(our working definition INHERITANCE". of the notion of class)is less obvious than in earlier examples.But it definitely serves a 24.9,page847. useful purpose.We will examine its theoretical justification in a later chapter. The scheme shown would not work without multiple inheritance,since SOME CLASS FOR THE ED/TOR may need other parents,either for access to other constants or for more standard uses of inheritance. 18.3 CONSTANTS OF CLASS TYPES Symbolic constants,allowing you to use identifiers to denote certain constant values,are not just use ful for predefined types such as /NTEGER;the need also arises for types that developers have defined,through classes.Here the solution is less obvious. Manifest constants are inappropriate for class types A typical example in which you may need to define a constant for a non-basic types is that of a class describing complex numbers: class COMPLEX creation make cartesian,make polar feature x,y:REAL --Real and imaginary parts
646 GLOBAL OBJECTS AND CONSTANTS §18.3 keys associated with various commands. In such a case, the constants will still be grouped in a class (where else could they be?), but there will not be any instances of that class; it is simply used as parent for the classes that need to access the constants, as in class EDITOR_CONSTANTS feature Insert: CHARACTER is 'i' Delete: CHARACTER is 'd'; -- etc. … end class SOME_CLASS_FOR_THE_EDITOR inherit EDITOR_CONSTANTS … Other possible parents … feature … … Routines of the class have access to the constants declared in EDITOR_CONSTANTS … end A class such as EDITOR_CONSTANTS is used only to host a group of related constants, and its role as an “abstract data type implementation” (our working definition of the notion of class) is less obvious than in earlier examples. But it definitely serves a useful purpose. We will examine its theoretical justification in a later chapter. The scheme shown would not work without multiple inheritance, since SOME_ CLASS_FOR_THE_EDITOR may need other parents, either for access to other constants or for more standard uses of inheritance. 18.3 CONSTANTS OF CLASS TYPES Symbolic constants, allowing you to use identifiers to denote certain constant values, are not just useful for predefined types such as INTEGER; the need also arises for types that developers have defined, through classes. Here the solution is less obvious. Manifest constants are inappropriate for class types A typical example in which you may need to define a constant for a non-basic types is that of a class describing complex numbers: class COMPLEX creation make_cartesian, make_polar feature x, y: REAL -- Real and imaginary parts See “FACILITY INHERITANCE”, 24.9, page 847
$18.3 CONSTANTS OF CLASS TYPES 647 make cartesian (a,b:REAL)is --Initialize with real part a,imaginary part b. do x:=a;y:=b end ..Other routines (x and y are the only attributes)... end You may want to define the complex number i,with real part 0 and imaginary part 1.The first idea that comes to mind is a manifest constant notation such as i:COMPLEX is "Expression specifying the complex number (0,1)" How can you write the expression after is?For simple types,the manifest constants were self-evident:345 is a constant of type integer,'4'of type character.But no such predefined notation is available for developer-defined class types. One could imagine a notation based on the attributes of the class;something like Not a retained nota- i:COMPLEX is COMPLEX (0.1 tion.For purposes of illustration only. But such an approach (although present in some O-O languages)is incompatible with the principles of modularity which serve as the basis for object technology.It would mean requiring clients of COMPLEX to describe constants in terms of the implementation. This breaks information hiding.You could not add an attribute,even a secret one,without invalidating client code;neither could you re-implement an attribute such as x as a function(to switch internally to a polar representation). Besides,how could you make sure that such manifest constants will satisfy the class invariant if there is one? This last remark opens the way to a correct solution.An earlier chapter noted that it is the responsibility of the creation procedures to make sure that every object satisfies the invariant immediately upon creation.Creating objects in any other way (apart from the safe companion mechanism,clone)would lead to error situations.So we should look for a mechanism that,rather than manifest objects in the above style,will rely on the usual technique for object creation. Once functions We may view a constant object as a function.For example i could be defined within class COMPLEX itself as i:COMPLEX is --Complex number with real part 0 and imaginary part I do !Result.make cartesian (0,1) end
§18.3 CONSTANTS OF CLASS TYPES 647 make_cartesian (a, b: REAL) is -- Initialize with real part a, imaginary part b. do x := a; y := b end … Other routines (x and y are the only attributes) … end You may want to define the complex number i, with real part 0 and imaginary part 1. The first idea that comes to mind is a manifest constant notation such as i: COMPLEX is “Expression specifying the complex number (0, 1)” How can you write the expression after is? For simple types, the manifest constants were self-evident: 345 is a constant of type integer, 'A' of type character. But no such predefined notation is available for developer-defined class types. One could imagine a notation based on the attributes of the class; something like i: COMPLEX is COMPLEX (0, 1) But such an approach (although present in some O-O languages) is incompatible with the principles of modularity which serve as the basis for object technology. It would mean requiring clients of COMPLEX to describe constants in terms of the implementation. This breaks information hiding. You could not add an attribute, even a secret one, without invalidating client code; neither could you re-implement an attribute such as x as a function (to switch internally to a polar representation). Besides, how could you make sure that such manifest constants will satisfy the class invariant if there is one? This last remark opens the way to a correct solution. An earlier chapter noted that it is the responsibility of the creation procedures to make sure that every object satisfies the invariant immediately upon creation. Creating objects in any other way (apart from the safe companion mechanism, clone) would lead to error situations. So we should look for a mechanism that, rather than manifest objects in the above style, will rely on the usual technique for object creation. Once functions We may view a constant object as a function. For example i could be defined within class COMPLEX itself as i: COMPLEX is -- Complex number with real part 0 and imaginary part 1 do !! Result ● make_cartesian (0, 1) end Not a retained notation. For purposes of illustration only