14 Object Oriented Design
R. Baskaran
OBJECT ORIENTED DESIGN
Object oriented design is a software design approach that aims at analysis and designing of a system, by encompassing object interaction to implement a solution for a system.
OBJECTIVES
- To create OO design of a system from the requirements model.
- Comprehend the nature of design patterns by understanding examples.
- To evaluate the design for applicability, reasonableness.
PROGRAM DEVELOPMENT
The creation of software involves four basic activities:
- Requirement establishment – The requirements are elicited from the stakeholders and the requirements are analyzed and clearly specified.
- Creating a design – After the specification of the requirements, a design is developed for implementation. With the requirements elicited from the stakeholders, a blueprint or the architecture of the system to be developed is designed. It comprises of all the functionalities and features of the system.
- Implementing the code – Once the developer gets a clear picture on what is to be developed, the design is implemented.
- Testing the implementation – Test cases are developed to test the system implemented. The system is tested for its functionalities and quality measures are tested using test cases.
These activities are not strictly linear, they overlap and interact. During the development cycle, developers to tend to backtrack to improvise the system or they work on different modules in parallel which are later integrated.
DESIGN
A software design specifies how a program will accomplish its requirements. Software design determines how the solution can be broken down into manageable pieces and what each piece will do. The principles of software design involve the following:
- Correspondence to analysis model
- Ensure minimal errors
- Represent correspondence between software and real world problem.
- Programming paradigm
- Uniform and integrated
- Gentle degradation
- Code reuse
- Prototyping
DESIGN
An object-oriented design determines which classes and objects are needed, and specify how they will interact. It encompasses object interaction to implement a solution for a system. Low level design details include how individual methods will accomplish their tasks.
IDENTIFYING CLASSES AND OBJECTS
The core activity of object-oriented design is determining the classes and objects that will make up the solution. The classes may be part of a class library, reused from a previous project, or newly written. One way to identify potential classes is to identify the objects discussed in the requirements. Objects are generally nouns, and the services that an object provides are generally verbs. A partial requirement document example is given below from which we can infer that not all nouns will correspond to a class or object in the final solution.
Guidelines for Discovering Objects
The guidelines for discovering objects encompass the following conventions:
- Limit responsibilities of each analysis class.
- Use clear and consistent names for classes and methods.
- Keep analysis classes simple.
- Limit Responsibilities
- Use Clear and Consistent Names Each class should have a clear and simple purpose for existence.
Classes that contain many responsibilities are difficult to comprehend and maintain. A good test for limiting responsibilities lies in making attempts to explain the functionality of a class in a few sentences. As the design progresses and when more feedbacks are obtained from potential end-users, the project drifts and becomes more complicated. Therefore, it is probably good to have tiny objects. Smaller classes can be deployed in the project and later decisions can be made to merge it with other classes.
Classes and methods should have suitable names. Class names should be nouns. The boundaries of the class tend to become too fuzzy when good names are not coined for the classes. Using too many simple classes is acceptable provided good and descriptive names are coined for the classes
- Keep Classes Simple
The classes should be kept simple without worrying about details like object relationships. The class represents a group (classification) of objects with the same behaviors. Hence the class represents the concept of one such object. Generally, classes that represent objects should be given names that are singular nouns. Examples: Coin, Student, Message. The developer can instantiate as many objects as needed. Sometimes it is challenging to decide whether something should be represented as a class. For example, should an employee’s address be represented as a set of instance variables or as an Address object. The more we examine the problem and its details, more clearly these issues become visible. When a class becomes too complex, it often should be decomposed into multiple smaller classes to distribute the responsibilities. The classes must be defined with the proper amount of detail. For example, it may be unnecessary to create separate classes for each type of appliance in a house and may be sufficient to define a more general Appliance class with appropriate instance data. It all depends on the details of the problem being solved. Identification of class also comprises the process of assigning responsibilities to each class.
BEHAVIOR DESCRIPTION
Every activity that a program must accomplish must be represented by one or more methods in one or more classes. We generally use verbs for the names of methods. In early stages it is not necessary to determine every method of every class – begin with primary responsibilities and evolve the design. The set of methods also dictate how your objects interact with each other to produce a solution. Sequence diagrams can help tracing object methods and interactions. The sequence diagram depicts the customer validation while logging on to the system.
COHESION BETWEEN METHODS
The methods of an object should be in harmony. If a method seems out of place, then your object might be better off by giving that responsibility to somewhere else. For example, getPosition(), getVelocity(), getAcceleration(), getColor(). Clear and unambiguous method names must be employed. Good names may prevent others to have a need for documentation and it gives a better understanding for other developers. If you cannot find a good name, it might mean that your object is not clearly defined, or you are trying to do too much inside your method.
STATIC CLASS MEMBERS
A static method is one that can be invoked through its class name. For example, the methods of the Math class are static:
result = Math.sqrt(25)
Variables can be static as well. Determining whether a method or variable should be static is an important design decision
Static Modifier
Static methods and variables are declared using the static modifier. It associates the method or variable with the class rather than with an object of that class. Static methods are sometimes called class methods and static variables are sometimes called class variables
Static Variables – Each object has its own data space, but if a variable is declared as static, only one copy of the variable exists. The memory space for a static variable is created when the class is first referenced. All objects instantiated from the class share its static variables.
The change in value of a static variable in one object changes it for all others private static float price;
Static Methods – Static methods are namespaced global functions. Static methods sometimes are called class methods.
class Helper
{
public static int cube (int num) { return num * num * num;
}}
Because it is declared as static, the method can be invoked as value = Helper.cube(5);
Static Class Members – Static methods and static variables often work together. The following example keeps track of how many objects have been created using a static variable, and makes that information available using a static method.
CLASS RELATIONSHIPS
Classes in a software system can have various types of relationships to each other. Three of the most common relationships:
◦ Dependency: A uses B
◦ Aggregation: A has-a B
◦ Inheritance: A is-a B
Dependency – A dependency exists when one class relies on another in some way, usually by invoking the methods of the other. Numerous or complex dependencies among classes must be avoided as we do not want complex classes that depend on others. A good design strikes the right balance. Some dependencies occur between objects of the same class. A method of the class may accept an object of the same class as a parameter.
For example, the concat method of the String class takes as a parameter another String object.
str3 = str1.concat(str2);
This drives home the idea that the service is being requested from a particular object.
Aggregation – An aggregate is an object that is made up of other objects. Therefore aggregation is type of has-a relationship. E.g. A car has a chassis. In software, an aggregate object contains references to other objects as instance data. The aggregate object is defined in part by the objects that make it up. This is a special kind of dependency – the aggregate usually relies on the objects that compose it. The following example expresses aggregation in UML
Inheritance – Classes with a set of similar attributes and operations may be organized into a hierarchical relationship. Common attributes and operations are factored out and assigned to a broad superclass (generalization).
◦ Generalization is the “is-a” relationship.
◦ Super classes are ancestors, subclasses are descendants.
A class can be iteratively refined into subclasses that inherit the attributes and operations of the superclass (specialization). The following figure provides an example for interitance where “ball” is the superclass and the types of balls such as “football, baseball, basketball” are subclasses which inherit the properties of the superclass “ball”.
CLASS DESIGN PRINCIPLES (SOLID)
The object oriented design is comprised of five design principles called “SOLID” that facilitates agile software development. The SOLID principle are as follows:
Single Responsibility Principle
A class should have one, and only one, reason to change. It should possess a single responsibility.
Open/Closed Principle
A principle that states we should add new functionalities by adding new code, not editing old code. Abstraction is the key for this principle. It aims at providing room for extension but not for modification.
Liskov Substitution Principle
All derived classes must be substitutable for their base classes. This principle guides us in the creation of abstractions. LSP Guides the Creation of Abstractions. Derived classes must be usable through the base class interface, without the need for the user to know the difference.
Interface Segregation Principle
Interface Segregation Principle splits interfaces to manage dependencies. Sometimes class methods have various groupings. These classes are used for different purposes and not all users rely upon all methods and they should not be forced to rely on method that they do not use. This lack of cohesion can cause serious dependency problems which are to be refactored.
Dependency Inversion Principle
Dependency Inversion Principle avoids the following actions such as, deriving from concrete classes, associating to concrete classes, aggregating concrete classes and dependencies on concrete components. The key factor of this principle states that “Details should depend on abstractions. Abstractions should not depend on details.”
Web Links
- https://en.wikipedia.org/wiki/Object-oriented_design
- https://www.tutorialspoint.com/object_oriented…design/ooad_object_oriented_design
- https://www.cs.colorado.edu/~kena/classes/5828/s07/lectures/20/lecture20.pdf
Supporting & Reference Materials
- Roger S. Pressman, “Software Engineering: A Practitioner’s Approach”, Fifth Edition, McGraw Hill, 2017.
- PankajJalote, “An Integrated Approach to Software Engineering”, Second Edition, Springer Verlag, 1997.
- Ian Sommerville, “Software Engineering”, Sixth Edition, Addison Wesley, 2000.