CS320 Lecture: Implementing Classes in C++;                           9/11/96
                Encapsulation; Public and Private Members;    Revised 9/22/97
                Designing a Class Interface; friends.

Materials: Transparencies: Side by side class description and interface
                           for class Session
                           bank.h (abbreviated)
                           atm.h
                           atmparts.h (page 1 only)
                           transaction.h (class Transaction only)
                           status.h
                           session.cc
                           main.cc
                           transaction.cc (implementation of base class only)
                           Design suggestions from text
                           MacGregor/Sykes class design guidelines

           Handout: Instance vs class variables/methods

I. Preliminary Comments
-  ----------- --------

   A. Stroustrup philosophy in design of C++:

        "I find Kierkegaard's almost fanatical concern for the individual and 
        keen psychological insights much more appealing than the grandiose 
        schemes and concern for humanity in the abstract of Hegel or Marx.  
        Respect for groups that doesn't include respect for individuals of those
        groups isn't respect at all.  Many C++ design decisions have their 
        roots in my dislike for forcing people to do things in some particular
        way.  In history, some of the worst disasters have been caused by 
        idealists trying to force people into 'doing what is good for them'.  
        Such idealism not only leads to suffering among its innocent victims, 
        but also to delusion and corruption of the idealists applying the force.
        I also find idealists prone to ignore experience and experiment
        that inconveniently clashes with dogma or theory.  Where ideals
        clash and even sometimes when pundits seem to agree, I prefer
        to provide support that gives the programmer a choice.

        My preferences in literature have reinforced this unwillingness
        to make a decision based on theory and logic alone.  In this
        sense, C++ owes as much to novelists and essayists such as
        Martin A. Hansen, Albert Camus, and George Orwell, who never saw
        a computer, as it does to computer scientists such as David
        Gries, Don Knuth, and Roger Needham.  Often, when I was tempted
        to outlaw a feature I personally disliked, I refrained from
        doing so because I did not think I had a right to force my
        views on others ... A high degree of tolerance and acceptance
        that different people do think in different ways and strongly
        prefer to do things differently is to me far preferable.
        ...
        In particular, I do not try to enforce a single style of design
        through a narrowly defined programming language.  People's ways
        of thinking and working are so diverse that an attempt to force
        a single style would no more harm than good.  Thus, C++ is
        deliberately designed to support a variety of styles rather
        than a would-be 'one true way'." 

        Stroustrup-Design and Evolution of C++ (Addison Wesley, 1994) pp. 23-24.

   B. My approach here

        For pedagogical reasons, I will not try to cover all the alternative
        ways of doing things in C++ - but will instead focus on one
        approach to each task which integrates seamlessly with the design
        methods we have already discussed.  Sometimes, I will also mention
        one or more alternatives as well.  I will leave it to you to explore
        other alternatives on your own as you become more familiar with
        the language.  However, for class use, I would encourage you to
        use the style taught in class.

   C. Turning a class description form into a C++ implementation is done in
      two parts - a class declaration (normally in a .h file) plus a
      class implementation (normally in corresponding .cc file).

      1. The class declaration includes all the information in the class 
         description form.

      2. The class implementation contains an implementation of each method
         declared for the class, and perhaps other things as well.

