CSC/ECE 517 Fall 2007/wiki3 3 ab: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(28 intermediate revisions by 2 users not shown)
Line 4: Line 4:
==Introduction==
==Introduction==
===Separation of Responsibility===
===Separation of Responsibility===
In Object-Oriented Design (OOD), '''Separation of Concern''' is well known as a principle or process of  
In Object-Oriented Design (OOD), '''Separation of Concern''' is well known as a principle or process of breaking computer program codes into different components that have little coupling with each other and have strong cohesion. Following this principle, a class should have one clearly defined responsibility. In separation of concern, there are two important concepts: '''Separation of Responsibility''' and '''Separation of knowledge''' (information and environment hiding).
breaking computer program codes into different components that have little coupling with each other and have strong cohesion. Following this principle, a class should have one clearly defined responsibility. In separation of concern, there are two important concepts: '''Separation of Responsibility''' and '''Separation of knowledge''' (information and environment hiding).


'''Separation of responsibility''' states that specific functionality or specific actions are assigned to design components and are not distributed throughout a design [3], in another word, each individual object should have as few responsibilities as possible, ideally one responsibility per object.
'''Separation of responsibility''' states that specific functionality or specific actions are assigned to design components and are not distributed throughout a design [3], in other words, each individual object should have as few responsibilities as possible, ideally one responsibility per object.


===Why using separation of responsibility===
===Why we should use separation of responsibility===


Before we discuss the separation of responsibility, let us have a look at the following class [4]:
Before we discuss the separation of responsibility, let us have a look at the following class [4]:
Line 22: Line 21:
</pre>
</pre>


This class have to be changed when the following aspects are changed.
This class has to be changed when the following aspects are changed.


*The business rules having to do with calculating pay.  
*The business rules having to do with calculating pay.  
Line 30: Line 29:
That is to say, the class ''Employee'' is impacted by three completely different responsibilities. Every time the accounts decide to change the format of the hourly report, or every time the DBAs make a change to the database schema, as well as every time the managers change the payroll calculation, we have to change the class ''Employee''.
That is to say, the class ''Employee'' is impacted by three completely different responsibilities. Every time the accounts decide to change the format of the hourly report, or every time the DBAs make a change to the database schema, as well as every time the managers change the payroll calculation, we have to change the class ''Employee''.


Separation of responsibility can avoid this trouble. When using separation of responsibility, these three functions ''calculatePay()'', ''save()'', ''reportHours()'' will be separated into different classes so that they can change independently without influence others. Using separation of responsibility, programs are easy to maintain and change.
Separation of responsibility can avoid this trouble. When using separation of responsibility, these three functions ''calculatePay()'', ''save()'', ''reportHours()'' will be separated into different classes so that they can change independently without influencing others. Using separation of responsibility, programs are easy to maintain and change.


===Principle of Separation of Responsibility===
===Principle of Separation of Responsibility===


