CSE 283 Introduction to Object Oriented Design

Barbara Nostrand, Ph.D.

Electrical Engineering and Computer Science


Object Oriented Design

Your first course in software engineering probably emphasized structured programming.  Your programs probably consisted of collections of functions.  In Object Oriented Programming,  programs consist of collections of classes.  Instead of functions we have either static methods which are attached to classes or instance methods which are attached to individual objects specified by classesObjects are not actions they are entities.  Consequently,  Object Oriented Design begins by identifying what objects are needded and sorting them into classes

  1. Identify the problem's objects. 
    1. If an oabject cannot be directly representing using the existing primitive types or library classes: 
      Design a class to do so. 
    2. If two or more classes share common attributes: 
      Design a common class to store their common attributers and have the specific classes extend this common class. 
  2. Identify the operations for each of your objects. 
    1. Define or identify a method for each of these operations. 
    2. Simplify system design by placing each new method definition in as general a class as possible so that it can be inheritted as often as possible. 
    3. If you can not find a single best class in which to define a method,  consider specifying it in an interface to enforce compatibility between each of your method's definitions. 
    4. Simplify method design by defining your new method in a class where your new method can inherit as many its compenents as possible. 
    5. If necessary,  have your child classes override methods inheritted from parent classes
    6. In general,  do not declare attributes protected.  Instead,  declare them private and declare protected accessor and mutator methods instead. 
    7. Do not give parameters or methods non-intuitive names.  If your class needs to use both a child version and a parent version,  just give both of them the same name.  Just qualify the common name with super. and whenever you need to access the parental version.  Further,  you can access the version attached to the current object by attaching the this. qualifier. 
  3. Develop and implement algorithms to implement your operations and manage your objects. 

Discovering Classes

Objects and Strings

Thus far,  we have mostly been handling input and output of strings and primitive data elements such as integers.  However,  we want to be able to dynamically handling our objects.  There are two parts to this.  We need to support input from streams and we want to be able to dynamically specify what class we are constructing. 

  1. We can handle String based input for our class simply by specifying a constructor which accepts a single String parameter. 
  2. We can use a static Class method to construct an arbitrary object by passing the name of the target class as a String parameter: 

    Class.forName(StringVariable).newInstance()

Reusing Designs

Our goal is to do as little design and implementation as possible by reusing previous designs.  You achieve this in Object Oriented Design by designing specialized classes which extend more general classes.  And,  by carefully discovering,  designing,  and implementing general classes.  In Java,  Object is the core class which ultimately all of the other classes either directly or indirectly extend.  When a child class extends a parent class,  it inherits all of the attributes an methods of the parent class.  This means that you can avoid designing or implementing attributes or methods which belong to an already implemented class.  All you have to do is have your class extend a class which already has some of the attributes and methods that you need.  But,  what do you do if a method defined for your parent class doesn't quite work the way you want it to?  All you need to do is is override the parent method by redefining it your child class. 

Using CRC Cards to Manage Classes

CRC stands for “classes”,  “responsibilities”,  “collaborators”.  Once you have completed a set of CRC cards for your application,  you should continue your analysis and design activity by developing class and method charts similar to those we have been using in the excercises.  UML (Unified Modeling Language) diagrams can help you keep track of class inheritance and class dependencies.  The CRC card method is intentionally informal.  The CRC card method proceeds as follows: 

Designing and Implementing Classes

Developing and Documenting Methods

While you may be tempted to immediately start writing the final code for your various methods one method at a time,  actual software practice suggests that this is a poor strategy.  Instead,  you should begin by embedding your documentation into your source file,  and then systematically fill in the executable code.  You should do each of the following activities before you become very involved in writing the final version of the executable statements in your method: 

  1. You should begin to develop a method by copying the external specifications and algorithm descriptions into your source file as comments.  The various parts of your method should appear immediately after the corresponding comment that you created at this stage. 
  2. Next,  create the calling sequence (access and ownership qualifiers,  return type,  method name,  parameter list,  and optional throws notification. 
  3. Follow the calling sequence with a statement block containing an appropriate dummy return statement if required.  This will allow you to call the method before it is finished. 
  4. Further,  you should write your Javadoc comments at this time.  These will include at a minimum a brief description of the method,  the return type,  and the calling sequence.  For example: 
    /**
        Represents Rational Numbers Q in reduced form. 
    */
    public class Fraction {
        private int numerator, denominator; 
    
    /** Add a Fraction
        @return a new Fraction containing the sum of the Fraction object and the Fraction passed as
                a parameter. The new Fraction is returned in reduced form. 
        @param fraction the Fraction to be added to the contents of the local Fraction object.
    */
        public Fraction add(Fraction fraction) {
           return new Fraction(this.numerator()*fraction.denominator()+fraction.numerator()*this.denominator(),
                               this.denominator()*fraction.denominator());
        }
    */

Using Diagrams

Thus far,  you have probably been getting by without drawing very many pictures.  However,  diagrams can help you design and implement both faster and more reliably.  There are several kinds of diagrams that you have already met in this course.  First,  there are class hierarchy diagrams and object utilization diagrams.  These are common to Object Oriented Development.  However,  you have also met data structure diagrams.  You should make it a habit to draw this sort of diagrams when implementing data structures.  They will help you correctly sequence handing off links from one object to the next.  Remember,  you must never loose track of an object and in particular a Node,  for if you do,  you will not get it back. 

Extreme Programming




Last modified: 2007 NOV 12
bnostran@syr.edu