880 A SENSE OF STYLE $26.2 obscure rather than illuminate the text.Remember that every use of the feature will unambiguously indicate the class,as in partl.number where partl must have been declared with a certain type,PART or a descendant. For composite names,it is better to avoid the style,popularized by Smalltalk and also used in such libraries as the X Window System,of joining several words together and starting the internal ones with an upper-case letter,as in yearly Premium.Instead,separate components with underscores,as in yearly_premium.The use of internal upper-case letters is ugly;it conflicts with the conventions of ordinary language;and it leads to cryptic names,hence to possible errors (compare aLongAndRatherUnreadableldentifier with an even longer but perfectly clear choice of name). Sometimes,every instance ofa certain class contains a field representing an instance of another class.This suggests using the class name also as attribute name.You may for example have defined a class RATE and,in class ACCOUNT,need one attribute of type RATE,for which it seems natural to use the name rate-in lower case,according to the rules on letter case stated below.Although you should try to find a more specific name, you may,if this fails,just declare the feature as rate:RATE.The rules on identifier choice explicitly permit assigning the same name to a feature and a class.Avoid the style of prefixing the name with the,as in the rate,which only adds noise. Local entities and routine arguments The emphasis on clear,spelled-out names applies to features and classes.Local entities and arguments of a routine only have a local scope,so they do not need to be as evocative. Names that carry too much meaning might almost decrease the software's readability by giving undue weight to ancillary elements.So it is appropriate to declare local entities (here in routines of TWO WAY LIST in the Base libraries)as move (i:INTEGER)is --Move cursor i positions,or after if i is too large. local c:CURSOR;counter:INTEGER;p:like FIRST ELEMENT remove is --Remove current item;move cursor to right neighbor (of after if none). local succ,pred,removed:like first element If succ and pred had been features they would have been called successor and predecessor.It is also common to use the names new for a local entity representing a new object to be created by a routine,and other for an argument representing an object of the same type as the current one,as in the declaration for clone in GENERAL: frozen clone (other:GENERAL):like other is
880 A SENSE OF STYLE §26.2 obscure rather than illuminate the text. Remember that every use of the feature will unambiguously indicate the class, as in part1 ● number where part1 must have been declared with a certain type, PART or a descendant. For composite names, it is better to avoid the style, popularized by Smalltalk and also used in such libraries as the X Window System, of joining several words together and starting the internal ones with an upper-case letter, as in yearlyPremium. Instead, separate components with underscores, as in yearly_ premium. The use of internal upper-case letters is ugly; it conflicts with the conventions of ordinary language; and it leads to cryptic names, hence to possible errors (compare aLongAndRatherUnreadableIdentifier with an_even_longer_but_perfectly_clear_choice_of_name). Sometimes, every instance of a certain class contains a field representing an instance of another class. This suggests using the class name also as attribute name. You may for example have defined a class RATE and, in class ACCOUNT, need one attribute of type RATE, for which it seems natural to use the name rate — in lower case, according to the rules on letter case stated below. Although you should try to find a more specific name, you may, if this fails, just declare the feature as rate: RATE. The rules on identifier choice explicitly permit assigning the same name to a feature and a class. Avoid the style of prefixing the name with the, as in the_rate, which only adds noise. Local entities and routine arguments The emphasis on clear, spelled-out names applies to features and classes. Local entities and arguments of a routine only have a local scope, so they do not need to be as evocative. Names that carry too much meaning might almost decrease the software’s readability by giving undue weight to ancillary elements. So it is appropriate to declare local entities (here in routines of TWO_WAY_LIST in the Base libraries) as move (i: INTEGER) is -- Move cursor i positions, or after if i is too large. local c: CURSOR; counter: INTEGER; p: like FIRST_ELEMENT … remove is -- Remove current item; move cursor to right neighbor (of after if none). local succ, pred, removed: like first_element … If succ and pred had been features they would have been called successor and predecessor. It is also common to use the names new for a local entity representing a new object to be created by a routine, and other for an argument representing an object of the same type as the current one, as in the declaration for clone in GENERAL: frozen clone (other: GENERAL): like other is…
$26.2 CHOOSING THE RIGHT NAMES 881 Letter case Letter case is not significant in our notation,as it is too dangerous to let two almost identical identifiers denote different things.But strongly recommended guidelines help make class texts consistent and readable: Class names appear in all upper case:POINT,LINKED_LIST,PRICING_MODEL. Formal generic parameters too,usually with just one letter:G. Names of non-constant attributes,routines other than once functions,local entities and routine arguments appear in all lower case:balance,deposit,succ,i. Constant attributes have their first letter in upper case and the rest in lower case: Pi:INTEGER is 3.1415926524:Welcome message:STRING is "Welcome!".This applies to unique values,which are constant integers. The example of i The same convention applies to once functions,the equivalent of constants for non- was on page 648. basic types:Error window,lo.Our first example,the complex number i,remained in lower case for compatibility with mathematical conventions. This takes care of developer-chosen names.For reserved words,we distinguish two categories.Keywords such as do and class play a strictly syntactic role;they are written in lower case,and will appear in boldface (see below)in printed texts.A few reserved words are not keywords because they carry an associated semantics;written with an initial upper case since they are similar to constants,they include Current,Result,Precursor, True and False. Grammatical categories Precise rules also govern the grammatical category of the words from which identifiers are derived.In some languages,these rules can be applied without any hesitation;in English, as noted in an earlier chapter,they will leave more flexibility. See the Class Name The rule for class names has already been given:you should always use a noun,as rule on page 727. in ACCOUNT,possibly qualified as in LONG TERM SAVINGS ACCOUNT,except for the case of deferred classes describing a structural property,which may use an adjective as in NUMERIC or REDEEMABLE. Routine names should faithfully reflect the Command-Query separation principle: Procedures (commands)should be verbs in the infinitive or imperative,possibly with complements:make,move,deposit,set color. Attributes and functions (queries)should never be imperative or infinitive verbs; never call a query get value,but just value.Non-boolean query names should be nouns,such as number,possibly qualified as in last month balance.Boolean queries should use adjectives,as in fill.In English,because of possible confusions between adjectives and verbs(empry,for example,could mean "is this empty?"or
§26.2 CHOOSING THE RIGHT NAMES 881 Letter case Letter case is not significant in our notation, as it is too dangerous to let two almost identical identifiers denote different things. But strongly recommended guidelines help make class texts consistent and readable: • Class names appear in all upper case: POINT, LINKED_LIST, PRICING_MODEL. Formal generic parameters too, usually with just one letter: G. • Names of non-constant attributes, routines other than once functions, local entities and routine arguments appear in all lower case: balance, deposit, succ, i. • Constant attributes have their first letter in upper case and the rest in lower case: Pi: INTEGER is 3.1415926524; Welcome_message: STRING is "Welcome!". This applies to unique values, which are constant integers. • The same convention applies to once functions, the equivalent of constants for nonbasic types: Error_window, Io. Our first example, the complex number i, remained in lower case for compatibility with mathematical conventions. This takes care of developer-chosen names. For reserved words, we distinguish two categories. Keywords such as do and class play a strictly syntactic role; they are written in lower case, and will appear in boldface (see below) in printed texts. A few reserved words are not keywords because they carry an associated semantics; written with an initial upper case since they are similar to constants, they include Current, Result, Precursor, True and False. Grammatical categories Precise rules also govern the grammatical category of the words from which identifiers are derived. In some languages, these rules can be applied without any hesitation; in English, as noted in an earlier chapter, they will leave more flexibility. The rule for class names has already been given: you should always use a noun, as in ACCOUNT, possibly qualified as in LONG_TERM_SAVINGS_ACCOUNT, except for the case of deferred classes describing a structural property, which may use an adjective as in NUMERIC or REDEEMABLE. Routine names should faithfully reflect the Command-Query separation principle: • Procedures (commands) should be verbs in the infinitive or imperative, possibly with complements: make, move, deposit, set_color. • Attributes and functions (queries) should never be imperative or infinitive verbs; never call a query get_value, but just value. Non-boolean query names should be nouns, such as number, possibly qualified as in last_month_balance. Boolean queries should use adjectives, as in full. In English, because of possible confusions between adjectives and verbs (empty, for example, could mean “is this empty?” or The example of i was on page 648. See the Class Name rule on page 727
882 A SENSE OF STYLE $26.2 "empty this!"),a frequent convention for boolean queries is the is form,as in is empty. Standard names You will have noted,throughout this book,the recurrence of a few basic names,such as put and item.They are an important part of the method. Many classes will need features representing operations of a few basic kinds:insert an element into a structure,replace the value of an element,access a designated element... Rather than devising specific names for the variants of these operations in every class,it is preferable to apply a standard terminology throughout. Here are the principal standard names.We can start with creation procedures,for which the recommended is make for the most common creation procedure of a class.Non- vanilla creation procedures may be called make some qualification,for example make polar and make cartesian for a POINT or COMPLEX class. For commands the most common names are: extend Add an element. Standard command replace Replace an element. names force Like put but may work in more cases;for example pur for arrays has a precondition to require the index to be within bounds,but force has no precondition and will resize the array if necessary. remove Remove an (unspecified)element. prumne Remove a specific element. wipe out Remove all elements. For non-boolean queries (attributes or functions): item The basic query for accessing an element:in ARRAY, Standard the element at a given index;in STACK classes,the names for non- stack top;in OUEUE classes,the oldest element;and so boolean on. queries infix "@ A synonym for item in a few cases,notably ARRAY. cout Number of usable elements in a structure. capaci力 Physical size allocated to a bounded structure,measured in number of potential elements.The invariant should include 0<=count and count <capacity
882 A SENSE OF STYLE §26.2 “empty this!”), a frequent convention for boolean queries is the is_ form, as in is_ empty. Standard names You will have noted, throughout this book, the recurrence of a few basic names, such as put and item. They are an important part of the method. Many classes will need features representing operations of a few basic kinds: insert an element into a structure, replace the value of an element, access a designated element… Rather than devising specific names for the variants of these operations in every class, it is preferable to apply a standard terminology throughout. Here are the principal standard names. We can start with creation procedures, for which the recommended is make for the most common creation procedure of a class. Nonvanilla creation procedures may be called make_some_qualification, for example make_ polar and make_cartesian for a POINT or COMPLEX class. For commands the most common names are: For non-boolean queries (attributes or functions): extend Add an element. replace Replace an element. force Like put but may work in more cases; for example put for arrays has a precondition to require the index to be within bounds, but force has no precondition and will resize the array if necessary. remove Remove an (unspecified) element. prune Remove a specific element. wipe_out Remove all elements. item The basic query for accessing an element: in ARRAY, the element at a given index; in STACK classes, the stack top; in QUEUE classes, the oldest element; and so on. infix "@" A synonym for item in a few cases, notably ARRAY. count Number of usable elements in a structure. capacity Physical size allocated to a bounded structure, measured in number of potential elements. The invariant should include 0 <= count and count <= capacity. Standard command names Standard names for nonboolean queries
$26.2 CHOOSING THE RIGHT NAMES 883 For boolean queries: Standard empty Is the structure devoid of elements? names for boolean full Is there no more room in the representation to add elements?(Normally the same as count capacity.) queries has Is a certain element present?(The basic membership test.) extendible Can an element be added?(May serve as a precondition to extend.) prunable Can an element be removed?(May serve as a precondition to remove and prune.) readable Is there an accessible element?(May serve as precondition to item and remove.) writable Is it possible to change an element?(May variously serve as precondition to extend,replace,put etc.) A few name choices which may seem strange at first are justified by considerations of clarity and consistency.For example prune goes with prunable and extend with extendible;delete and add might seem more natural,but then s.deletable and s.addable would carry the wrong connotation,since the question is not whethers can be deleted or added but whether we can add elements to it or delete elements from it.The verbs prune and extend,with the associated queries,convey the intended meaning. The benefits of consistent naming The set of names sketched above is one of the elements that most visibly contribute to the distinctive style of software construction developed from the principles of this book. Is the concern for consistency going too far?One could fear that confusion could result from routines that bear the same name but internally do something different.For example item for a stack will return the top element,and for an array will return an element corresponding to the index specified by the client. With a systematic approach to O-O software construction,using static typing and Design by Contract,this fear is not justified.To learn about a feature,a client author can rely on four kinds of property,all present in the short form of the enclosing class: Fl·Its name. F2.Its signature(number and type ofarguments if a routine,type ofresult if a query). F3.Its precondition and postcondition if any. F4.Its header comment. A routine also has a body,but that is not part of what client authors are supposed to use
§26.2 CHOOSING THE RIGHT NAMES 883 For boolean queries: A few name choices which may seem strange at first are justified by considerations of clarity and consistency. For example prune goes with prunable and extend with extendible; delete and add might seem more natural, but then s ● deletable and s ● addable would carry the wrong connotation, since the question is not whether s can be deleted or added but whether we can add elements to it or delete elements from it. The verbs prune and extend, with the associated queries, convey the intended meaning. The benefits of consistent naming The set of names sketched above is one of the elements that most visibly contribute to the distinctive style of software construction developed from the principles of this book. Is the concern for consistency going too far? One could fear that confusion could result from routines that bear the same name but internally do something different. For example item for a stack will return the top element, and for an array will return an element corresponding to the index specified by the client. With a systematic approach to O-O software construction, using static typing and Design by Contract, this fear is not justified. To learn about a feature, a client author can rely on four kinds of property, all present in the short form of the enclosing class: F1 • Its name. F2 • Its signature (number and type of arguments if a routine, type of result if a query). F3 • Its precondition and postcondition if any. F4 • Its header comment. A routine also has a body, but that is not part of what client authors are supposed to use. empty Is the structure devoid of elements? full Is there no more room in the representation to add elements? (Normally the same as count = capacity.) has Is a certain element present? (The basic membership test.) extendible Can an element be added? (May serve as a precondition to extend.) prunable Can an element be removed? (May serve as a precondition to remove and prune.) readable Is there an accessible element? (May serve as precondition to item and remove.) writable Is it possible to change an element? (May variously serve as precondition to extend, replace, put etc.) Standard names for boolean queries
884 A SENSE OF STYLE $26.3 Three of these elements will differ for the variants of a basic operation.For example in the short form of class STACK you may find the feature put (x:G) --Push x on top. require writable:not full ensure not_empty:not empty pushed:item =x whereas its namesake will appear in ARRAY as put (x:G;i:INTEGER) --Replace by x the entry of index i require not too small:i>=lower not too large:i<=upper ensure replaced:item (i)=x The signatures are different (one variant takes an index,the other does not);the preconditions are different;the postconditions are different;and the header comments are different.Using the same name put,far from creating confusion,draws the reader's attention to the common role of these routines:both provide the basic element change mechanism. This consistency has turned out to be one of the most attractive aspects of the method and in particular of the libraries.New users take to it quickly;then,when exploring a new class which follows the standard style,they feel immediately at home and can zero in on the features that they need. 26.3 USING CONSTANTS Many algorithms will rely on constants.As was noted in an early chapter of this book, constants are widely known for the detestable practice of changing their values;we should prepare ourselves against the consequences of such fickleness. Manifest and symbolic constants The basic rule is that uses of constants should not explicitly rely on the value: Symbolic Constant principle Do not use a manifest constant,other than the zero elements of basic operations,in any construct other than a symbolic constant declaration
884 A SENSE OF STYLE §26.3 Three of these elements will differ for the variants of a basic operation. For example in the short form of class STACK you may find the feature put (x: G) -- Push x on top. require writable: not full ensure not_empty: not empty pushed: item = x whereas its namesake will appear in ARRAY as put (x: G; i: INTEGER) -- Replace by x the entry of index i require not_too_small: i >= lower not_too_large: i <= upper ensure replaced: item (i) = x The signatures are different (one variant takes an index, the other does not); the preconditions are different; the postconditions are different; and the header comments are different. Using the same name put, far from creating confusion, draws the reader’s attention to the common role of these routines: both provide the basic element change mechanism. This consistency has turned out to be one of the most attractive aspects of the method and in particular of the libraries. New users take to it quickly; then, when exploring a new class which follows the standard style, they feel immediately at home and can zero in on the features that they need. 26.3 USING CONSTANTS Many algorithms will rely on constants. As was noted in an early chapter of this book, constants are widely known for the detestable practice of changing their values; we should prepare ourselves against the consequences of such fickleness. Manifest and symbolic constants The basic rule is that uses of constants should not explicitly rely on the value: Symbolic Constant principle Do not use a manifest constant, other than the zero elements of basic operations, in any construct other than a symbolic constant declaration