II. Declaring a Class
--  --------- - -----

   A. Basic form of a class declaration: 

        class NAME [ : public BASECLASS ]
          {
            public:

                DECLARATIONS (PROTOTYPES) FOR CONSTRUCTOR, MUTATOR, ACCESSOR, 
                AND DESTRUCTOR METHODS - NORMALLY IN THAT ORDER

            private:

                DECLARATION OF PRIVATE METHODS, IF ANY
                DECLARATIONS OF FIELDS

          };

      Note that these sections correspond very closely to the class
      description form - except that there is nothing directly corresponding
      to the "states" portion of the form.  (The state information has to
      actually be encoded by the value of some field.)

   B. Example: SIDE BY SIDE TRANSPARENCY OF SESSION CLASS DESCRIPTION
      FORM AND SESSION.H.

      Note:

      1. public: and private: sections

         a. public usable by all, private only accessible within
            implementation of methods of the class (compiler protected).

            Example:

             class foo
               {
                 public:

                     int bar();

                 private:

                     int _x;
               };

             int foo:bar()
               { return _x ++; }        // legal

             main()
               {
                 foo f;
                 ...
                 cout << f.bar();       // legal
                 cout << f._x;  // illegal - detected by compiler
               }

         b. Standard practice: methods are public, fields are private

         c. Can have private methods (used to implement other public methods)

         d. Can have public fields (therefore accessible to all) - but this
            is bad practice (violates encapsulation).

      2. Methods are declared by giving a full prototype (as in operation
         description forms) followed by a ;

         RETURN-TYPE NAME([TYPE ARG [, TYPE ARG]...]);

         Methods always have parentheses after name - even if empty.

      3. Our book suggests declaring methods in the order

         constructor(s)
         mutators
         accessors
         destructor

         a. Constructor method(s) are distinguished by name of method being
            same as name of class.  

            - When an instance of a class is created, a constructor is 
              automatically called.

              - Before main program for global variables
              - Upon entry into function or block for local variables
              - Within expression for temporaries
              - When creating an object dynamically using new

            - "Miranda rule" for constructors

         b. Mutators/accessors should be named appropriately

            - Note that accessor prototypes (cardNumber(), PIN()) are
              followed by const.  This indicates that these methods do
              not change the object's fields (i.e. they could be applied to 
              an object that is declared as a constant).

            - Mutators are allowed to change the object's fields.
              (In this case, the first two alter the value of _PIN; the
              doFailedTransactionExtension method turns out not to alter
              the state of the object, but this was not clear at the
              time it was first designed.)

         c. Not shown here are destructors

            - Name is ~CLASSNAME (e.g. ~Session())

            - Automatically called when an instance of the class is destroyed

              - After termination of main for global variables
              - Upon exit from function or block for local variables
              - Within an expression for temporaries (when no longer needed)
              - When delete is used to destroy an object created using new

              However: an object created using new that is never explicitly
                       destroyed by delete is not destructed!

            - "Miranda rule" for destructors - but only in certain cases where
              a destructor is needed because a component of the object has a
              destructor that needs to be called.  (Unlike construction,
              destruction is not mandatory).

      4. Fields are declared by giving a type then name (or comma-separated
         names) followed by a ; - no parentheses

      5. Anonymous enum type created for field _state (only variable that
         will ever hold a value of this type).

      6. "Forward" declaration of class Transaction:

         a. Transaction is declared in transaction.h.  It turns out that
            Transaction objects contain a reference to the Session object
            that created them, and Session objects contain a pointer to
            the currently active Transaction object.  So no matter which
            class is declared first, there will be a problem!

         b. Solved by use of an INCOMPLETE CLASS DECLARATION of the form

             class CLASSNAME ;

            - Declares that the class exists, but provides no information
             about it.

            - Must be followed by a full declaration later.

            - Variables of an incomplete class type cannot be declared until
              after the declaration has completed, but pointers and
              references can be declared. (The issue is that the compiler
              does not know how much memory to allocate for an object until
              its class has been declared; but size of a pointer/reference
              is independent of size of object it points to.)

      7. Field _currentTransaction must be a pointer, not a reference,
         because value will change.

      8. Closing } is followed by a ;

   C. The public section of the declaration is the class interface.  The
      private section really shouldn't need to be in the declaration, but
      is there as a concession to practicality so that the compiler can 
      figure out the size of objects of the class and reserve space for 
      variables of class type, as well as to support inline methods
      (to be discussed later).

   D. Further examples: walk through additional .h files

      1. bank.h - TRANSPARENCY (ABBREVIATED) - Note:

         a. class declaration can also declare other data types - e.g.
            enum AccountType

            - will be referred to by these names inside class declaration
              and methods

            - must be referred to as Bank::AccountType elsewhere

         b. use of reference parameters (Money &) for items that will be
            returned from methods

         c. Two uses of const in declarations of accountName() and
            rejectionDescription():

            - const after () - these are accessors, so do not alter state
              of Bank object

            - const before return type - these return a pointer to a
              character string constant.  The caller is NOT allowed to
              alter the contents of the string returned - e.g. the
              following would be illegal:

              const char * foo =
                     theBank.rejectionDescription(BANK::NO_SUCH_ACCOUNT);
              foo[0] = 'X';     // Illegal - rejected by compiler

              Likewise, the following would also be illegal:

              char * foo =
                     theBank.rejectionDescription(BANK::NO_SUCH_ACCOUNT);
              // Compiler will not allow a const char * pointer to be
              // stored into a non-const pointer

      2. atm.h - TRANSPARENCY - Note:

         a. Parameters to constructor - must be supplied when a  variable of 
            the class is created.  The following appears in main.cc:

               ATM theATM(42, "GORDON COLLEGE", theBank);

            - location parameter is declared const char * as a promise
              that string passed to it will not be changed.

         b. Accessor methods are const.  (The operations may alter the
            state of the component part that performs that operation, but
            not of the ATM itself, which simply forwards the message to
            the right component)

         c. String parameters to getMenuChoice(), issueReceipt(),
            and reportTransactionFailure() are const char * - method will not
            alter them.

            - Note that const on parameters is an issue only with pointers
              and references

            - Reference parameters in issueReceipt are NOT const because
              they will be altered, since they are used for return values.

         d. Anonymous enumeration type for variable _state

         e. Fields _cardReader etc. that contain references to component
            parts.  

            - These use keyword class to create an incomplete type
              declaration - the detailed declarations of the parts is not
              relevant to clients of ATM.

            - We can use a reference here, rather than a pointer,
              because parts will be created when ATM is created and will not
              change.  When this is the case, use of a reference is
              preferable.
            
      3. atmparts.h - TRANSPARENCY (PAGE 1 ONLY) - Note:

         a. Several related classes included in one .h file

         b. Close correspondence between these methods and some declared
            in atm.h - the ATM object will simply forward the message to
            the right component.  (But many of these are non-const
            because the state of the ATM component is altered.)

         c. The only class that depends on this interface is ATM.

      4. transaction.h - TRANSPARENCY (class Transaction only)

         a. The method chooseTransaction() is declared static.

            i. Recall that in OO systems most computation is done by sending
               MESSAGES to OBJECTS, which are handled by appropriate METHODS.
               As a result, most of the time when a method is called it is
               associated with a specific object.  (In fact, each instance 
               method has an implicit first parameter which is a pointer to
               the object on which it was invoked.)

           ii. There are times, however, when a method cannot be associated
               with a specific object.  This is the case here - the whole
               purpose of chooseTransaction() is to construct a new object
               of a specific subclass.

          iii. A method like this is called a CLASS METHOD, because the
               message is really being sent to the class, rather than to
               a specific object.

           iv. In C++, class methods are declared static in the interface.

         b. Names of types declared as part of other classes must
            be preceeded by a scope specifier - e.g.

             Status::Code

            TRANSPARENCY: status.h (note no .cc file will be needed)

         c. Several methods are declared virtual.  This supports polymorphism,
            and will be discussed later.

         d. Several instance variables are declared protected.  This relates
            to subclasses and inheritance, and will be discussed later.

         e. The field _lastSerialNumberAssigned is declared static.

            i. Ordinarily, each object of a class has its own copy of each
               field - e.g. each Transaction has its own session, serialNumber,
               and resulting balances.

           ii. Sometimes, though, we have a need for a field which exists in
               a single copy shared by ALL instances of the class.  Such a
               field is called a CLASS VARIABLE.

          iii. This is the case here.  The constuctor for Transaction will
               assign a serial number to each object as it is constructed.
               To do this, we need to keep track of what serial numbers have
               already been used.  That is what _lastSerialNumberAssigned is
               used for.

           iv. In C++, a class variable is declared static in the class
               declaration.  All objects of the class share one copy of the
               variable.

      5. HANDOUT - Instance versus class variables and methods

