26 A sense of style mplementing the object-oriented method requires paying attention to many details of style,which a less ambitious approach might consider trifles. 26.1 COSMETICS MATTERS! Although the rules appearing hereafter are not as fundamental as the principles of object- oriented software construction covered in earlier chapters,it would be foolish to dismiss them as just"cosmetics".Good software is good in the large and in the small,in its high- level architecture and in its low-level details.True,quality in the details does not guarantee quality of the whole;but sloppiness in the details usually indicates that something more serious is wrong too.(If you cannot get the cosmetics right,why should your customers believe that you can master the truly difficult aspects?)A serious engineering process requires doing everything right:the grandiose and the mundane So you should not neglect the relevance of such seemingly humble details as text layout and choice of names.True,it may seem surprising to move on,without lowering our level of attention,from the mathematical notion of sufficient completeness in formal specifications (in the chapter on abstract data types)to whether a semicolon should be preceded by a space (in the present chapter).The explanation is simply that both issues deserve our care,in the same way that when you write quality O-O software both the design and the realization will require your attention. We can take a cue from the notion of style in its literary sense.Although the first determinant of good writing is the author's basic ability to tell a story and devise a coherent structure,no text is successful until everything works:every paragraph,every sentence and every word. Applying the rules in practice Some of the rules of this chapter can be checked or,better yet,enforced from the start by software tools.Tools will not do everything,however,and there is no substitute for care in writing every piece of the software
26 A sense of style Implementing the object-oriented method requires paying attention to many details of style, which a less ambitious approach might consider trifles. 26.1 COSMETICS MATTERS! Although the rules appearing hereafter are not as fundamental as the principles of objectoriented software construction covered in earlier chapters, it would be foolish to dismiss them as just “cosmetics”. Good software is good in the large and in the small, in its highlevel architecture and in its low-level details. True, quality in the details does not guarantee quality of the whole; but sloppiness in the details usually indicates that something more serious is wrong too. (If you cannot get the cosmetics right, why should your customers believe that you can master the truly difficult aspects?) A serious engineering process requires doing everything right: the grandiose and the mundane. So you should not neglect the relevance of such seemingly humble details as text layout and choice of names. True, it may seem surprising to move on, without lowering our level of attention, from the mathematical notion of sufficient completeness in formal specifications (in the chapter on abstract data types) to whether a semicolon should be preceded by a space (in the present chapter). The explanation is simply that both issues deserve our care, in the same way that when you write quality O-O software both the design and the realization will require your attention. We can take a cue from the notion of style in its literary sense. Although the first determinant of good writing is the author’s basic ability to tell a story and devise a coherent structure, no text is successful until everything works: every paragraph, every sentence and every word. Applying the rules in practice Some of the rules of this chapter can be checked or, better yet, enforced from the start by software tools. Tools will not do everything, however, and there is no substitute for care in writing every piece of the software
876 A SENSE OF STYLE $26.1 There is often a temptation to postpone the application of the rules,writing things casually at first and thinking"I will clean up everything later on;I do not even know how much of this will eventually be discarded".This is not the recommended way.Once you get used to the rules,they do not add any significant delay to the initial writing of the software;even without special tools,it is always more costly to fix the text later than to write it properly from the start.And given the pressure on software developers,there is ever a risk that you will forget or not find the time to clean things up.Then someone who is asked later to take up your work will waste more time than it would have cost you to write the proper header comments,devise the right feature names,apply the proper layout. That someone may be you. Terseness and explicitness Software styles have oscillated between the terse and the verbose.In programming languages,the two extremes are perhaps APL and Cobol.The contrast between the Fortran-C-C++line and the Algol-Pascal-Ada tradition -not just the languages themselves,but the styles they have bred-is almost as stark. What matters for us is clarity and,more generally,quality.Extreme forms of terseness and verbosity can both work against these goals.Cryptic C programs are unfortunately not limited to the famous"obfuscated C"and "Obfuscated C++"contests; but the almost equally famous DIVIDE DAYS BY 7 GIVING WEEKS of Cobol is a waste of everyone's attention. The style that follows from this chapter's rules is a particular mix of Algol-like explicitness(although not,it is hoped,verbosity)and telegram-style terseness.It never begrudges keystrokes,even lines,when they truly help make the software readable;for example,you will find rules that enjoin using clear identifiers based on full words,not abbreviations,as it is foolish to save a few letters by calling a feature disp (ambiguous) rather than display (clear and precise),or a class ACCNT (unpronounceable)rather than ACCOUNT.There is no tax on keystrokes.But at the same time when it comes to eliminating waste and unneeded redundancies the rules below are as pitiless as the recommendations of a General Accounting Office Special Commission on Improving Government.They limit header comments to indispensable words,getting rid of all the non-essential "the"and other such amenities;they proscribe over-qualification of feature names (as in account balance in a class ACCOUNT,where balance is perfectly sufficient);against dominant mores,they permit the grouping of related components of a complex construct on a single line,as in from i:=/invariant i<=n until i=n loop;and so on This combination of terseness and explicitness is what you should seek in your own texts.Do not waste space,as exaggerated size will in the end mean exaggerated complexity;but do not hesitate to use space when it is necessary to enhance clarity Also remember,iflike many people you are concerned about how much smaller the text of an object-oriented implementation will be than the text of a comparable C,Pascal, Ada or Fortran program,that the only interesting answer will appear at the level of a
876 A SENSE OF STYLE §26.1 There is often a temptation to postpone the application of the rules, writing things casually at first and thinking “I will clean up everything later on; I do not even know how much of this will eventually be discarded”. This is not the recommended way. Once you get used to the rules, they do not add any significant delay to the initial writing of the software; even without special tools, it is always more costly to fix the text later than to write it properly from the start. And given the pressure on software developers, there is ever a risk that you will forget or not find the time to clean things up. Then someone who is asked later to take up your work will waste more time than it would have cost you to write the proper header comments, devise the right feature names, apply the proper layout. That someone may be you. Terseness and explicitness Software styles have oscillated between the terse and the verbose. In programming languages, the two extremes are perhaps APL and Cobol. The contrast between the Fortran-C-C++ line and the Algol-Pascal-Ada tradition — not just the languages themselves, but the styles they have bred — is almost as stark. What matters for us is clarity and, more generally, quality. Extreme forms of terseness and verbosity can both work against these goals. Cryptic C programs are unfortunately not limited to the famous “obfuscated C” and “Obfuscated C++” contests; but the almost equally famous DIVIDE DAYS BY 7 GIVING WEEKS of Cobol is a waste of everyone’s attention. The style that follows from this chapter’s rules is a particular mix of Algol-like explicitness (although not, it is hoped, verbosity) and telegram-style terseness. It never begrudges keystrokes, even lines, when they truly help make the software readable; for example, you will find rules that enjoin using clear identifiers based on full words, not abbreviations, as it is foolish to save a few letters by calling a feature disp (ambiguous) rather than display (clear and precise), or a class ACCNT (unpronounceable) rather than ACCOUNT. There is no tax on keystrokes. But at the same time when it comes to eliminating waste and unneeded redundancies the rules below are as pitiless as the recommendations of a General Accounting Office Special Commission on Improving Government. They limit header comments to indispensable words, getting rid of all the non-essential “the” and other such amenities; they proscribe over-qualification of feature names (as in account_balance in a class ACCOUNT, where balance is perfectly sufficient); against dominant mores, they permit the grouping of related components of a complex construct on a single line, as in from i := 1 invariant i <= n until i = n loop; and so on. This combination of terseness and explicitness is what you should seek in your own texts. Do not waste space, as exaggerated size will in the end mean exaggerated complexity; but do not hesitate to use space when it is necessary to enhance clarity. Also remember, if like many people you are concerned about how much smaller the text of an object-oriented implementation will be than the text of a comparable C, Pascal, Ada or Fortran program, that the only interesting answer will appear at the level of a
$26.1 COSMETICS MATTERS! 877 significant system or subsystem.If you express a basic algorithm-at the level of Quicksort,say,or Euclid's algorithm-in C and in the notation of this book,expect the O-O version to be at least as large.In many cases,if you apply the principles thoroughly, it will be larger,since it will include assertions and more type information.Yet in ISE's experience of looking at medium-scale systems we have sometimes found(without being able to give a general law,as the circumstances vary considerably)the object-oriented solution to be several times smaller.Why?This is not due to terseness at the "micro"level but to systemwide application of the architectural techniques of the O-O method: Genericity is one of the key factors.We have found C programs that repeated essentially the same C code many times to handle different types.With a generic class-or for that matter a generic Ada package-you immediately get rid of that redundancy.It is disturbing in this respect to see that Java,a recent O-O language based on C,does not support genericity. Inheritance is also fundamental in gathering commonalities and removing duplications Dynamic binding replaces many complex decision structures by much shorter calls Assertions and the associated idea of Design by Contract avoid redundant error checking,a principal source of bloat. The exception mechanism gets rid of some error code. If you are concerned with source size,make sure to concentrate on these architectural aspects.You should also be terse in expressing algorithms,but never skimp on keystrokes at the expense of clarity The role of convention Most rules define a single permissible form,with no variants.The few exceptions include font use,which is governed by external considerations(what looks good in a book may not be visible on overhead transparencies),and semicolons,for which there exist two opposite schools with equally forceful arguments(although we will have a few universal rules anyway).In all other cases,in line with the introductory methodology chapter's exhortations against wishy-washiness,the rules leave about as much room to doubt as a past due reminder from the Internal Revenue Service. The rules are rooted in a careful analysis of what works and what works less well, resulting from many years of observation;some of the rationale will appear in the discussion.Even so,some rules may appear arbitrary at first,and indeed in a few cases the decision is a matter of taste,so that reasonable persons working from the same assumptions may disagree.If you object to one of the recommended conventions,you should define your own,provided you explain it in detail and document it explicitly;but do think carefully before making such a decision,so obvious are the advantages of abiding by a universal set of rules that have been systematically applied to thousands of classes over more than ten years,and that many people know and understand
§26.1 COSMETICS MATTERS! 877 significant system or subsystem. If you express a basic algorithm — at the level of Quicksort, say, or Euclid’s algorithm — in C and in the notation of this book, expect the O-O version to be at least as large. In many cases, if you apply the principles thoroughly, it will be larger, since it will include assertions and more type information. Yet in ISE’s experience of looking at medium-scale systems we have sometimes found (without being able to give a general law, as the circumstances vary considerably) the object-oriented solution to be several times smaller. Why? This is not due to terseness at the “micro” level but to systemwide application of the architectural techniques of the O-O method: • Genericity is one of the key factors. We have found C programs that repeated essentially the same C code many times to handle different types. With a generic class — or for that matter a generic Ada package — you immediately get rid of that redundancy. It is disturbing in this respect to see that Java, a recent O-O language based on C, does not support genericity. • Inheritance is also fundamental in gathering commonalities and removing duplications. • Dynamic binding replaces many complex decision structures by much shorter calls. • Assertions and the associated idea of Design by Contract avoid redundant error checking, a principal source of bloat. • The exception mechanism gets rid of some error code. If you are concerned with source size, make sure to concentrate on these architectural aspects. You should also be terse in expressing algorithms, but never skimp on keystrokes at the expense of clarity. The role of convention Most rules define a single permissible form, with no variants. The few exceptions include font use, which is governed by external considerations (what looks good in a book may not be visible on overhead transparencies), and semicolons, for which there exist two opposite schools with equally forceful arguments (although we will have a few universal rules anyway). In all other cases, in line with the introductory methodology chapter’s exhortations against wishy-washiness, the rules leave about as much room to doubt as a past due reminder from the Internal Revenue Service. The rules are rooted in a careful analysis of what works and what works less well, resulting from many years of observation; some of the rationale will appear in the discussion. Even so, some rules may appear arbitrary at first, and indeed in a few cases the decision is a matter of taste, so that reasonable persons working from the same assumptions may disagree. If you object to one of the recommended conventions, you should define your own, provided you explain it in detail and document it explicitly; but do think carefully before making such a decision, so obvious are the advantages of abiding by a universal set of rules that have been systematically applied to thousands of classes over more than ten years, and that many people know and understand
878 A SENSE OF STYLE $26.1 As noted in an earlier chapter (in the more general context of design principles),The comment was in many of the style rules were originally developed for libraries,and then found their way the introduction to into ordinary software development.In object technology,of course,all software is chapter 23. developed under the assumption that even if it is not reusable yet it might eventually be made reusable,so it is natural to apply the same style rules right from the start. Self-practice Like the design rules of the preceding chapters,the style rules which follow have been carefully applied to the many examples of this book.The reasons are obvious:one should practice what one preaches;and,more fundamentally,the rules do support clarity of thought and expression,which can only be good for a detailed presentation of the object- oriented method. The only exceptions are a few occasional departures from the rules on software text layout.These rules do not hesitate to spread texts over many lines,for example by requiring that every assertion clause have its own label.Lines are not a scarce resource on computer screens;it has been observed that with the computer age we are reversing the direction of the next-to-last revolution in written communication,the switch from papyrus rolls to page-structured books.But this text is definitely a book,structured into pages,and a constant application of the layout-related rules would have made it even bigger than it is. The cases of self-dispensation affect only two or three layout-related rules,and will be noted in their presentation below.Any exception only occurs after the first few examples of a construct in the book have applied the rules scrupulously. Such exceptions are only justified for a paper presentation.Actual software texts should apply the rules literally. Discipline and creativity It would be a mistake to protest against the rules of this chapter(and others)on the grounds that they limit developer creativity.A consistent style favors rather than hampers creativity by channeling it to where it matters.A large part of the effort of producing software is spent reading existing software and making others read what is being written. Individual vagaries benefit no one;common conventions help everyone Some of the software engineering literature of the nineteen-seventies propounded Sentence initalics the idea of "egoless programming":developing software so that it does not reflect from D.H.Brandon, “Data Processing anything of its authors'personality,thereby making developers interchangeable.Applied Organiation and to system design,this goal is clearly undesirable,even if some managers may sometimes Manpower Planning", long for it(as in this extract of a programming management book quoted by Barry Boehm: Petrocelh,1974, "...the programmer('s]creative instincts should be totally dulled to insure uniform and emphasis in original Ouoted in Boehm understandable programming",to which Boehm comments:"Given what we know about 1981,p.674. programmers and their growth motivation,such advice is a clear recipe for disaster"). What quality software requires is egoful design with egoless expression
878 A SENSE OF STYLE §26.1 As noted in an earlier chapter (in the more general context of design principles), many of the style rules were originally developed for libraries, and then found their way into ordinary software development. In object technology, of course, all software is developed under the assumption that even if it is not reusable yet it might eventually be made reusable, so it is natural to apply the same style rules right from the start. Self-practice Like the design rules of the preceding chapters, the style rules which follow have been carefully applied to the many examples of this book. The reasons are obvious: one should practice what one preaches; and, more fundamentally, the rules do support clarity of thought and expression, which can only be good for a detailed presentation of the objectoriented method. The only exceptions are a few occasional departures from the rules on software text layout. These rules do not hesitate to spread texts over many lines, for example by requiring that every assertion clause have its own label. Lines are not a scarce resource on computer screens; it has been observed that with the computer age we are reversing the direction of the next-to-last revolution in written communication, the switch from papyrus rolls to page-structured books. But this text is definitely a book, structured into pages, and a constant application of the layout-related rules would have made it even bigger than it is. The cases of self-dispensation affect only two or three layout-related rules, and will be noted in their presentation below. Any exception only occurs after the first few examples of a construct in the book have applied the rules scrupulously. Such exceptions are only justified for a paper presentation. Actual software texts should apply the rules literally. Discipline and creativity It would be a mistake to protest against the rules of this chapter (and others) on the grounds that they limit developer creativity. A consistent style favors rather than hampers creativity by channeling it to where it matters. A large part of the effort of producing software is spent reading existing software and making others read what is being written. Individual vagaries benefit no one; common conventions help everyone. Some of the software engineering literature of the nineteen-seventies propounded the idea of “egoless programming”: developing software so that it does not reflect anything of its authors’ personality, thereby making developers interchangeable. Applied to system design, this goal is clearly undesirable, even if some managers may sometimes long for it (as in this extract of a programming management book quoted by Barry Boehm: “…the programmer[‘s] creative instincts should be totally dulled to insure uniform and understandable programming”, to which Boehm comments: “Given what we know about programmers and their growth motivation, such advice is a clear recipe for disaster”). What quality software requires is egoful design with egoless expression. The comment was in the introduction to chapter 23. Sentence in italics from D.H. Brandon, “Data Processing Organization and Manpower Planning”, Petrocelli, 1974, emphasis in original. Quoted in [Boehm 1981], p. 674
$26.2 CHOOSING THE RIGHT NAMES 879 More than style standards,what would seem to require justification is the current situation of software development,with its almost total lack of style standards.In no other discipline that demands to be called "engineering"is there such room for such broad personal variations of whim and fancy.To become more professional,software development needs to regulate itself. 26.2 CHOOSING THE RIGHT NAMES The first aspect that we need to regulate is the choice of names.Feature names,in particular,will be strictly controlled for everyone's benefit. General rules What matters most is the names of classes and features which will be used extensively by the authors of classes that rely on yours. For feature and class names,use full words,not abbreviations,unless the abbreviations are widely accepted in the application domain.In a class PART describing parts in an inventory control system,call number,not num,the feature (query)giving the part number.Typing is cheap;software maintenance is expensive.An abbreviation such as usa in a Geographical Information System or copter in a flight control system,having gained an independent status as a word of its own,is of course acceptable.In addition,a few standard abbreviations have gained recognition over the years,such as PART for PARTIAL in class names such as PART COMPARABLE describing objects equipped with a partial order relation. In choosing names,aim for clarity.Do not hesitate to use several words connected by underscores,as in ANNUAL RATE,a class name,or yearly premium,a feature name. Although modern languages do not place any limit on the length of identifiers,and treat all letters as significant,name length should remain reasonable.Here the rule is not the same for classes and for features.Class names are input only occasionally (in class headers,type declarations,inheritance clauses and a few other cases)and should describe an abstraction as completely as possible,so PRODUCT OUANTITY INDEX EVALUATOR may be fine.For features,there is seldom a need for more than two or possibly three underscore-connected words.In particular,do not overqualifiy feature names.If a feature name appears too long,it is usually because it is overqualified: Composite Feature Name rule Do not include in a feature name the name of the underlying data abstraction (which should serve as the class name). The feature giving the part number in class PART should be called just number,not part number.Such over-qualification is a typical beginner's mistake;the resulting names
§26.2 CHOOSING THE RIGHT NAMES 879 More than style standards, what would seem to require justification is the current situation of software development, with its almost total lack of style standards. In no other discipline that demands to be called “engineering” is there such room for such broad personal variations of whim and fancy. To become more professional, software development needs to regulate itself. 26.2 CHOOSING THE RIGHT NAMES The first aspect that we need to regulate is the choice of names. Feature names, in particular, will be strictly controlled for everyone’s benefit. General rules What matters most is the names of classes and features which will be used extensively by the authors of classes that rely on yours. For feature and class names, use full words, not abbreviations, unless the abbreviations are widely accepted in the application domain. In a class PART describing parts in an inventory control system, call number, not num, the feature (query) giving the part number. Typing is cheap; software maintenance is expensive. An abbreviation such as usa in a Geographical Information System or copter in a flight control system, having gained an independent status as a word of its own, is of course acceptable. In addition, a few standard abbreviations have gained recognition over the years, such as PART for PARTIAL in class names such as PART_COMPARABLE describing objects equipped with a partial order relation. In choosing names, aim for clarity. Do not hesitate to use several words connected by underscores, as in ANNUAL_RATE, a class name, or yearly_premium, a feature name. Although modern languages do not place any limit on the length of identifiers, and treat all letters as significant, name length should remain reasonable. Here the rule is not the same for classes and for features. Class names are input only occasionally (in class headers, type declarations, inheritance clauses and a few other cases) and should describe an abstraction as completely as possible, so PRODUCT_QUANTITY_INDEX_ EVALUATOR may be fine. For features, there is seldom a need for more than two or possibly three underscore-connected words. In particular, do not overqualify feature names. If a feature name appears too long, it is usually because it is overqualified: The feature giving the part number in class PART should be called just number, not part_number. Such over-qualification is a typical beginner’s mistake; the resulting names Composite Feature Name rule Do not include in a feature name the name of the underlying data abstraction (which should serve as the class name)
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