This article introduces Java through one of its most important featuresobject- oriented application design. The process of object modeling will be covered, using a sample application and an explanation of the Java code that supports the object model created.
Java is hot, but what makes it so hot? The source of that heat is object-oriented programming. The object-oriented nature of Java is not just a featureits the basic foundation of Java. The realization of long-term benefits from writing business applications in Java will be achieved only through sound object-oriented design. This article is the first in a series designed to teach Java programming in the context of object-oriented design.
The following material introduces the Unified Modeling Language (UML) for use as the standard graphical notation for object modeling. A small purchase order application will be explained from object design to Java code.
Object-oriented AnalysisUse Cases
Just like structured applications, an object-oriented project begins with analysis and then moves into design. The first phase of object-oriented analysis is the development of use cases. A use case is simply a written summary of a typical interaction between a user and a computer system to perform a discrete business task. For example: The order processor will search for the customer in the system first using the caller ID, as shown on the phone LCD. If the customer information is not found, the order processor will request the customers number. If the customer does not know his number, the customers company name will be used. If the customer information is still not found, the order processor will assume that the customer is not in the database and will then add that customer to the system.
Initially, enough use cases are developed to provide an overview into the scope of the application. Use cases should provide a clear understanding of what the user expects from the application. Often, the use cases are used for bargaining chips (I can get the application done two weeks earlier if I drop this caller ID thing and we just force the customer to know his number). And, as always, it is good to get it in writing.
Object Discovery
Using use cases to provide project scope, the application designer works closely with a domain experta user who is an expert in the business area of the proposed applicationto model the world by discovering the business objects that form the vocabulary of the problem domain (the application).
A business object is nothing more than a business entity. As a legacy application programmer, you might ask, Isnt this process of discovering business objects the same as the first step of relational database design? Yes, they are similar. A major part of both structured and object-oriented analysis is the identification of business entities. In the design phase, both object-oriented and structured methods define the attributes of entities and chart the relationships between those entities. But with object-oriented design, the behavior of an entity, as well as its attributes, is designed to be an integral part of that entity.
Take a moment to look at the object model of Figure 1. Then look at the entity relation chart in Figure 2. Both of these graphics model the same business entities except for a few extra objects in the model of Figure 1specifically Consumer and Company. Object-oriented analysis drills down further in the decomposition of entities by classifying them into hierarchies (more on that later). For now, understand that the identification of objects is the hardest part of object-oriented analysis and design. A well-designed object model is elegantly intuitive, but, as Descartes once said, The discovery of an order is no easy task. Yet, once the order has been discovered, there is no difficulty at all knowing it. To help clarify objects, you need a graphic design aid. This is where UML comes into play.
The object model of Figure 1 uses the notation specified by UML. For the past decade, each of the half dozen leaders in the object-oriented programming industry had its own published design methodologies, complete with dissimilar notations. In 1997, three of them, Booch, Jacobson, and Rumbaugh (collectively known as the three amigos), got together and collaborated on a standard graphical notationUML. The notation of UML is to be used to graphically express object-oriented designs. In the short time that UML has been available, it has already been widely embraced as the standard for object modeling.
The Purchasing Problem Domain
The purchasing applications UML in Figure 1 uses boxes to represent business entities or objects. Each object box has three sections: The top identifies the object, the middle lists the attributes of the object, and the bottom shows the operations (a.k.a. behaviors) that are associated with that object. The PurchaseOrder object, for instance, has order number and due date attributes along with operations to add line items to the order and to allocate inventory for the order. It also has an operation that has the same name as the object itselfPurchaseOrder. Operations such as this are special operations known as constructors because they are used to create an object and then set the initial state of that object.
Design with Class
A class is a set of objects that share a common structure and a common behavior. The Java implementation for the class of PurchaseOrder objects is shown in Figure 3. The PurchaseOrder class is the Java code designed to hold the attributes and the behaviors of purchase orders. This Java class contains the attributes that are in the UML object model of Figure 1: orderNumber and dueDate. Two other attributeslineItems and customerare
defined in the class but are not explicitly defined in the UML. Those attributes relate the PurchaseOrder object to other objectsPOLineItem and Customer. The UML graphically portrays these relationships with links to the other objects. Adding these objects as data members to the attribute section of the object box would be redundant and would also clutter up the object model.
Note that the link from PurchaseOrder to POLineItem has a diamond at the top of the link. The diamond represents aggregation; you have multiple line items for a purchase order. Thats why, in the Java class code, the name of the array of POLineItems (as represented with the Java dynamic array data typeVector) is plural.
Behavioral Relationships
Lets compare the object models PurchaseOrder to POLineItem and Customer relationships (Figure 1) with the entity relation chart (Figure 2). The attributes of the PurchaseOrder entity are represented with data fields of a record format in Figure 2. The custNumber field of PurchaseOrder is tagged as a foreign key to show the dependency to the Customer entity. The PurchaseOrder entity of the entity relation chart has no POLineItem array as the UML didthat is handled with the relational database design. The POLineItem entity contains the orderNumber foreign key to relate each line item to a specific purchase order.
The UML and the entity relation diagrams appear to be quite similar. The major difference is the object models encapsulation of an entitys behavior to an object. That is the value-add of object-oriented programmingthe ability to encapsulate the definition of the procedures that manipulate that state of an entity within the same discrete storage location as its data. The third section of the object box contains the operations of that object. These operations are the names of functions that will be defined in a Java class with the code that implements the computer simulation of the behaviors of an object. The Java class code of Figure 3 shows the function definitions for the operations of a purchase order: allocate, addLineItem, and PurchaseOrder. These functions are implemented to accept specific external parameters and then provide the objects behavioral code between the functions curly braces. Unlike RPG and COBOL, there are no global variables in Java. The functions that constitute a class have access only to those fields, those data members, those attributes (these three terms all mean the same thing) that are a part of that class. A classs only connection to the outside world is from the external parameters that are passed to those functions.
Abstract Data Types
The Java class definition of a purchase order object is what is known as an abstract data type. We are all familiar with a number of general data typesdata types like integers, floats, and the ubiquitous zoned-decimal and packed-decimal of RPG. These data types all have attributes: their numeric values, and, for zoned and packed, their decimal count. Just like Java classes, these basic data types have operations associated with themaddition, subtraction, multiplication, division, and, of course, assignment. In RPG, COBOL, or CL, you define a variable as a particular data type. For example, with CL, you might have the following decimal data type variable declaration:
DCL &MONEY *DEC LEN(9 2)
The variable MONEY may then invoke the implicit addition and assignment operations:
CHGVAR &MONEY VALUE(&MONEY + 5.4)
With object-oriented programming languages, you define your own data types (except for a few built-in ones). These abstract data types are designed by you to encapsulate the attributes that represent the state of an entity along with the operations that modify the state of that entity.
Construction
This articles definition of a purchase order Java class is an abstract data type. That is, the fields and functions that make up a class form an abstraction of an entity. That Java class can then be used as a user-defined data typehence the term abstract data type. For example, the Java PurchaseOrder class name is used as an abstract data type to declare the type of a Java variable in the following statement:
PurchaseOrder poVariable;
But before you can use this purchase order variable, you must first create it with an object-oriented process known as construction. The poVariable, until it is constructed, is considered a null objectit has not been assigned to represent a particular business entity, and it does not contain any data. It doesnt even have storage reserved to contain that data. To construct a Java object, you use the class constructor of the abstract data type of the variable to be created. For the poVariable class variable, you use the PurchaseOrder constructor function passing the required parameters, as shown in Figure 3 (remember that a constructor function has the same name as its class). That operation (a.k.a. function) takes an integer order due date value and a customer object. Constructors are special functions because they are used to create an object instance of a class. In Java, an object is created by using the reserved word New followed by the name of the constructor function of the object to be created along with its required parameters:
poVariable = new PurchaseOrder(1298, aCustomerObject);
Javas New operator handles the storage allocation for the object, and the classs constructor function is implemented with the code necessary to set the initial state of that object. For example, the purchase order constructor first sets its due date attribute to be equal to 12/98 and then sets its customer attribute to reference the passed customer object. The PurchaseOrder constructor then creates the lineItems vector attribute. Note that the Vector class is a base part of Java and provides an abstract data type of a dynamically sizable array. As you can see in Figure 3, the constructor function for the Vector class takes no parameters, and the New operator returns a reference to the object created by Vectors constructor. Likewise, when the PurchaseOrder constructor completes, poVariable is set to reference the newly created purchase order object.
Class vs. Object
The terms class and object are being thrown out to you in such a seemingly random fashion that they may appear to be arbitrary. But there is a difference between a class and an object.
A Java class is the code that represents an entity, and an object is a specific instance of an entity. A class is an abstract data type that can be thought of as the mathematical set of all objects of that data type. An object, on the other hand, is one instance of an object of that set. A class is the definition (or pattern or template) for an object, and an object is the physical manifestation of that definition (or pattern or template). An object has its own state, behavior, and identity.
To use an AS/400 database analogy, a class could be compared to a record format. That record format, like a class, has fields for the representation of the attributes of entities. An object could be compared to a single record. The values of the fields in that record contain the state of a specific entity, and the key of that record holds the unique identity of that entity. The behavior of the entity...well, here, the analogy breaks down. This is one of the advantages of object-oriented programmingthe behaviors of an entity are encapsulated in the object that represents the entity.
No Object Is an Island
An object interacts with the outside world through its functions. Values and objects are passed as parameters, and the functions return an object (technically, a function can also return a simple data type like an integer or a float rather than an object). The UML notation for operations shows the return data type. For instance, the Customer objects checkCredit function returns an integer. Some functions return nothing, which is represented with the Java keyword Void.
Remember poVariable? The routine that declared that class variable interacts with the PurchaseOrder object by invoking the desired operation using the Java syntax of the variable name, the dot operator, and the function name followed by any required parameters. For instance, look back at the purchase order classs addLineItem function in Figure 3. The purchase orders line items attribute, lineItems, invokes the Vector classs addElement() function. This function adds an element to the lineItems dynamic array. That element will then reference the purchase order line item object passed to Vectors addElement() function:
poVariable.addLineItem(289, 3);
This is the first level of object-oriented programming with Java: You use classes as abstract data types to declare class variables. Through those variables, you can invoke the class functions that encapsulate the business rules for the entities represented by that class. A well-designed class encapsulates the operations of a business entity by hiding the complexity of the class implementation from other programmers who merely want to use that class. Realize that the user in this case is another programmer who uses the class as an abstract data type.
As our PurchaseOrder class demonstrates, Java classes themselves may contain other classes and may also receive object references as function parameters. The sequence of object function invocation can therefore become quite complex. To graph the intricacies of nested object function invocations, designers use a different UML notation called sequence diagrams to show how objects interact to support a specific use case. Sequence diagrams will be covered in detail in a later installment of this series.
Three Levels of Object-oriented Programming
The concepts of object-oriented programming are often broken down into three major areas: encapsulation, inheritance, and polymorphism.
Encapsulation was briefly covered above. Inheritance relates to deriving a new class from the definition of an existing class, thus inheriting all the attributes and behaviors of its parent class. The new object definition then has more specific behavior added. The Company and Consumer classes of Figure 1, for example, inherit the address, custNumber, and name attributes from the Customer class, as well as inherit the checkCredit operation. You can think of the parent class as being a generalization of a related business entity and the derived classes as conforming to that generalized API. Polymorphism, the most difficult concept of object-oriented programming to grasp, is
when a program dynamically performs behavior specific to objects from various levels of an inheritance tree. Because inheritance is a kind of generalization of an API, polymorphism acts as a kind of substitution where any object from an inheritance tree that conforms to the same generalized API can be substituted for a class variable of a related data type.
Think Objects
This is but a brief overview into object-oriented design strategies. You have seen how the discovery of business entities in object-oriented design is very similar to the same process in database design. You have been introduced to the use of basic UML for the clarification of an object model. You have also seen how a Java class is coded from the design of that object model, how a Java object is created, and how a Java object interacts with the outside world.
I know that I have only kind of covered encapsulation, inheritance, and polymorphism, but these object-oriented concepts will be covered in detail in a subsequent article in this series. These future articles will continue to expand on the use of UML in object design. They will also continue to show and explain the Java code. For now, go back to your legacy applications, but dont ever look at a record format again without thinking, What operations modify the state of this entity?
Figure 1: The purchasing applications object model using UML
private static int lastLineNo = 0;
Item item ;
public void allocate(){
item.allocate(); }
public POLineItem( int itemNo, int qty){
}
}
public class Item {
private int itemNo;
private int allocated;
private int onOrder;
private int onHand;
public void allocate(){/*code */}
public void adjustInv( int amount){/*code */}
}
public class Customer {
private String address;
private String custNumber;
private String name;
public int checkCredit(){
return 10000;
}
}
public class Consumer extends Customer {
private String creditCardNo;
public void invoice() {/*code */}
}
public class Company extends Customer {
private String contactName;
public void invoice(){/*code */}
}
Figure 3: The purchasing applications Java code
LATEST COMMENTS
MC Press Online