III. Implementing a Class
---  ------------ - -----

   A. Basic form of a class implementation

      INCLUDE DIRECTIVES FOR CLASS DECLARATION AND OTHER NEEDED HEADERS
      DEFINITIONS FOR EACH METHOD AND CLASS VARIABLE
       (NORMALLY IN THE ORDER OF DECLARATION)

   B. Example: TRANSPARENCY: SESSION.CC

      1. Implementation (.cc) file will #include interface (.h) file, plus
         any other .h files needed

         a. If the class being implemented uses objects of some other class
            in its interface, then .h files for those classes must be
            #included BEFORE its .h file.

            Example: status.h and money.h must be included before bank.h,
                     because methods declared in bank.h take parameters of
                     type Status::Code and Money.  (Many other examples
                     could be cited.)

         b. If the class uses objects for some other class for its
            implementation (but not interface), then .h files for these classes
            can be #included before or after its .h file (depending on needs
            for their interface)

            Example: atm.h  - We will see that session uses methods of ATM
                              (such as getTransactionChoice(), ejectCard(),
                              and retainCard()) to implement its methods

              transaction.h - Session creates transaction objects and uses
                              their doTransactionUseCase method.

         c. Standard libaries are normally #include-d first

            Examples: None here.

      2. Rest of the file is implementation of each method

         Note:

         a. Use of scope specifier (Session::) before name of each method
            being implemented

            i. Method names must be unique within a class, but different
               classes can have methods with the same name.  The complete
               name of a method, therefore, must include the class of
               which it is a part unless the class is implicit in the context -
               which is not the case here.

           ii. Note the order RETURN-TYPE SCOPE::METHODNAME(ARGS)

          iii. Note, too, that if the return type or parameter belongs to a
               different class, then it may need a scope specifier as well
        
               Example: Status::Code is the return type for the method
                        Session::doInvalidPINExtension()

         b. Methods are a special kind of C++ function, and are implemented
            accordingly.

            i. Basic syntax:

                PROTOTYPE -- must match declaration in interface exactly,
                             including use of const.
                 { BODY }

                Examples: doSessionUseCase(), doInvalidPINExtension,
                          doFailedTransactionExtension(),
                          cardNumber(), PIN()

           ii. Special syntax for constructor

                PROTOTYPE
                  : INITIALIZERS
                  { BODY }

               - The initializers part is a comma separated list of field names
                 and values (or base class names and values).  Each value can be
                 any C++ expression, and can use the constructor's parameters

                 Example: Session() initializers

               - With two exceptions, you are not under any obligation to
                 initialize a field at this point.  You can, instead, assign
                 it a value later.

                 Example: the _PIN field is not initialized, because its value
                          is not obtained until the use case is started.  It
                          is assigned a value by the first statement in
                          doSessionUseCase()

                 Exceptions:

                 - If the field is an object (not a simple value) and it does
                   not have a default constructor (one that takes no
                   parameters), then you must supply an explicit constructor
                   call with appropriate parameters.

                 - A field which is of a reference type must be initialized 
                   here, since it cannot be assigned to

                   Example: _atm, _bank

               - Even if you are not obligated to initialize a given field,
                 it is good practice to do so if you can give it a reasonable
                 value.

         c. Within an instance method, there is an implicit parameter which is a
            pointer to the specific object that received the message that
            led to this method being invoked.  The fields and methods of
            this object are accessible without qualification.

            Example: In the initializers list in Session(), we can refer to
                     the _state and _cardNumber attributes of the Session
                     object being constructed.

            Example: In doSessionUseCase, we use the _atm, _PIN, 
                     _currentTransaction, and _state fields of the Session 
                     object which received the doSessionUseCase message 

            (This is not the case, however, with a class method - one
             declared as static.)

         d. Methods of other classes are normally invoked by using the syntax:

                VARIABLE.METHOD(ARGS)

            or  REFERENCE.METHOD(ARGS)

                Example: _atm.getPIN() in doSessionUseCase() and several
                         other similar calls

            or  POINTER->METHOD(ARGS)

                Example: currentTransaction->doTransactionUseCase() in
                         doSessionUseCase()

            Any of these syntaxes have the same effect - the appropriate
            method is called, with an implicit parameter pointing to the
            object that was named when the method was called.

         e. Likewise, methods and fields of other objects of the same class
            can be referenced by using the OBJECT. or POINTER -> syntax.

   C. There are three important kinds of method that are handled a bit
      differently from other methods

      1. CONSTRUCTOR METHODS

         a. A constructor method is a method whose name is the same as the
            name of its class (e.g. Session() is a constructor for objects
            of class Session).

            i. It can have parameters but most not have a return type specified.

           ii. A class can have more than one constructor, provided the
               argument types are different.

               Example: In the homework, you have been working with a chess
                        game, which includes the class Game that models a
                        single game.  This class might have two constructors:

                        Game() - no parameters - starts up a game from scratch
                        Game(file) - resumes game saved in file

          iii. One special type of constructor is the COPY CONSTRUCTOR.  It
               takes a single parameter of const reference its own type -
               e.g. a copy constructor for Session would be declared

               Session(const Session &);

               The copy constructor is used whenever an object needs to be
               copied - e.g. when passing a parameter by value or generating
               a run time temporary.

           iv. If a class does not have any constructors declared at all, the
               compiler generates a default constructor that takes no
               parameters and does nothing (except, if necessary, to use
               default constructors to initialize fields of class types).

            v. If a class does not have a copy constructor, the compiler
               generates one that simply copies all the fields.

         b. We have already noted that the syntax for implementing a
            constructor includes a special provision for initializing the
            fields of the object being constructed.

         c. A constructor method is usually not called explicitly - e.g. if
            session is an object of class Session, then a call of the form

                session.Session()

            would be unusual (though not illegal).  This is because 
            a constructor is automatically called whenever an object 
            is created, either via a variable definition or through the use 
            of the new operator.  (If parameters are needed for the 
            constructor, they must be supplied.)

            i. Example of an implicit constructor call when a variable
               is defined: TRANSPARENCY - main.cc

                     definitions of theATM, theBank

               NOTE: Global variable objects are constructed before the main
                     program starts up.  Local variable objects are constructed
                     when execution reaches the line on which the declaration
                     appears.

                     (There are no globals in this program)

           ii. Example of a constructor call in conjunction with operator new:
               TRANSPARENCY - transaction.cc (partial)

                     four instances of new in chooseTransaction()

      2. DESTRUCTOR METHODS

         a. A destructor is a method whose name is of the form ~CLASSNAME
            (e.g. ~Session()).  It can have neither parameters nor return
            type (not even void).

         b. A DESTRUCTOR METHOD is always called when an object is
            destroyed, either via program termination, or via exiting the
            block to which it is local, or via the use of the delete
            operator.

            Example: TRANSPARENCY - session.cc

                     delete _currentTransaction in doSessionUseCase()

         c. If an object being destroyed has fields which have destructors,
            their destructors are automatically called (the code to do so
            is supplied by the compiler when the destructor is compiled).

         d. There are no examples of destructor methods in the ATM system.
            Explicit destructors are typically only written when some
            special action needs to be taken - e.g. freeing up resources that
            the object has allocated.

            Example: Consider the following simple class

                class Person
                  {
                    public:
                        Person(const char * name);
                    private:
                        const char * _name;
                  };

                Person::Person(char * name)
                  : _name(new char[strlen(name) + 1])
                  { strcpy(_name, name); }

            The constructor allocates space to hold a private copy of the string
            passed as a parameter to it.

            This class should have a destructor to free up this space:

            - Add Person::~Person() to the declaration

            - Implementation:

                Person::~Person()
                  { delete [] _name; }

      3. CLASS METHODS

         a. CLASS METHODS are methods whose call is  not associated with a
            specific object of the class, and thus do not take an object as
            an implicit parameter.

         b. Such methods are declared static in C++

            Example: TRANSPARENCY - transaction.h (Looked at earlier)

         c. Class methods are called by the syntax CLASSNAME::METHODNAME(ARGS)
            instead of OBJECT.METHODNAME(ARGS)

             Example: TRANSPARENCY - session.cc
        
                      call to makeTransaction() in doSessionUseCase()

         d. Class methods cannot access the individual fields of an object or
            ordinary class methods without explicitly naming an object, since
            there is no implicit first parameter.

   D. When a class declaration includes one or more class variables (fields
      declared as static) the implementation file must initialize them.

      Example: TRANSPARENCY - transaction.cc

