CSC/ECE 517 Fall 2011/ch4 4j fw

From Expertiza_Wiki
Jump to navigation Jump to search

Introduction

In this wiki page, we will introduce the factors that relevant to software project success and failure. And we will focus on analyzing how Object Oriented Design (OOD) affects the success of software. In the later part of this wiki page, we will demonstrate and analysis some examples of software failures which due to poor OOD.

Software success and failure

What is software success

The general definition of software project success is - projects delivered on time, in scope (software quality is satisfied) and within planned costs. [1] It is just a most simplistic definition of software project success because it merely relies on the schedule and budget. In fact, it is hard to tell whether software is a success or failure one, because business success, at sometime, is more essential than technical success. [2] This means that the software which is being implemented must create value that business needed, such as making profit, rather than simply achieve the software goal and requirement.

In The Strategic Project Office, written by J. Kent Crawford, [3] we can find some more specific success criteria mentioned to address alignment between project goals, business requirements, and outcomes:

The organization’s strategies are executed according to plan. The organization’s shareholders are satisfied. The organization is financially successful. Projects are completed on schedule and on budget. Project customers are satisfied. Project resources are allocated optimally. Projects are aligned to the organization’s business strategy. The organization works on the right projects.

What is software failure

Compared with software success, it is relative easier to define software failure. It can be definite as “(1) being over-scheduled by more than 30% and/or, (2) being over-budget by more than 30% and/or, (3) the end product did not meet user requirements. These three criteria cover the schedule, budget, and requirement, all surrounded by quality that should comprise all projects.”[5].

In technical term, software failure is possibly due to software bugs or the poor software design, such as bad OOD that will be discussed later. In the figure below, we can see the cyclic behavior of failure. A fault or bug will cause errors. And errors in the system lead to the subsequent failure. In most of the cases, the software system comprises multiple components in which one failure may result in bugs or errors in another component.

                                                            

                                                                     Figure 1 cyclic Fault behavior

Factors leading to software failure

Most software project can be considered at least partial failures since few of the software can meet all the schedule, cost and requirement objective. According to many studies, failure rate of software projects is between 50% - 80%. [6] In most of the cases, the software projects fail because we do not recognize that good engineering principles should be applied to software projects just as they are to building office buildings. Below are some factors that may lead to the software failure with no particular order:

Poor user input
It is possible that a titanic project which meets all the requirements ultimately get fails because the system did not meet the user needs.

Vague requirement
People cannot design a process that assumes the requirement is stable. Projects could be headed for trouble if architectures and processes are not change-friendly, or if there are poorly established guidelines that determine how and when requirements can be added, removed, and implemented—and who will shoulder the cost of the changes.

Poor cost and schedule estimation
Although it is unfair to call software project a failure if it cannot meet the budget and schedule goals that were inherently unattainable, every software project has a minimum achievable cost and schedule.

Skills that not match the job
It is obvious reason, just like managers can perform poorly if they lead projects that do not match their strengths.

Communication breakdown
Communication breakdown may lead to low efficiency and even the project failure. Especially large software project which is done by different groups in various sites, same code may be tested two times because no one knows the other exist.

Poor architecture
This is because people never think ahead about what is likely to change. Once the software is developed in an inflexible way, it may be outdate quickly after it is released and may cause problems because it cannot deal with the continue change incomes. For this reason, we come to realize why OOD is so important in software development.

What is Object Oriented Design (OOD)

Object Oriented Design (OOD) is the concept that forces programmers to plan out their code in order to have a better flowing program [7]. Simply speaking, OOD is all about objects. An object can be considered as a “black box” which receives and sends messages. Code (sequence of computer instructions) and data (information that instructions operates on) are included in this “black box”. [8] Interface is used in the object and everything an object can do is represented by its message interface.

Simple example of OOD

Here we give a simple example of coding used in both non-object-oriented-design and object-oriented-design.

If we want to add two names together in non-object-oriented language such C. We first define a data type as list which will be defined as structure in C:

structure list {
<definition of list structure data here>
};

list a, b, c;

a = “Adam”;
b = “Eva”;
c = a + b;

We expect to get the result as “Adam Eva” but it doesn’t work actually in C. C complier will generate error when adding a and b because it only know how to add number while “Adam” and “Eva” are not.

Let try this example again in Object-oriented language such as Ruby, we write the code as below:

a = “Adam”
b =”Eva”
c = a + b
puts c

The object a is created with string “Adam” and object b is created with string “Eva”. After entering the code, we can get the result “AdamEva”. Ruby complier knows how to manipulate the message “+” and that’s why object c gets new value.

Tools help for OOD

