Lecture Notes on Object-Oriented Programming

The Quality of Classes and OO Design

This collection of notes on OOP was never meant to stand alone. It also represents a view of OO circa early to mid 1990s. Some people still find them useful, so here they are, caveat emptor. Special thanks to Gilbert Benabou for taking to time to compile the first printable version of this document and inspiring us to provide it.
[PDF]
Printable Version

This demonstration uses a very simple ATM system to contrast the execution of a structure and an OO program. The ATM only lets a validated user do a single withdrawl or deposit, then returns the card. The “code” is written in a sort of pseudo Java/C++. The “design” of the program leaves many things unexplained and weird. The intent is to give a more intuitive feeling for how an OO program looks in execution.

The topology of a structure program is inherently different than the topology of an OO program. Modules are nested into a calling tree, as shown below:

The topology of a structure program.

By contrast, the topology of an OO program is inherently less ordered. Objects cluster together by those which communicate most frequently. Inter-cluster messages exist, but are less common than intra-cluster messages. Notice how much like a computer network this topology looks.

The topology of an OO program.
Materials
blank paper, heavy marker pen

Baseline Procedural Visualization for Comparison

Acting out

  • global data structures – desks or chairs
  • functions – students
  • main function – instructor
  • koosh ball – thread of execution (program counter)
  1. Stand students in a line facing classroom (code layed out linearly in memory).
  2. Label functions with pieces of paper students hold.
  3. Stand yourself at the end of the line, with a whiteboard nearby.
  4. Begin execution in main() showing the code for main() on the board.
  5. Pass the koosh ball along to each function as they execute.
int main(){
 
 while( 1 ){
 
 display(GREETING_MSG);
 card = block_for_card_input();
 
 display(PROMPT_FOR_PIN);
 pin = block_for_pin_input();
 
 if( verify_account(card, pin) == OK ) {
 
 display(main_menu);
 
 action = get_activity_selection();
 
 switch( action ){
 case DEPOSIT: deposit();
 break;
 
 case WITHDRAWL: withdrawl();
 break;
 }
 
 return_card();
 else {
 display(AUTH_FAILED_MSG);
 
 eject_card();
 }
 }
 }
 

Notice:

  • how relatively important the main() method is; lots of intelligence
  • how the main method has transaction logic in it.
  • global data is used by functions to avoid unwieldy passing of arguments.
  • the order of execution and use of machine/program is determined by the way the code is written.
  • several functions (get_pin, get_activity_selection) use the same hardware device (keypad).
  • functions are the units of modularity, organization, and encapsulation within the program.
  • global data is used by functions to avoid unwieldy passing of arguments.

Object Oriented

Acting out

  • Put five empty chairs in a scattered, random sort of pattern. This is the object space.
  • Start with empty chairs and main() method.
  • Call students to chairs as objects are instantiated and give them their object name on a piece of paper.
int main(){
 ATM atm;
 atm.init();
 atm.run();
 }
class ActiveDevice {
 public abstract void run();
 }
class ATM subclasses ActiveDevice {
// ivars
 private CardReader cardReader;
 private Display display;
 private Printer printer;
 private KeyPad keyPad;
 private SecurityGuard securityGuard;
// constructor (initialization)
 
 public ATM() {
 display = new Display();
 keyPad = new KeyPad();
 securityGuard = new SecurityGuard();
 cardReader = 
 new CardReader(display, keyPad, securityGuard);
 printer = new Printer();
 }
// methods
 
 public void init(){
 securityGuard.wakeup();
 }
 public void run(){
 Customer customer;
 
 Transaction transaction;
 
 while( 1 ){
 display.show(greetingMsg);
 customer = cardReader.waitForCustomer();
 if (customer.isValid()) {
 transaction = new Transaction(customer);
 transaction.start();
 }
 else {
 display.show(invalidCustomerMsg);
 cardReader.ejectCard();
 }
 }
 }
 }
class CardReader {
 private Display display;
 private KeyPad keyPad;
 private SecurityGuard securityGuard;
// constructor
 public CardReader(
 Display d, KeyPad k, SecurityGuard g) {
 display = d;
 keyPad = k;
 securityGuard = g;
 }
 public Customer waitForCustomer() {
 PIN pin;
 Card card;
 Customer customer = new Customer();
 card = blockForCardInput();
 display.show(promptForPINMsg);
 pin = blockForPINInput();
 customer.setCredentials(card, pin);
 if (securityGuard.validateCustomer(customer)) {
 customer.setValid(true); 
 }
 return customer;
 }
 }
 

Notice:

  • how relatively unimportant the main() method is.
  • how the main method doesn’t have any transaction logic in it.
  • how some devices are dumb (display) and some are smart (transaction).
  • how the cardReader is notified of the display and keyPad device objects.

The main program is usually minimal in an OO design. Booch quotes Meyer as saying, “Real systems have no top”, meaning that large complex systems are more naturally characterized as a collection of many services. As an example of that, here is the main program for a NEXTSTEP application (from the simplest to the most complex):

void main(int argc, char *argv[]){ [Application new]; if ([NXApp loadNibSection:"HRMan.nib"  owner:NXApp withNames:NO]) [NXApp run]; [NXApp free]; exit(0); }

Booch claims that the OO paradigm is applicable to the widest variety of problems. A point of confusion when moving from a procedure-oriented to an object-oriented mindset is that the algorithms don’t go away. This begs the question, “so what’s the difference?”

Think about the difference as this: The algorithms still exist (after all, the answer has to be computed somewhere) but they are encapsulated into an object which represents the thing in the problem domain most closely associated with that algorithm.

In a way, you can look at the individual methods of an object as procedural (with the exception that they can/will message other objects) and the overall organization of the program as OO. Work happens in an OO system when objects messageeach other, rather than when procedures are invoked.