October 11th, 2013
Software Development Activities
Four basic development activities:
- establishing the requirements
- creating a design
- implementing the design
- testing
This sequence would be ideal but it almost never completely linear in reality.
They overlap and interact.
Software requirements specify what a program must accomplish: a document called a functional specification.
The client will often provide an initial set of requirements. However, these initial requirements are often incomplete, ambiguous, and perhaps even contradictory.
The software developer must work with the client to refine the requirements.
A software design indicates how a program will accomplish its requirements.
The design specifies the classes and objects needed in a program and defines how they interact. It also specifies the relationships among the classes.
During software design, alternatives need to be considered and explored. Often, the first attempt at a design is not the best solution.
Implementation is the process of writing the source code that will solve the problem.
Too many programmers focus on implementation exclusively when actually it should be the least creative of all development activities. The important decisions should be made when establishing the requirements and creating the design.
Testing is the act of ensuring that a program will solve the intended problem given all of the constraints under which it must perform.
Identifying classes and objects
A fundamental part of object-oriented software design is determining the classes that will contribute to the program. We have to carefully consider how we want to represent the various elements that make up the overall solution. These classes determine the objects that we will manage in the system.
When designing classes, objects are generally nouns.
The nouns in a problem description may indicate some of the classes and objects needed in a program.
A class represents a group of objects with similar behavior. A plural noun is an indication that your design might not be good.
Classes that represent objects should generally be given names that are singular nouns.
A class represents a single item from which we are free to create as many instances as we choose.
Another key decision is whether to represent something as an object or as a primitive attribute of another object.
We want to strike a good balance between classes that are too general and those that are too specific.
There might be additional classes to support the work necessary to get the job done.
Keep in mind that may be an old class that’s similar enough to serve as the basis for our new class.
The existing class may be part of the Java standard class library, part of a solution to a problem we’ve solved previously, or part of a library that can be bought from a third party, “Software Re-usability”.
Assigning responsibilities
Part of the process of identifying the classes needed in a program is the process of assigning responsibilities to each class. Each class represents an object with certain behaviors that are defined by the methods of the class. Any activity that the program must accomplish must be represented somewhere in the behaviors of the classes. That is, each class is responsible for carrying out certain activities, and those responsibilities must be assigned as part of designing a program.
Generally use verbs for the names of behaviors and the methods that accomplish them.
Sometimes it is challenging to determine which is the best class to carry out a particular responsibility. You could benefit from defining another class to shoulder the responsibility.
It’s not necessary in the early stages of a design to identify all the methods that a class will contain. It is often sufficient to assign primary responsibilities and consider how those responsibilities translate to particular methods.
Class and object relationships
The classes in a software system have various types of relationships to each other. Three of the more common relationships are dependency, aggregation, and inheritance.
Dependency relationships: a class “uses” another.
Class A uses class B, then one or more methods of class A invoke one or more methods of class B. If an invoked method is static, then A merely references B by name. If the invoked method is not static, then A must have access to a specific instance of class B in order to invoke the method. That is, A must have a reference to an object of class B.
UML notation distinguishes between object diagrams and class diagrams. In an object diagram the class names are underlined; in a class diagram the class names are not underlined. In a class diagram, you denote dependency by a dashed line with a shaped open arrow tip that points to the dependent class. Figure 1 shows a class diagram indicating that the CashRegister class depends on the Coin class.
Note that the Coin class does not depend on the CashRegister class. Coins have no idea that they are being collected in cash registers, and they can carry out their work without ever calling any method in the CashRegister class.
Aggregation: the objects of one class contain objects of another, creating a “has-a” relationship.
When one class instantiates the objects of another, it is the basis of an aggregation relationship. The access can also be accomplished by passing one object to another as a method parameter.
The less dependent our classes are on each other, the less impact changes and errors will have on the system.
Inheritance: creates an “is-a” relationship between classes.