IV. Encapsulation and Design Issues
--  ------------- --- ------ ------

   A. The class is the basic mechanism used for encapsulation in C++.  Correct
      use of public: and private: is an important part of this.

      1. As a rule of thumb, the methods of a class should be public and
         the fields should be private.  However, there can be exceptions to 
         this.

      2. Sometimes, a method is needed only to facilitate the implementation of
         other methods - i.e. it is not intended to be called directly from the 
         outside.  In this case, it should be private.

         Example: In our ATM system the Bank class serves to model our
                  interface to the Bank.  The physical connection to the bank
                  may be a communications link, in which case the various
                  methods will be implemented like this:

                  Construct a communications packet from the parameters
                  Send it to the bank over the network
                  Wait for a response packet from the bank
                  Convert the response packet into value(s) to return to
                   the caller.

         The class Bank may have private methods like constructPacket(),
         sendPacket(), and getResponse()

      3. What about making a data member public?

         a. This is never necessary - one can make full access to a data
            member possible - while preserving the wall of abstraction - by
            creating a modifer and accessor method.

            Example: A class foo has an integer data member called _number.
                     If necessary, we can include methods:

                     void setNumber(int value);
        
                     -- body: { _number = value; }

                     int number();

                     -- body: { return _number; }

         b. However, some would argue that this leads to run-time inefficiency,
            since there is the overhead of a procedure call involved instead
            of simple access to a field in a structure.

            To address, this, C++ allows the use of INLINE methods:

            i. The implementation of an inline method is included in the class 
               HEADER (.h) file - preceeded by the keyword inline.

               Example:

               inline void foo::setNumber(int value)
                 { _number = value; }

               inline int foo::number()
                 { return _number; }

           ii. The compiler substitutes the body of method for a call to the
               method, making the result as efficient as accessing the data
               member directly.

          iii. Actually, as an alternative C++ allows inline methods to have
               both declaration and body in the class declaration - e.g.

               class foo
                 {
                   ...
                   inline void setNumber(int value)     { _number = value; }
                   inline int number()                  { return _number; }
                   ...
                 }
        
               However, this tends to clutter the interface and so we will
               avoid it.

         c. Someone may argue that since giving the inline code for a method
            in the header file breaches abstraction, we might as well go all
            the way and have public data members, thus avoiding the work of
            writing the inline methods.  The best response to this is that
            using inline methods allows us to change the implementation at a
            later date without requiring a lot of code to be rewritten.

            Example: It becomes necessary to ensure that the value of _number
                     never exceeds 100.  If an attempt is made to set it to
                     a higher value, it must be just set to 100.  This is
                     easily done by just changing the one body of the inline
                     method and then recompiling.

      4. We have seen that C++ provides two alternatives for specifying how
         a member of a class can be accessed - private, which restricts
         access only to operation of the class, and public, which grants
         access to everyone.  (Actually, there is a third kind of access -
         protected - which applies when a class has subclasses.)

         a. Sometimes, one wants to grant some other class privileged access, 
            without granting that access to everyone.

         b. Example: Suppose we need to maintain a record of all transactions
                     performed at our ATM, so we create a TransactionLog class.

            class TransactionLog
              {
                public:

                    TransactionLog();           // Make an empty log
                    void add(Transaction * t);  // Add a transaction
                    void print();               // Print the log
                     ...
       
            Suppose further that we decide to do this using a linked list 
            implementation.  To support this, we add a _link field to the 
            declaration of Transaction.  Should this field be private or public?

            ASK

            Answer: Neither is really right. If it is private, then
                    TransactionLog::add and Transaction::print cannot access 
                    it.  If it is public, everyone can access it - which 
                    violates encapsulation.

         c. To handle cases like this, C++ allows one class to declare another
            class to be a friend.  Methods of a friend class can access
            private members of the class just like methods of the class
            itself.

            Example:

            We could add

                friend class TransactionLog;

            to the declaration of Transaction.  This would allow all the
            methods of TransactionLog to access the private members of
            Transaction.

         d. In addition to declaring a class as a friend, it is also
            possible to declare a specific global function or a specific
            method of another class to be a friend.

            Example: In this case, if add and print were the only operations of
                     TransactionLog needing to access the _link of Transaction,
                     we could put the following in Transaction:

                     friend void TransactionLog::add(Transaction *);
                     friend void TransactionLog::print();

         e. The friend feature of C++ has been criticized as providing too
            large of a hole in encapsulation - e.g. in this case TransactionLog
            would have access to other private members of Transaction besides
            the one (_link) it needs.  It can usually be avoided by careful
            design, though (as Stroustrup points out) there are a few places
            where it is the only way to do something in a clean, elegant way.

   B. Naming conventions.  One important choice in designing a class is the
      NAMES that are used for classes, objects, methods, data members, etc.

      1. Many conventions are in common use

      2. Ones I will use are those recommended in our book - actually based on
         Smalltalk conventions.  (All examples from ATM simulation code.)

         a. Class names begin with uppercase - then lower case except first
            letter of new word

            ex: Session, Bank, ATM (abbreviation for AutomatedTellerMachine),
                CardReader

         b. Other user-defined types - ditto

            ex: ApprovalCode

         c. Method names begin with lowercase - then lower case except first
            letter of new word

            ex: doSessionUseCase()

         d. Field names begin with underscore - then lower case except first
            letter of new word

            ex: _state

            (Note: _PIN is an exception because it is a standard abbreviation)

         e. Constant names (e.g. enum values) all uppercase

            ex: RUNNING

         f. Also: variables other than fields: begin with lower case, then 
            lower case except first letter of new word

            ex: theATM, theBank

   C. Our text makes a number of design suggestions in the chapters you were
      assigned to read.

      1. ASK

      2. TRANSPARENCY - DESIGN SUGGESTIONS

         ASK CLASS WHAT EACH MEANS

   D. Here are some additional general principles, taken from a book by
      McGregor and Sykes:

        TRANSPARENCY

        Go over each

Copyright ©1998 - Russell C. Bjork