There are several principles of Separation of Responsibility [1]:
There are several principles of Separation of Responsibility [1]:
* '''Single Responsibility Principle (SRP)'''. Different responsibilities should be divided among different objects, in another word, one object should have only one responsibility in ideal situation. We can only say '''A class should have only one reason to change.''' We want to focus classes, functions, etc. so that there is only one reason for them to change. This is why many people separate their application into layers. For example, The data access layer provides persistence and re-hydration of business objects. The business layer is all about business rules. And, the presentation layer is only about presenting information to the user. Hopefully a change in one layer won't cause a ripple effect of changes in other layers, or at least, keep the impact to a minimum.[9]
* '''Single Responsibility Principle (SRP)'''. Different responsibilities should be divided among different objects. In other words, one object should have only one responsibility in ideal situation. We can only say '''A class should have only one reason to change.''' We want to focus classes, functions, etc. so that there is only one reason for them to change. This is why many people separate their application into layers. For example, Ruby on Rails has three layers, View, Model and Controller. Different layers handle different rules. When we change database, we only need to change models. And when we change business logics, we only need to change Controllers.  
* '''Encapsulation'''. One class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes. In another word, Data should be kept in only one place.
* '''Encapsulation'''. One class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes. In other word, Data should be kept in only one place.
* '''Expert pattern'''. The object that contains the necessary data to perform a task should be the object that manipulates the data.
* '''Expert pattern'''. The object that contains the necessary data to perform a task should be the object that manipulates the data.
* '''The Dry principle'''. Code should not be duplicated. A given functionality should be implemented only in one place in the system.
* '''The Dry principle'''. '''D'''on't '''R'''epeat '''Y'''ourself. Code should not be duplicated. A given functionality should be implemented only in one place in the system.


==Examples==
==Examples==
We consider the '''Java example for Principle of Separation of Responsibility''' is the best example to describe Separation of Responsibility.


===Java Example for Principle of Separation of Responsibility===
===Java Example for Principle of Separation of Responsibility===


There is an Java example of principle of Separation of responsibility[4].  
There is an Java example of principle of Separation of responsibility[5].  


<pre>
<pre>
Line 62: Line 63:
</pre>
</pre>


The method name is create. While others viewing the the code will expect to have a create function. But instead it has three functionality, creates a customer, checks if it's already exist and then save it. It should divide these functionality into 4 methods.  
The method name is ''create''. While others viewing the the code will expect to have a create function. But instead it has three functionalities, creates a customer, checks if it's already exist and then save it. It should divide these functionalities into 4 methods.  
 
#''bindValidateAndSave'' is the application method. It tells what to do rather than how's done.
#''bindCustomer''  binds and adds new shoppingCart.
#''validateCustomer'' checks whether the customer exists.
#''saveCustomer'' saves the customer.
 


#''bindValidateAndSave'' The application method. It tells what to do rather than how's done.
The last method ''saveCustomer'' has only 1 line of code, why were we let it become a individual method? It is show how it works although it might not improve the readability of the code.
#''bindCustomer''  bind and add new shoppingCart.
#''validateCustomer'' validate if customer exist.
#''saveCustomer'' save customer


Each methods only doing one thing and have only one responsibility. The blind, validate and save separately in different methods.


The last method ''saveCustomer'' has only 1 line of code, why were we let it become a individual method? Although it might not improve readability for programmers, it’s a paradigm shift in how the method is addressed. Because it calls ''customerService.save()''. it’s responsible that the save method is actually called right. Instead if we let it delegate to a newly extracted method (''saveCustomer'') it isn’t responsible for the explicit saving.
===Example for Single Responsibility Principle(SRP)===
===Example for Single Responsibility Principle(SRP)===


Single responsibility principle is to say that a object should only has one reason to change. If there are more than one reason to change the object then we should split the object into smaller object which has one responsibility.[10]
Single responsibility principle is to say that an object should only has one reason to change. If there are more than one reason to change the object then we should split the object into smaller object which has one responsibility.[10]


We have a object to keep an email message as below.  
We have an object to keep an email message as below.  


<pre>
<pre>
Line 97: Line 101:
*Another one would be for the Content field. Even if content is a string maybe we want in the future to support HTML or other formats.  
*Another one would be for the Content field. Even if content is a string maybe we want in the future to support HTML or other formats.  


We can create a new interface and class called IContent and Content to split the responsabilities. Having only one responsability for each class give us a more flexible design.
We can create a new interface and class called IContent and Content to split the responsibilities, having only one responsibility for each class give us a more flexible design.


*adding a new protocol causes changes only in the Email class.
*adding a new protocol causes changes only in the Email class.
Line 123: Line 127:
</pre>
</pre>


The Single Responsibility Principle represents a good way of identifying classes during the design phase of an application and it reminds you to think of all the ways a class can evolve. A good separation of Responsibility is done only when the full picture of how the application should work is well understand.
The Single Responsibility Principle represents a good way of identifying classes during the design phase of an application and it reminds you to think of all the ways a class can evolve. A good separation of Responsibility is done only when the full picture of how the application should work is well understood.


===Example for Information Expert(Expert pattern)===
===Example for Encapsulation principle and Expert pattern===


There is a simple part of a POS system example[10].  
One class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes. In other words, Data should be kept in only one place.


[[Image:Topic14NotesImage1.jpg]]
For example:
 
<pre>
We make choices about the assignment of responsibilities to classes. Information Expert helps us decide, once we know the task (responsibility), which class to make responsible for carrying out the task.
public class Person {
    private String firstName;
    private String lastName;
    private String suffixName;
    public String getFirstName() {
      return firstName;
    }
    public void setFirstName(String _x) {
      firstName = _x;
    }
    public String getLastName() {
      return lastName;
    }
    public void setLastName(String _x) {
      lastName = _x;
    }
    public String getSuffixName() {
      return suffixName;
    }
    public void setSuffixName(String _x) {
      suffixName = _x;
    }
...
}
</pre>


Assign a responsibility to the information expert; the class that has the information necessary to fulfill the responsibility.
In this example, class ''Person'' is responsible for the data ''firstName'', ''lastName'', ''suffixName''. ''Person'' uses methods ''getFirstName'' and ''setFirstName'' to get or set data. Other classes that need to use these data have to call these methods of objects declared as ''Person'', they can not use or modify these data directly.
So after we apply the expert pattern to the example above, it become following diagram.


[[Image:Topic14NotesImage2.jpg]]
The object of class ''Person'' contains the necessary data ''firstName'' to do the task of getting the first name. The object of class ''Person'' is also the only object that manipulates the data.


==Reference==
==References==
#[http://courses.ncsu.edu/csc517/common/lectures/notes/lec20.pdf Elegance and classes]
#[http://courses.ncsu.edu/csc517/common/lectures/notes/lec20.pdf Elegance and classes]
#[http://en.wikipedia.org/wiki/Separation_of_concerns Separation of concerns]
#[http://en.wikipedia.org/wiki/Separation_of_concerns Separation of concerns]
Line 148: Line 177:
#[http://www.babysentry.com/tech_specs_benefits.htm Benefits of the Three-Tiered Architecture]
#[http://www.babysentry.com/tech_specs_benefits.htm Benefits of the Three-Tiered Architecture]
#[http://davidhayden.com/blog/dave/archive/2005/05/29/1066.aspx Single-Responsibility Principle]
#[http://davidhayden.com/blog/dave/archive/2005/05/29/1066.aspx Single-Responsibility Principle]
#[http://web.cs.wpi.edu/~gpollice/cs4233-a05/CourseNotes/maps/class4/InformationExpert.html Information Expert]
#[http://www.oodesign.com/oo_principles/oo_principles/single_responsibility_principle.html OOD - Single Responsibility Principle]
#[http://www.oodesign.com/oo_principles/oo_principles/single_responsibility_principle.html Single Responsibility Principle]

Latest revision as of 04:31, 29 November 2007

Topic

Take the principle of Separation of Responsibility and catalog the information on it available on the Web. Find good descriptions and good, concise, understandable examples. Tell which you consider the best to present to a class.

Introduction

Separation of Responsibility

In Object-Oriented Design (OOD), Separation of Concern is well known as a principle or process of breaking computer program codes into different components that have little coupling with each other and have strong cohesion. Following this principle, a class should have one clearly defined responsibility. In separation of concern, there are two important concepts: Separation of Responsibility and Separation of knowledge (information and environment hiding).

Separation of responsibility states that specific functionality or specific actions are assigned to design components and are not distributed throughout a design [3], in other words, each individual object should have as few responsibilities as possible, ideally one responsibility per object.

Why we should use separation of responsibility

Before we discuss the separation of responsibility, let us have a look at the following class [4]:

class Employee
{
  public Money calculatePay()
  public void save()
  public String reportHours()
}

This class has to be changed when the following aspects are changed.

  • The business rules having to do with calculating pay.
  • The database schema.
  • The format of the string that reports hours.

That is to say, the class Employee is impacted by three completely different responsibilities. Every time the accounts decide to change the format of the hourly report, or every time the DBAs make a change to the database schema, as well as every time the managers change the payroll calculation, we have to change the class Employee.

Separation of responsibility can avoid this trouble. When using separation of responsibility, these three functions calculatePay(), save(), reportHours() will be separated into different classes so that they can change independently without influencing others. Using separation of responsibility, programs are easy to maintain and change.

Principle of Separation of Responsibility

There are several principles of Separation of Responsibility [1]:

  • Single Responsibility Principle (SRP). Different responsibilities should be divided among different objects. In other words, one object should have only one responsibility in ideal situation. We can only say A class should have only one reason to change. We want to focus classes, functions, etc. so that there is only one reason for them to change. This is why many people separate their application into layers. For example, Ruby on Rails has three layers, View, Model and Controller. Different layers handle different rules. When we change database, we only need to change models. And when we change business logics, we only need to change Controllers.
  • Encapsulation. One class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes. In other word, Data should be kept in only one place.
  • Expert pattern. The object that contains the necessary data to perform a task should be the object that manipulates the data.
  • The Dry principle. Don't Repeat Yourself. Code should not be duplicated. A given functionality should be implemented only in one place in the system.

Examples

We consider the Java example for Principle of Separation of Responsibility is the best example to describe Separation of Responsibility.

Java Example for Principle of Separation of Responsibility

There is an Java example of principle of Separation of responsibility[5].

public void createCustomer(Map requestParameters) {
	Customer customer = new Customer();
	customer.setName = requestParameters.get("name");

	//Check if a customer was already registered with that name
	if (customerService.getCustomerByName(customer.getName()) != null) {
		System.out.println("Customer already exists");
		return;
	}
	customer.setShoppingCart(new ShoppingCart());

	customerService.save(customer);
}

The method name is create. While others viewing the the code will expect to have a create function. But instead it has three functionalities, creates a customer, checks if it's already exist and then save it. It should divide these functionalities into 4 methods.

  1. bindValidateAndSave is the application method. It tells what to do rather than how's done.
  2. bindCustomer binds and adds new shoppingCart.
  3. validateCustomer checks whether the customer exists.
  4. saveCustomer saves the customer.


The last method saveCustomer has only 1 line of code, why were we let it become a individual method? It is show how it works although it might not improve the readability of the code.

Each methods only doing one thing and have only one responsibility. The blind, validate and save separately in different methods.

Example for Single Responsibility Principle(SRP)

Single responsibility principle is to say that an object should only has one reason to change. If there are more than one reason to change the object then we should split the object into smaller object which has one responsibility.[10]

We have an object to keep an email message as below.

// single responsability principle - bad example

interface IEmail {
   public void setSender(String sender);
   public void setReceiver(String receiver);
   public void setContent(String content);
}

class Email implements IEmail {
   public void setSender(String sender) {// set sender; }
   public void setReceiver(String receiver) {// set receiver; }
   public void setContent(String content) {// set content; }
}

The IEmail interface has two responsibilities.

  • One would be the use of the class in some email protocols such as pop3 or imap. If other protocols must be supported the objects should be serialized in another manner and code should be added to support new protocols.
  • Another one would be for the Content field. Even if content is a string maybe we want in the future to support HTML or other formats.

We can create a new interface and class called IContent and Content to split the responsibilities, having only one responsibility for each class give us a more flexible design.

  • adding a new protocol causes changes only in the Email class.
  • adding a new type of content supported causes changes only in Content class.
// single responsability principle - good example

interface IEmail {
   public void setSender(String sender);
   public void setReceiver(String receiver);
   public void setContent(IContent content);
}

interface Content {
   public String getAsString(); // used for serialization
}

class Email implements IEmail {
   public void setSender(String sender) {// set sender; }
   public void setReceiver(String receiver) {// set receiver; }
   public void setContent(IContent content) {// set content; }
}

The Single Responsibility Principle represents a good way of identifying classes during the design phase of an application and it reminds you to think of all the ways a class can evolve. A good separation of Responsibility is done only when the full picture of how the application should work is well understood.

Example for Encapsulation principle and Expert pattern

One class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes. In other words, Data should be kept in only one place.

For example:

public class Person {
 
    private String firstName;
    private String lastName;
    private String suffixName;
 
    public String getFirstName() {
       return firstName;
    }
    public void setFirstName(String _x) {
       firstName = _x;
    }
    public String getLastName() {
       return lastName;
    }
    public void setLastName(String _x) {
       lastName = _x;
    }
    public String getSuffixName() {
       return suffixName;
    }
    public void setSuffixName(String _x) {
       suffixName = _x;
    }
...
}

In this example, class Person is responsible for the data firstName, lastName, suffixName. Person uses methods getFirstName and setFirstName to get or set data. Other classes that need to use these data have to call these methods of objects declared as Person, they can not use or modify these data directly.

The object of class Person contains the necessary data firstName to do the task of getting the first name. The object of class Person is also the only object that manipulates the data.

References

  1. Elegance and classes
  2. Separation of concerns
  3. A Logical Theory of Interfaces and Objects
  4. Curly's Law: Do One Thing
  5. Java by Experience
  6. OO Programming By Example
  7. TDD Design Starter Kit – Responsibilities, Cohesion, and Coupling
  8. Benefits of the Three-Tiered Architecture
  9. Single-Responsibility Principle
  10. OOD - Single Responsibility Principle