Object Oriented Design is defined as a programming language that has 5 conceptual tools to aid the programmer. These programs are often more readable than non-object oriented programs, and debugging becomes easier with locality.[9]

Language Concepts

The 5 Basic Concepts of Object Oriented Design are the implementation level features that are built into the programming language. These features are often referred to by these common names:

Encapsulation:Encapsulation refers to a tight coupling or association of data structures with the methods or functions that act on the data. This is called a class, or object (an object is often the implementation of a class).

Data Protection:Data Protection is the ability to protect some components of the object from external entities. This is realized by language keywords to enable a variable to be declared as private or protected to the owning class.

Inheritance:Inheritance defines the ability for a class to extend or override functionality of another class. The so called child class has a whole section that is the parent class and then it has its own set of functions and data.

Interface:Interface is a definition of functions or methods, and their signatures that are available for use to manipulate a given instance of an object.

Polymorphism:Polymorphism refers to the ability to define different functions or classes as having the same name but taking different data types.

Programming Concepts

There are several concepts that were derived from the new languages once they became popular. The new standards that came around pushed on three major things:

Re-usability
The ability to reuse code for multiple applications. If a programmer has already written a power function, then it should be written that any program can make a call to that function and it should work exactly the same.

Privacy
This is important for large programs and preventing loss of data.

Documentation
The commenting of a program in mark up that will not be converted to machine code. This mark up can be as long as the programmer wants, and allows for comprehensive information to be passed on to new programmers. This is important for both the re-usability and the maintainability of programs.

How to achieve a good OOD

“Good design and programming is not learned by generalities, but by seeing how significant programs can be made clean, easy to read, easy to maintain and modify human-engineered, efficient, and reliable, by the application of good and programming practices. Careful study and imitation of good designs and programs significantly improves development skills.”--Kernighan & Plauger

At the heart of great design are a set of principles and patterns. Design principles form the foundation of good object-oriented design and design patterns provide general repeatable solutions for common software problems. [10]

Design principles

Design principles are guidelines and heuristics for a good object oriented designs. There are many different design principles of Object-Oriented Design. Here are 4 major principles of them:

Encapsulation
In a nutshell, encapsulation is the hiding of data implementation by restricting access to accessors and mutators. An accessor, usually in the form of properties in OOP, is a method that is used to ask an object about itself. Accessor has a get method, which is an accessor method. Mutator is used to modify the state of an object. It is a public method, and hides the implementation of exactly how the data gets modified.

Abstraction
Abstraction is the development of a software object. It denotes a model, a view, or some other focused-representations for an object we can actually find in the real world. It can be used to decompose complex systems into smaller by software developers.

Inheritance
Objects can relate to each other with either a “has a”, “uses a” or an “is a” relationship. “Is a” is the inheritance way of object relationship.[11]

Polymorphism
Meaning one name, many forms, polymorphism manifests itself by having multiple methods all with the same name, but slightly different functionality. There are two basic types of polymorphism: overriding, also called run-time polymorphism, and overloading, which is referred to as compile-time polymorphism.

Design patterns

Design pattern is a general reusable solution to a commonly occurring problem within a given context. It is a template describing how to solve a problem, which cannot be transformed directly into code. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved. Many patterns imply object-orientation or more generally mutable state, and so may not be as applicable in functional programming languages, in which data is immutable or treated as such. [12]

There are many types of design patterns, like

Creator
As one of the most common activities in an object-oriented system, creator pattern maintains a fundamental property of the relationship between objects of particular classes: class is responsible for creating objects. That is to say, creator pattern is responsible for creating an object of class.

Controller
The Controller pattern assigns the responsibility of dealing with system events to a non-UI class that represents the overall system or a use case scenario. A Controller object is a non-user interface object responsible for receiving or handling a system event. [13]

High Cohesion
High cohesion means that the responsibilities of a given element are strongly related and highly focused. It is an evaluative pattern generally used in support of Low Coupling, which can keep objects appropriately focused, manageable and understandable.

Indirection
By assigning the responsibility of mediation between two elements to an intermediate object, the Indirection pattern supports low coupling and reuse potential between them. An example of this is the introduction of a controller component for mediation between data (model) and its representation (view) in the Model-view-controller pattern. [13]

Protected Variations
By wrapping the focus of instability with an interface and using polymorphism to create various implementations of this interface, the Protected Variations pattern protects elements from the variations on other elements, like objects, systems and subsystems.

Tips for a good OOD

There are some tips that can be used in designing to enhance and improve the object-oriented projects.

