This short paper will attempt to very briefly describe what OO (Object Oriented) means. Typically, by OO we mean employing classes, object and their relationships to solve an automation problem. This involves coding a program using an OO programming language. It also involves the larger challenge of selecting the classes, objects and their relationships using (OO) Analysis and Design. Some degree of Analysis and Design should precede all OO programming efforts.
Additionally, classic Structured Analysis, Design and Programming will be covered so as to highlight the differences between it an OO and because Structured Programming is still applicable to portions of OO. If you are already familiar with Structured Programming, you can skip over the next section and go to section 3, OO.
2. Structured Analysis, Design and Programming
An excellent source on Structured Analysis, Design and Programming, and one that many of you have, is the 4th Edition of System Analysis and Design Methods by Whitten and Bentley. It also has a couple chapters on OO Analysis, Design and Programming. For simplicity, let's just refer to Structured Analysis, Design and Programming as Structured Programming.
Here is a very brief synopsis of the classical phases of Structured Programming. The Analysis phase looks at the problem/solution in "logical" business terms and produces the Requirements. Next the Design phase comes up with a solution in "physical" computer hardware/software terms. Typically these phases have subdivisions. Analysis may have a Planning and/or a Preliminary Analysis and/or a Formal Analysis phase. Design may have a preliminary and/or a high-level design as well as a detail design phase. Then there is the Programming or Implementation phase, typically made up of coding, testing and debugging, which is frequently done concurrently. Finally, most software development projects have a Maintenance phase during which the software experiences enhancements, bug fixes and modifications dictated by environmental changes such as Operating System changes. For large projects the maintenance phase can last years and cost lots. Reducing the cost of maintenance has been one of the drivers of finding other approaches to software development. Of course another and currently popular approach is OO. A major difference between Structured Programming and OO is that Structured Programming handles data and process (functionality) separately and OO integrates the two.
Data vs. Process
A characteristic of Structured Programming analyses is a parallel Process and Data approach. Both approaches employ "divide and conquer", breaking the problem into smaller pieces. Data looks for entities (things about which the organization wants to save information). It uses Entity Relationship diagrams, ERDs. They capture the collections of data (Entities) and especially the relationships between the Entities (the business rules of the company). A scary term, called Data Normalization, is applied to the entities to reduce duplication. The end product can be a database or file structure. The process approach used to use a hierarchy of Data Flow diagrams, to capture the flow of data in a system/company and especially the transformation of the data by various functional processes. The resulting lowest level processes would be the basis for program modules (more about modules in a moment). While data analysis techniques have not changed much, and in fact are similar to OO Analysis, process techniques seem to be evolving away from DFDs and toward OO-like techniques of capturing the events that manipulate the data (Event Diagrams). Before discussing data vs. process in programming as against analysis and design, I need to review modularity.
Earlier I talked about the breaking the problem into smaller and smaller pieces. The idea is to break a complex task into several modules. The common name for a piece is a module. It is a piece of the solution that seems to hang together. For example, Accounts Payable would be a module of an accounting solution. It, in-turn, is broken into several functional sub-pieces or modules.
Each module is subdivided until it does not make any sense to subdivide any further. At this "lowest level" we change the term from modules to functions in C and C++ and methods in Java (both mean the same thing). Oh, so modules are just collections of related functions/methods? Yes and hopefully single-task functions. At the bottom we might have a module which handles the current balance called doBalance. doBalance might have two display functions, get_input and display_output, and a calculation function, calcBal. When we are done, we end up with a hierarchy of modules and functions.
Here are a few key concepts that apply to modules and functions. If you succeed in keeping functions single-tasked, you will be adhering to the principle of high cohesion within modules/functions. If you design modules/functions to stand- alone and if they don't need to exchange much data, you have low coupling between modules/functions. Also avoiding global variables aids both of these principals of modular programming. These techniques will also result in short functions. As the module size grows, one begins to doubt if it is only doing one task. If you employ these concepts when designing a solution to the problem and break the solution into a hierarchy of pieces using divide-and-conquer, you are doing modular programming.
Surprising to some is that Structured Programming principles of modules are still very applicable to OO programming within C++ OO functions and Java methods.
Structured programming was developed as a means to avoid unreadable "spaghetti" code that was being generated by programmers using a "goto" approach of coding. Structured programming was supposed to adhere to a top-to-bottom flow of the code which FORBID the use of the goto-like "JUMPS". The only "jumping" allowed, out of the sequencial process, were controlled within limited branch and loop constructs. In C, C++ and Java they are respectively if and switch branching and for, while and do while looping. As with many developments in programming, the reason was to reduce errors and maintenance costs. Structured programs would be easier to debug and enhance. Go to's are still discouraged. However, not as much in vogue any more is the strict adherence to top-to-bottom flow of the code. Commonly used exceptions are: continue, exit(), break (except in a switch) and multiple returns (which violates the rule of one entry/one exit in a function). They are used in most current texts, even though Structured Programming purists abhor their use. However the syntax for these jumps doesn't even exist in PASCAL, the popular structured programming language. Nevertheless, the current pressure to get the stuff out the door before it becomes obsolete has caused the avoidance of jumps not to be enforced in the workplace, except for the use of "go to's".
Structured Programming Summary
In summary, here is a very simple encapsulation of Structured Programming that you should abide by for small programs. Determine the data outputs (of major concern to the client), determine the data available for inputs and then decide on how to get there, the process(es) or functions to produce the desired outputs. The sequence of steps that you use (your algorithm) can vary, as long as they produce the desired outputs and use agreed upon inputs. Finally, keep your functions single-tasked and donÕt use Go-tos.
OO Analysis and Design
Two excellent texts for OO Analysis and Design, are UML Toolkit by Eriksson and Penker and Object Oriented Systems Development by Ali Bahrami (which also relies heavily on UML).
What is UML? UML stands for Unified Modeling Language. UML is an amalgamation of the teachings of three of the biggest names in OO Analysis and Design: Grady Booch, James Rumbaugh and Ivar Jacobson. They now work together in a company called Rational Software Corporation, which developed UML.
A major goal of UML is to have it used as the standard for modeling systems using OO concepts. Perhaps surprisingly, there is disagreement as to what constitutes OO concepts. Here is how I understand what is generally agreed to constitute OO.
Not surprisingly, implicit in OO, is that the problem/solution is broken into smaller and smaller pieces. Eventually, into single tasks. The pieces must work together. These pieces are called classes. However classes, unlike modules/functions, handle both data and process/functionality. One of OOÕs, most distinctive features is that it integrates the two.
If you have some background with procedural (non-OO) programming, think of a class as a structure or record that can contain functions or procedures as well as data members.
Classes, objects and their relationships are at the core of OO. OO Analysis and Design must capture them so that OO Programming can implement them. C++ and Java have the syntax to handle them while C does not.
A class is just an abstraction or a model of reality that captures the common behavior and attributes of real things you want to describe and use. To provide an illustration, say that we need a piece of a solution that creates and displays various GUI (Graphical User Interface) buttons that have different colors and sizes. Remember that a class is just an abstraction, a template, a blueprint, a model, which encapsulates and specifies the data, the properties (attributes) and the functionality, responsibility, operation (behavior) of these similar GUI buttons. So "Button" might be our class. By contrast, an object is a specific "instance" of a class. So a littleRedButton would be a specific instance or object of the class. Color would be an attribute, however red would be the state of the attribute color in the object littleRedButton. The ability to draw itself would be a class behavior and drawYourself() a function in C++ and a method in Java. Typical behavior is to get, add, change (manipulate) or display the object's data. Finally, many OO programs typically use more than one class and an object of the class. In our example, we might also have a large GreenButton instance of the Button class. Also the Button class objects might cause instances of a label class to appear on the screen. The relationships between the classes and objects are a crucial, if not the most crucial, aspect of OO, next to selecting classes. But before discussing relationships, letÕs review the other minimal characteristics of OO.
The challenge, of course, is what classes, objects and relationships to use. More on this shortly.
The other minimal characteristics of OO are encapsulation, inheritance and, polymorphism. Encapsulation means that the class contains both the attributes/data and behavior/functionality. Closely related is data hiding, i.e. that the class can hide data from other classes. There is syntax built into OO programming languages to do this. Inheritance means that a class can inherit, or reuse, or extend the behavior and attributes of a parent or "base" class. Polymorphism can have a range of meanings. At one end is the use of what are called overloaded functions and at the other end are virtual or over-ridden functions. But very simply, it means that a function can reuse the same name but obtain different behavior. For example a program could reuse "open" several times but the function/method "open" would act differently for a door, window, eye lid, etc. Unlike overloaded functions, virtual or over-ridden functions/methods only apply to inheritance. OK, back to the relationship between multiple classes and objects.
Object and Class Relationships
Greatly simplified, the relationships between classes and objects are either hierarchical, known as inheritance, or non-hierarchical. Hierarchical means a parent-child relationship exists. Non-hierarchical relationships typically mean that one class needs to know about another class.
Let me hasten to say that relationships do not have a standard set of terms. However one way to classify them is to use the age-old terms applied to structured programming modules, coupling and cohesion. Coupling describes the strength of connections or the number of messages exchanged. Good programming is characterized by low or loose coupling of modules and now classes. Cohesion describes the "conceptual unity" of the modules or classes. High cohesion is considered as better. Using these measures, one can break non-hierarchical relationships in to: Attribution, the weakest coupling. Then comes Association, followed by Aggregation/Composition.
Attribution models a "has a" relationship (attributes of classes). Some also refer to this as a "Weak" relationship, a relationship in which objects depend on one another but do not directly interact (there are no messages). Association is the most common and is usually based on one class "using" another class, i.e. "uses, sends to, gets from". Aggregation/composition means that one object contains or is "part of" another object, a car contains an engine and wheels are part of a car.
Although these are often depicted as relationships between classes, in fact they are between objects. By contrast, Generalization, the last relationship that IÕll discuss, is a class relationship.
Generalization is another name for inheritance and is often called the "is a kind of " or simply "is a" relationship. Some also refer to it as a generalization-specialization, with the superclass or parent being the generalization and the subclass or child being the specialization. It is defined at the class level and all the class' objects must comply.
I hope that this is more than enough to describe OO. Still unanswered is, "but what classes, object and relationships do I use"? But before we move on to OO Analysis and Design Tools and techniques, that help answer this question, how about a few OO truisms?
OO Analysis and Design Truisms
OO Analysis and Design Tools and Techniques
Some of the better known techniques, and the ones that IÕll comment on, are:
One of the main reasons for all these techniques is to aid in the determination of classes, objects and their relationships. Many or most of these techniques employ diagrams, often to portray the classes, objects and relationships they discover.
Identifying classes is the most difficult part of the process. Unfortunately, it is not just a matter of "look and you will find them". Plus there is no one or right solution. The selection process needs help, even for the simplest program.
Nouns (and noun phrases)
A popular technique, and one that can be readily used on the simplest projects, is to write a problem/solution statement and look for nouns (and noun phrases) as likely candidates for classes. Eliminate likely duplicates, ones that are outside the scope of the problem/solution and ones that are more like attributes of classes. Then see if some lend themselves to grouping. Finally you should have a fairly short list of likely classes (remember this is an iterative process and you may make changes). Now you need the classes' attributes and then their behavior. Finding the events the objects must respond to and the actions the objects must perform, is a technique for selecting behavior/methods. Continued refinement and further dividing and grouping are probably necessary. This is a simple approach and can be fairly informal.
There is not one specification for a use-case. They range from freeform narratives to highly structured dialogues with pre- and post-conditions (as is noted below).
One view is that use-cases are initiated by actors and describe the flow of events in the system that these actors set off. (The actors, by the way, are outside the scope of the problem/solution). The individual use-cases are normally done in plain text, but they can also be described by an activity diagram (described later) and/or elaborated on in a scenario. As usual, the terms and definitions are not standardized.
A use-case might be, "Make a call". However, "instantiation of a use-case is called a scenario." The scenario might be, " John Doe makes a call to the company's Help Desk that is taken by the Operator, who determines the nature of the call". A use-case diagram, as denoted in the illustration below, is a way to show the interaction among "actors" and use cases within a system.
You will also see "use-case" applied to a lengthly list of steps (the flow of events) that the analyst and/or programmer believe the actor goes through in doing the use-case. It might look like an expanded outline with the headings of Description, Preconditions, Basic Course (the primary list of steps/flow of events), Alternate Course(s), Post Conditions (the result), Assumptions and finally Issues.
Here are some quotes that further explain use-cases. "Through use-case modeling, the external actors, that have an interest in the system, are modeled along with the functionality that they require from the system (the use cases). The actors and use cases are modeled with relationships, and have communication associations with each other or are broken down into hierarchies." To quote another source, "a use-case is simply a transaction, or a sequence of related operations, that the system performs in response to a user request or event" (an actor). A use-case must always deliver some value to an actor, the value being whatever the actor wants from the system. Actors interact with the system by sending and receiving messages. A use-case is always initiated by an actor that sends a message to it.
Finally, use-cases are used to describe functional requirements so as to:
However, not until all use cases are described, is there complete knowledge to identify suitable relationships.
Class-responsibility-collaboration (CRC) cards
Although not part of UML, another popular technique is CRC cards. The goal of CRC modeling is also to find the classes. Often it starts with a written problem statement. A popular way to get candidate classes is to collect the noun and noun phrases from the summary statement. Responsibilities often come from the verbs.
The cards are just 3x5 cards or pieces of paper. The name CRC comes from the "Class", which you write on the front along with its "Responsibilities" and corresponding "Collaborations". On the rear you write its attributes and a short description of the class. To get Collaborations, you scan the list of responsibilities of each class and identify any other class it needs in order to fulfill its responsibility. Responsibilities can be the things a class needs to know or do.
Some advocate the use of CRC cards prior to or along with use-cases, to help discover and describe classes and collaborations. However, in either case, the next step, much like UML, is class diagrams for describing the classes (more on them shortly).
Patterns go way beyond finding nouns and "hoping insight and experience will take over". Patterns focus on relationships between classes and objects more than the classes and objects themselves. The supporters believe that many of the relationships that we come across can be described in terms of formalized design patterns. Pattern writing tries to rigorously describe abstract patterns of classes, which employ (reuse) commonly occurring design solutions and programming paradigms. It is much like trying to design hardware parts. The approach stems from Christopher AlexanderÕs work in architectural design, which he documents in A Pattern Language. The most well known patterns are those popularized in the "Gang of Four" (Gamma, Helm, Johnson, Vlissides) Design Patterns: Elements of Reuseable Object-Oriented Software. Each of their patterns has a name, the problems for which it is useful, the conceptual solution the pattern provides and finally the implementation trade-offs and consequences. The reason to use Patterns is because it promotes re-using existing, quality solutions. The downside is that learning patterns and employing them is not a trivial task.
A less abstract and rigorous set of patterns is often called a Framework. Frameworks can be a set of cooperating classes that an organization puts together so as to be able to do reusable design based on earlier efforts.
As classes are identified, they may be defined in an individual class diagram. The class is portrayed as a rectangle with the class name at the top, the attributes in the middle and the behavior or operations at the bottom. Object diagrams, some call them Object models, are also used and look very similar to class diagrams, perhaps with additional detail. Both Class and Object diagrams provide static views and depict the "things" that are handled in the system.
As additional classes are identified, the relationship between them must be identified. Below is a class diagram with five classes, depicted along with their relationships. Bond and Stock are inherited from Portfolio and have a hierarchical relationship (also termed generalization). The others are related in non-hierarchical relationships.
To this class diagram, could be added names describing the relationships, such as "handles" on the line between Portfolio and Trader with an arrow-head pointing towards Portfolio. Finally the diagram could be annotated with a 1..* next to Portfolio and a 1 next to Trader, indicating that one Trader handles 1 to many Portfolios. This is known as cardinality or multiplicity. It refers to the number of objects that participate in an association and whether their participation is optional or mandatory.
A drawing such as this, focused on one class/object, and with detail about the object (attributes and methods) and its relationships, might be called an Object model.
For problem/solutions that have an important temporal (time) aspect, there are also dynamic diagrams or models. These depict the "how", behavior and functionality over time. There are:
Sequence and collaboration diagrams, the popular Interaction diagrams, can be drawn from each other and there are automated tools for doing this. They depict the objects and the messages (interactions) between them. State diagrams show "the sequence of states that an object goes through over time in response to outside stimuli and messages". One last diagram worth mentioning is an activity diagram, a variation of the state diagram, but one that models an entire business process rather than one object. It can be used to show a view of the flows and what is going on inside a use-case.
This very brief paper tried to describe OO and OO Analysis and Design Some degree of Analysis and Design should precede all OO programming efforts. Additionally, classic Structured Programming was briefly covered so as to highlight the differences between it and OO and because Structured Programming is still applicable to portions of OO.
From a programmer's perspective, OO Analysis and Design can be used to help determine classes, objects and their relationship, which is what the programmer needs to code the program. Various techniques exist to aid in determining these but experience is the best aid. Also it is important to remember that the determination of classes, objects and their relationship can be difficult and a bit arbitrary. There is not one "right" answer and it is not a one-shot effort. Most techniques favor an incremental and iterative approach with additional refinement and detail being added. Probably, at the minimum, a use-case and an object model should be done. Finally, utilizing some of these techniques to get the classes, objects and their relationship down on paper before coding starts, saves time and money in the long run.
Return to the Java Help Page.