Previously we presented how to model classes and objects. Classes define attributes and operations. The purpose of this chapter is describe operations in the object model. The major topics are:
A class defines attributes and operations. The purpose of this section is describe operations. We will present how to identify operations, show operations on a class diagram, describe operations in a class specification, and generate C++ code for operations with a CASE tool.
An operation is a function, action or set
of actions. An operation does work. It accomplishes some action.
For example, a simple operation of a car is to setGasQuantity".
A more complex operation is to "start" the car. An operation
is implemented as a function in C++. There are many forms of operations.
An object operation uses or modifies an object attribute.
SetGasQuantity is an object operation because it modifies the
gasQuantity attribute. A class operation uses or modifies
a class attribute or affects the class as an entity. Examples
of class operations are constructor operations to create
an object instance and destructor operations that eliminate
an object instance. In C++ a constructor function initializes
an object's attributes and a destructor function deletes an object.
A modifier operation modifies or updates an attribute value.
A modifier operation can modify an object attribute or a class
attribute. A very simple modifier operation is "set attribute
value". An inquiry operation uses an attribute value
but does not modify or update the attribute value. Typically,
an inquiry operation returns an attribute or an object. A very
simple inquiry operation is "get attribute value". Simple
get and set operations are called accessor operations.
The simplest specification of an operation is the class name,
operation name, input parameter class and object name, and output
(return) object class name. The table below shows several operations.
Table Sample operations.
---------------------------------------------------------------------------------------------------------------------------------
Class Operation Input Parameter Output Remarks
Name Name Class and Object (Return) Class
---------------------------------------------------------------------------------------------------------------------------------
Car start None None Modifier
Car setGasQuantity Integer aGasQuantity None Modifier
Car getGasQuantity None Integer Inquiry
Customer evaluateCredit Integer currentSalary Boolean Modifier
Customer setCreditOK Boolean aCreditStatus None Modifier
Customer getCreditOK None Boolean Inquiry
Product setDescription String aDescription None Modifier
Product getDescription None String Inquiry
Order setQuantity Integer aQuantity None Modifier
Order getQuantity None Integer Inquiry
----------------------------------------------------------------------------------------------------------------------------------
Operation access is the degree that an operation can be invoked from outside the class. The forms of access in this book are based upon C++ access definitions. They are applicable to other object-oriented languages. Private access is the most restrictive access. With private access an operation can be invoked from within the class only. That means that an object of a different class cannot directly invoke a private operation. Protected access is a less restrictive access than private access. With protected access an operation cannot be invoked by an object of another class. However, protected access has special rules that permit access a subclass operation to invoke a protected operation in a superclass. Public access is the least restrictive form of access. With public access an operation can be invoked by an object of another class. Public operations define the public interface and the behavior of an object.
To identify operations ask the following questions for each class. What are the actions and behavior of objects of the class? Peter Coad and Ed Yourdon suggest that the developer consider himself as an object of the class [Coad-91]. Ask the questions: As an object of the class, what do I do? As an object of the class, what are my responsibilities? As an object of the class, what is my behavior, e.g. what messages do I respond to?
Operations are shown on class diagrams. In the Rumbaugh OMT and the Coad-Yourdon class diagram operations are shown in the lower section of the class symbol. For simplicity, show operation names only as shown in the figure below. Alternatively show the operation name, input parameter class and name, and output (return) class/type.
The operation specification lists important text
information for each operation. Its purpose is to state adequate
information to document and to code each operation. We will first
present a CASE tool specification input form, define the specification
information, and present a sample report. The steps to create
the attribute specification using a CASE tool are listed below.
>> Run the CASE tool from Windows
>> Select "File - Open" e.g. c:\car.omt
>> Double click on a class, e.g. Car
>> Double click on an operation in the class, e.g. start to bring up the operation specification form
>> Enter operation information, e.g. description, access, etc.
>> Optionally enter "Code", e.g. C++ statements for expressions, rules, algorithms, etc.
>> Select "Generate - Generate Class Report and enter the report script, e.g. RPTOPER.SCT or TABOPER.SCT
>> Select "File - Edit File" and enter the report file name to view the report
The figure below is a sample attribute form in a CASE tool for the operate operation. The figure below is a sample operation specification form in a CASE tool.
The operation specification holds information on
each operation. Operation information may include the information
based upon the operation specification in Object-Oriented Design
with Applications by Grady Booch [Booch-94]. The specification
items, such as preconditions, will be discussed in the functional
model. Some information is provided that may be placed in a user
field in the CASE specification form above. State information
on each of the following specification items as required:
Check boxes are provided to designate an operation as virtual, static, const, pure virtual, or procedure. These are used in C++ and other code generation. A user may enter C++ source code by hitting the Code Button. This button opens up a simple editor in which the user only need enter the lines of code contained inside the brackets of the function. A user may "Import C++" to import a function body from a .CPP file and may "Save to Memory" to save the function body code in memory. The following are additional information items that may be collected for an operation.
To access the operation specification information,
you need to know the script variable for each piece of information
in the operation specification input form. The following are sample
script variables from the operation specification in a CASE tool.
A brief description states what occurs when the script variable
appears in a script. Operation variables access operation information.
Since there are multiple operations for each class, these variables
are used within the [] (Repeat Operator). For example, the following
script statement prints out the operation names in each class
[OPERATION_NAME, ].
OPERATION_NAME Prints operation name
OPERATION_RETURN_TYPE Prints operation return type
OPERATION_ACCESS Prints operation visibility
OPERATION_TRANSFORMATION Prints transformation (formula)
OPERATION_PRECONDITION Prints precondition
OPERATION_POSTCONDITION Prints postcondition
OPERATION_EXCEPTION_TYPE Prints exception type or class
OPERATION_EXCEPTION_NAME Prints exception name
OPERATION_CLASSIFICATION Prints classification
OPERATION_CONCURRENCY Prints concurrency
OPERATION_CODE Prints code
OPERATION_COMMENT1 Prints comment 1
OPERATION_COMMENT2 Prints comment 2
OPERATION_COMMENT3 Prints comment 3
OPERATION_CPP_VIRTUAL_BASE_CLASS Prints virtual if a virtual function appears in the class
CPP_OPERATION_VIRTUAL Prints the virtual box if checked
CPP_OPERATION_CONSTANT Prints the keyword const if checked
CPP_OPERATION_STATIC Prints the keyword static if checked
CPP_OPERATION_PURE_VIRTUAL Prints = 0 if checked
PASCAL_OPERATION_VIRTUAL Prints virtual ; if the virtual box is checked
CPP_OPERATION_PARAMETERS Prints operation parameters in C++ format, e.g.
Class/Type Name Parameter Name - int aNumber
A CASE tool may have different script variables to print out parameter information for a specific language, e.g. PASCAL_OPERATION_PARAMETERS, ADA_OPERATION_PARAMETERS, C_OPERATION_PARAMETERS, etc.
A sample operation specification for the "operate"
operation is as follows:
- Operation Name: operate
- Operation Return Type/Class: none
- Operation Parameters: int aSpeed
- Operation Access: public
- Operation Transformation: speed = aSpeed; rpm = 50 * aSpeed
- Operation Precondition: aSpeed <= maxSpeed
- Operation Postcondition: gasQuantity < oldGasQuantity; speed == aSpeed
- Operation Exception Type: string
- Operation Exception Name: noGasError
- Operation Classification: modifier
- Operation Concurrency: Sequential
- Operation Code: N/A
- Comment 1: N/A
- Comment 2: N/A
- Comment 3:
N/A
The abbreviated script (RPTOPPRE.SCT) to generate
this report from the class diagram is shown below.
[Operation Name: OPERATION_NAME
Operation Return Type/Class: OPERATION_RETURN_TYPE
Operation Parameters: CPP_OPERATION_PARAMETERS
Operation Access: OPERATION_ACCESS
Operation Transformation: OPERATION_TRANSFORMATION
Operation Precondition: OPERATION_PRECONDITION
Operation Postcondition: OPERATION_POSTCONDITION
Operation Exception Type: OPERATION_EXCEPTION_TYPE
Operation Exception Name: OPERATION_EXCEPTION_NAME
Operation Classification: OPERATION_CLASSIFICATION
Operation Concurrency: OPERATION_CONCURRENCY
Operation Code: OPERATION_CODE
Comment 1: OPERATION_COMMENT1
Comment 2: OPERATION_COMMENT2
Comment 3: OPERATION_COMMENT3 ]
The following is sample additional information that may be collected in the user fields.
- Abstract/Normal - normal
- Implementation: C++ function
- Applicable Invariant: None
- Time: Low
- Space: Low
- Description: operate calculates the rpm and sends the rpm to a Motor object
A sample operation table is shown below.
| Class Name | Operation Name | Input Para-meters | Precondition
/Exception | Transformation | Postcondition
/Exception | Return Type |
| Car | start | gasQuantity > 0/noGasError | gasQuantity = gasQuantity - .1 | gasQuantity < oldGasQuantity
/calculationError | void | |
| Car | operate | int aSpeed | aSpeed <= maxSpeed /speedHighError |
gasQuantity = gasQuantity - .1; speed = aSpeed; rpm = 50 * aSpeed | gasQuantity < oldGasQuantity /calculationError; speed == aSpeed /calculationError | void |
| Car | stop | speed = 0 | speed == 0/stopError | void |
The script (TABOPPRE.SCT) to generate this table from a class
diagram is shown below.
SCRIPT_NOREPEAT_HEADER_BEGIN
Class Name, Operation Name, Input Parameters, Precondition/Exception, Transformation, Postcondition/Exception, Return Type SCRIPT_NOREPEAT_HEADER_END
[CLASS_NAME, OPERATION_NAME, CPP_OPERATION_PARAMETERS, OPERATION_PRECONDITION, OPERATION_TRANSFORMATION, OPERATION_POSTCONDITION, OPERATION_RETURN_TYPE]
Once the class diagram and operation specification
forms have been completed, then C++ code can be automatically
generated with a CASE tool. We are briefly presenting how to code
operations in C++ to be able to understand and modify the generated
C++. Operations are coded in C++ as function members. The table
below is the comparison of the O-O modeling terms and C++ terms
for operations.
Table O-O modeling and
C++ terms for operations.
---------------------------------------------------------------------
O-O Modeling C++
---------------------------------------------------------------------
object operation function member
class operation static function member
input parameter argument
output (return) parameter return type or class
exception exception
---------------------------------------------------------------------
There are object and class operations. An object
operation affects only an object of the class. For example, an
object operation is to get or set an object attribute value. To
code an object operation in C++, declare a function member in
the following form: <return class or type> <operation
name> (<argument class or type> <argument object>,
...). The following is a sample C++ function
member declaration: void operate (int aSpeed).
A class operation affects all objects of the class.
For example, a class operation is to get or set a class attribute
value. To code a class operation declare a static function member
in the following form: static <return class>
<operation name> (<argument class or type> <argument
object>,...). The following is a sample C++
static function member declaration: static
int getMaxNumberPassengers().
Based upon the class diagram in the figure below,
the listing is the generated C++ code from a CASE tool without
get and set accessor function members.
Listing Generated C++
code from a CASE tool.
///////////////////////Car Class Declaration - car.h file////////////////
#ifndef __CAR_H
#define __CAR_H
class Car
{ int speed;
public:
Car () : speed(0) { } //Constructor
void start () ; //Public function member
void operate (int aSpeed); //Public function member
void stop () ; //Public function member
~ Car ( ) { } //Destructor
};
#endif
////////////////////////Car Class Function Definitions - car.cpp/////////
#include "Car.h"
void Car::start() {
}
void Car::operate(int aSpeed) {
}
void Car::stop() {
}
////////////////////////Main Function///////////////////////////////////
#include "car.h"
int main ()
{ Car car1; //Creates car1 object
car1.start(); //Invokes start operation
car1.operate(55); //Invokes operate operation
car1.stop(); //Invokes stop operation
return 0;
}
This code was generated with a CASE tool script previously presented.
Sample input and output functions C++ are shown in
the diagrams and code listing below. To code a class in C++ code
the class declaration in the header file, code the function definitions
in the source code file, and code a main (test) function in a
source code file. Key aspects of the class declaration are shown
on the left. This information class diagram shows that a class
declaration should have a #include statement, a class name, data
members, a constructor, function members, input insertion operator
(operator>>), output extraction operator (operator<<),
and a destructor. The class diagram on the right shows sample
C++ identifiers that are also in the code listings.
Key aspects of coding a class with input and output operators are:
- Declare #include compiler directive, e.g. #include <iostream.h>
- Define input function for text stream input - C++ insertion operator>> for use with cin e.g. friend istream& operator>> (istream& is, Car& aCar);
- Define the output function for text stream output - C++ extraction operator<< for use with cout<<, e.g. friend ostream& operator<< (ostream& os, Car& aCar)
- Define a main (test) function with cin >>
and cout << statements
A listing of a class with input and output functions
is below.
Listing Class with Input
and Output Functions
// Class: Car //ANSI C++
#ifndef __CAR_H //Required for current class
#define __CAR_H
#ifndef __IOSTREAM_H //Required for cin and cout
#include <iostream.h>
#endif
class Car
{
int speed; //Attribute data member
public:
Car () : speed(0) { }
friend ostream& operator<< (ostream&
os, Car& aCar); //Operator<< for cout
friend istream& operator>> (istream&
is, Car& aCar); //Operator>> for cin
void operate () ;
~ Car ( ) { } //Destructor - Delete any pointer data members
//that used new in constructors
};
#endif
//////////////////////////.cpp file//////////////////////////////////////////////
#include "Car.h"
// Functions for class Car
void Car::operate() { }
ostream& operator<< (ostream& os, Car& aCar) //Operator<< extraction for cout
{ os << "Object Attribute Values - Class Car" << "\n";
os << "speed: " << aCar.speed << "\n";
return os;
}
istream& operator>> (istream& is, Car& aCar) //Operator>> insertion for cin
{ cout << "\nEnter Object Attribute Values or 0 - Class Car";
cout << "\nEnter speed : " << "\n";
is >> aCar.speed;
return is;
}
#include "car.h"
#include <iostream.h>
int main () {
Car car1; //Invokes default constructor
cin >> car1; //Invokes input function >>
cout << car1; //Invokes output function <<
return 0; //Default destructor is invoked
}
/* Sample Output
Enter Object Attribute Values or 0 - Class Car
Enter speed: 55
Object Attribute Value - Class Car
speed: 55
*/
Sample constructors, destructors, and operators in
C++ are shown in the diagrams below. Key aspects of the class
declaration are shown on the left. This information class diagram
shows that a class declaration should have a class name, data
members, a default constructor, a constructor with arguments,
a copy constructor, assignment operator (operator=), equality
operator (operator==), function members, and a destructor. The
class diagram on the right shows sample C++ identifiers that are
also in the code listings. The C++ compiler provides a default
constructor, copy constructor, and assignment operator=.
Key aspects of coding a class with constructors, destructor, and operators are:
A listing of a class with constructors, destructor,
and operators is below. The C++ compiler provides a default constructor,
copy constructor, assignment operator=, and destructor. The copy
constructor and assignment operator= provides a member by member
assignment including pointers. The C++ compiler does not provide
a default equality operator==. A CASE tool with a scripting language
provides you the capability to precisely generate the constructors,
destructor, and operators. In this tutorial, we follow the C++
coding guidelines in Scott Meyer's book Effective C++ [Meyer-92].
Listing Class with Constructors,
Destructor, and Operators
// Class: Car //ANSI C++
#ifndef __CAR_H //Required for current class
#define __CAR_H
class Car
{ //Attribute data member
int speed;
public:
Car () : speed(0) { //Default constructor - Ensure correct initial values
}
Car ( int aspeed ) //Constructor with arguments
: speed (aspeed) { }
Car (const Car& aCar ) //Copy constructor
{ speed = aCar.speed;
}
Car& operator= (const Car& aCar); //Operator= Assignment Operator
int operator== (const Car& aCar) const; //Operator== Equality Operator
void operate () ;
~ Car ( ) { } //Destructor - Delete any pointer data members
//that used new in constructors
};
#endif
//////////////////////////.cpp file//////////////////////////////////////////////
#include "Car.h"
void Car::operate() {
}
Car& Car::operator= (const Car& aCar) //Operator= Assignment Operator
{ if (this == &aCar) return *this;
speed = aCar.speed;
return *this;
}
int Car::operator== (const Car& aCar) const //Operator== Equality Operator
{ return (
(speed == aCar.speed)
);
}
#include "car.h"
#include <iostream.h>
int main ()
{
Car car1; //Invokes default constructor
Car car2 (car1); //Invokes copy constructor
Car car3 (55); //Invokes constructor with arguments
car1 = car3;
//Invokes equality operator
if (car1 == car3) cout << "Cars are equal." << "\n";
else cout << "Cars are not equal." << "\n";
return 0; //Default destructor is invoked
}
Cars are equal.
How we model operations can affect the quality of
the resulting software. Correctly identifying and specifying operations
can contribute to creating high quality software that is correct,
reliable, extendible, and reusable. For example, specifying correct
operation transformations and correctness assertions (rules) supports
correctness and reliability. These will be presented in the chapter
on the functional model.
The two software quality techniques most applicable to operations are encapsulation and strong cohesion. We can support encapsulation (information hiding) by allowing the minimum number of public operations that a class requires. We can support strong cohesion by identifying operations that are related together in a class. There should be no unneeded or out-of-place operations. We can check for strong cohesion by examining each operation in a class to ensure that it necessary for the class. For example, the operation "calculate the national debt" is out-of-place in a customer class.
To model classes and objects, attributes and operations must be identified and described. An attribute is a characteristic or property of an object. An operation is an action or set of steps to accomplish something. Attributes and operations are graphically shown on the class diagram. They are described in the attribute specification form and operation specification form. A CASE tool is useful to create class diagrams and specification forms. A CASE tool may generate source code for the declaration of attributes and operations in the class declaration. A CASE tool may generate fill-in code templates which must be updated with code statements to accomplish the purpose of each operation.