Use Lots of Objects
By adding lots of objects, it is easy to make each object has and only has one job. Once you understand the architecture, it helps to avoid changing massive amounts of code when we modify the code.

Use Interfaces to Make APIs Predictable
Interfaces allow for strict type hinting, and by type hinting you can ensure that certain methods are always available for your use. [14]Each interface will provide the model to utilize. The utilization of a particular interface will cause the implementations of a few methods.

Use Dependency Injection
Using dependency injection can make testing and feature addition easier. While, it makes testing impossible by instantiating objects directly in the code, or grabbing objects out of singletons.

Create Loosely Coupled Classes
When a developer gives each object only one responsibility, they tightly couple objects together. Objects will often request information from other objects, and while this is not avoidable in all situations, these tightly coupled classes that rely on one another’s functionality makes pulling those objects apart impossible.[14]


Poor OOD Leads to Software Failures

In technical term, software failure is possibly due to software bugs or the poor software design, such as bad OOD. In the figure 1, we can see the cyclic behavior of failure. A fault or bug will cause errors. And errors in the system lead to the subsequent failure. In most of the cases, the software system comprises multiple components in which one failure may result in bugs or errors in another component.

                                                            

                                                                     Figure 1 cyclic Fault behavior

Factors may lead to Poor OOD

Bad practice in code will always lead to the poor OOD. Here are some common ones[15]:

  • Classes that break the Single Responsibility Principle (SRP) and perform too many actions
  • Favor Composition over Inheritance: too much inheritance instead of composition, i.e. Classes that derive from a sub-type purely so they get functionality for free
  • Repeated use of switch/case statements on the same enumerated member (sign of sub-classes needing extraction)
  • Lots of member variables that are used for processing, not to capture state (might indicate need to extract a method object)
  • Long chains of member access
  • Use of too many design patterns in a small space
  • Some repeated pattern of action, process or structure that initially appears to be beneficial, but ultimately produces more bad consequences than beneficial results
  • A base class down-casting itself to a derived class. Like, excessive use of switch statements, or derived classes that override everything
  • Duplicate code, code that does the same thing

Software design anti-patterns

In software engineering, an anti-pattern (or anti-pattern) is a pattern that may be commonly used but is ineffective and/or counterproductive in practice.[2]Many anti-pattern ideas amount to little more than mistakes, rants, unsolvable problems, or bad practices to be avoided if possible.

Anti-patterns, like their design pattern counterparts, define an industry vocabulary for the common defective processes and implementations within organizations.[3] In OOP, the anti-patterns of software design and object-oriented design are dangerous. They will result in bugs and errors in practice, and then finally lead to the failures of software. Here are the examples:[4]

  • Abstraction inversion: Not exposing implemented functionality required by users, so that they re-implement it using higher level functions
  • Ambiguous viewpoint: Presenting a model (usually Object-oriented analysis and design (OOAD)) without specifying its viewpoint
  • Big ball of mud: A system with no recognizable structure
  • Database-as-IPC: Using a database as the message queue for routine interprocess communication where a much more lightweight mechanism would be suitable
  • Gold plating: Continuing to work on a task or project well past the point at which extra effort is adding value
  • Inner-platform effect: A system so customizable as to become a poor replica of the software development platform
  • Input kludge: Failing to specify and implement the handling of possibly invalid input
  • Interface bloat: Making an interface so powerful that it is extremely difficult to implement
  • Magic pushbutton: Coding implementation logic directly within interface code, without using abstraction
  • Race hazard: Failing to see the consequence of different orders of events
  • Stovepipe system: A barely maintainable assemblage of ill-related components

Object oriented design anti-patterns

  • Anemic Domain Model: The use of domain model without any business logic. The domain model's objects cannot guarantee their correctness at any moment, because their validation and mutation logic is placed somewhere outside (most likely in multiple places).
  • BaseBean: Inheriting functionality from a utility class rather than delegating to it
  • Call super: Requiring subclasses to call a superclass's overridden method
  • Circle-ellipse problem: Subtyping variable-types on the basis of value-subtypes
  • Circular dependency: Introducing unnecessary direct or indirect mutual dependencies between objects or software modules
  • Constant interface: Using interfaces to define constants
  • God object: Concentrating too many functions in a single part of the design (class)
  • Object cesspool: Reusing objects whose state does not conform to the (possibly implicit) contract for re-use
  • Object orgy: Failing to properly encapsulate objects permitting unrestricted access to their internals
  • Poltergeists: Objects whose sole purpose is to pass information to another object
  • Sequential coupling: A class that requires its methods to be called in a particular order
  • Yo-yo problem: A structure (e.g., of inheritance) that is hard to understand due to excessive fragmentation


References