CSC/ECE 517 Fall 2009/wiki3 17 VR: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 128: Line 128:


== In detail ==
== In detail ==
Assume the case of a library management system.
The definition stated above talks about an exhaustive list.
 
Object oriented systems handle this by having a class hierarchy[3].  
Consider the Publications of a library. In Pascal-Ada syntax, we can represent the Publications type as follows:
For example: old style procedural code to print different "shape" objects can be written as follows:
<pre language="ADA">
type PUBLICATION =
record
author, title: STRING;
publication_year: INTEGER
 
case pubtype: (book, journal, conference_proceedings) of
book: (publisher: STRING);
journal: (volume, issue: STRING);
proceedings: (editor, place: STRING) -- Conference proceedings
end
</pre>
 
In this representation the fields author ,title and publication_year are common to all the instances and others are specific to individual variants.
 
Now consider a module which contains the above representative declaration and let the module be A.
 
When A is open :
fields can be added or new variants can be implemented.
 
A must be closed when A must be enabled to have clients i.e. the listing of all fields and variants is completed now.
 
Consider B a client of A.
If B has to manipulate publications through a variable like p it can be done in the following way :
 
<pre>p: PUBLICATION</pre>
 
If we must differentiate between the various cases of p, it can be done as follows:
<pre>
<pre>
case p of
if (type==CIRCLE)
book: ...Instructions which may access the field p l publisher...
  print "Circle with  r=" + radius;
journal: ...Instructions which may access fields p l volume, pl issue...
else if (type==Square)
proceedings: ...Instructions which may access fields p l editor, pl place...
  print "Square with  sides=" + sideLength;
end
else if (type==Rectangle)
  print "Rectangle with height=" + height + ", width=" + width;
endif
</pre>
</pre>


Hence, by using the case instruction, we can move choice control between variants.
But there is a possibility that the same list of choices can be used for computing the area and rendering it to a GUI and checking if the parameters are overlapping with any other shape.
 
The major point to be noted is that this coding sequence works fine for this list of variants of publication supported by A. But later on when a new variant like technical report of university, etc. is to be added, the definition of <b>PUBLICATION</b> has to be modified to cater the need of the new case.


Fair enough: you have modified the conceptual notion of publication, so you should update the corresponding type declaration. This change is logical and inevitable. Far harder to justify, however, is the other consequence: any client of A, such as B, will also require updating if it used a structure such as the above, relying on an explicit list of cases for p. This may, as we have seen, be the case for most clients.
So, instead of having a list of cases which must be modified in all places, whenever we need to add a shape, we can use the concept of subclasses.  


Let us consider another Object oriented example :
Let us consider another Object oriented example :
Line 223: Line 195:
</pre>
</pre>
</b>
</b>
<i>NOTE: This supports the Open-Closed Principle also. </i>
Let us consider another example for better understanding. Assume <b>the case of a library management system</b>.
Consider the Publications of a library. In Pascal-Ada syntax, we can represent the Publications type as follows:
<pre language="ADA">
type PUBLICATION =
record
author, title: STRING;
publication_year: INTEGER
case pubtype: (book, journal, conference_proceedings) of
book: (publisher: STRING);
journal: (volume, issue: STRING);
proceedings: (editor, place: STRING) -- Conference proceedings
end
</pre>
In this representation the fields author ,title and publication_year are common to all the instances and others are specific to individual variants.
Now consider a module which contains the above representative declaration and let the module be A.
When A is open :
fields can be added or new variants can be implemented.
A must be closed when A must be enabled to have clients i.e. the listing of all fields and variants is completed now.
Consider B a client of A.
If B has to manipulate publications through a variable like p it can be done in the following way :
<pre>p: PUBLICATION</pre>
If we must differentiate between the various cases of p, it can be done as follows:
<pre>
case p of
book: ...Instructions which may access the field p l publisher...
journal: ...Instructions which may access fields p l volume, pl issue...
proceedings: ...Instructions which may access fields p l editor, pl place...
end
</pre>
Hence, by using the case instruction, we can move choice control between variants.
The major point to be noted is that this coding sequence works fine for this list of variants of publication supported by A. But later on when a new variant like technical report of university, etc. is to be added, the definition of <b>PUBLICATION</b> has to be modified to cater the need of the new case.
Fair enough: you have modified the conceptual notion of publication, so you should update the corresponding type declaration. This change is logical and inevitable. Far harder to justify, however, is the other consequence: any client of A, such as B, will also require updating if it used a structure such as the above, relying on an explicit list of cases for p. This may, as we have seen, be the case for most clients.


== Conclusion ==
== Conclusion ==


== References ==
== References ==

Revision as of 04:04, 19 November 2009

Single choice principle
Bertrand Meyer is the author of the book, "Object Oriented Software Construction", which is considered a foundational text of object-oriented programming book. In this book, he has mentioned about the five principles which explain modularity requirements. This wiki will explore through the Single Choice Principle in particular and its usage.

Introduction

In 1978, Yourdon and Constantine defined a software module as “a lexically contiguous sequence of program statements, bounded by boundary elements, having an aggregate identifier.” They had also proposed two important techniques namely – “Coupling” and “Cohesion” for measuing the dependability between modules. The various fundamental requirements resulting from a "modular" design method are :

  • DECOMPOSABILITY
    Meyer defined decomposability as :
    " A software construction method satisfies Modular Decomposability if : 
    it helps in the task of decomposing a software problem into a small number of less complex sub problems, connected by a simple structure, and
    independent enough to allow further work to proceed separately on each of them."
    

  • COMPOSABILITY
    Meyer defined composability as :
    A method satisfies Modular Composability if it favors the production of
    software elements which may then be freely combined with each other to
    produce new systems, possibly in an environment quite different from the
    one in which they were initially developed.
    

  • UNDERSTANDABILITY
    Meyer defined understandability as :
    A method favors Modular Understandability if it helps produce software in
    which a human reader can understand each module without having to know
    the others, or, at worst, by having to examine only a few of the others.
    
  • CONTINUITY
    A method satisfies Modular Continuity if, in the software architectures that
    it yields, a small change in a problem specification will trigger a change of
    just one module, or a small number of modules.
    
  • PROTECTION
    Meyer defined Protection as:
    A method satisfies Modular Protection if it yields architectures in which the
    effect of an abnormal condition occurring at run time in a module will remain
    confined to that module, or at worst will only propagate to a few neighboring
    modules.
    

In order to ensure modularity the following five rules must be followed:

  • Direct mapping:
  • Small interfaces(weak coupling):
  • Explicit interfaces:
  • Information Hiding:
  • Few interfaces:

There are five principles of software construction which are to be followed along with the above stated requirements and rules. They are:

The Linguistic Modular Units principle  :

This principle states that modules must correspond to syntactic units in the language used.

The self-documentation principle

 :

This principle states that the designer of a module should strive to make all information about the module part of the module itself.

The uniform access principle

 :

This principle states that all services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation.

The open-closed principle

 :

This principle states that the modules should be both open and closed.

The single choice principle

 :

This principle states that whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.

In detail

The definition stated above talks about an exhaustive list. Object oriented systems handle this by having a class hierarchy[3]. For example: old style procedural code to print different "shape" objects can be written as follows:

 if (type==CIRCLE)
   print "Circle with  r=" + radius;
 else if (type==Square)
   print "Square with  sides=" + sideLength;
 else if (type==Rectangle)
   print "Rectangle with height=" + height + ", width=" + width;
 endif

But there is a possibility that the same list of choices can be used for computing the area and rendering it to a GUI and checking if the parameters are overlapping with any other shape.

So, instead of having a list of cases which must be modified in all places, whenever we need to add a shape, we can use the concept of subclasses.

Let us consider another Object oriented example :

class Circle inherits Shape {
    method scale {....}
    method rotate {....}
    method draw {....}
  }
  class Rectangle inherits Shape {
    method scale {....}
    method rotate {....}
    method draw {....}
  }
  class Polygon inherits Shape {
    method scale {....}
    method rotate {....}
    method draw {....}
  }

The operations used in the three classes are scale, rotate and draw. These methods have been repeated in all the three classes. If a new method, for e.g., fillup() needs to be added, then, it must be added in all the three shapes and then the code becomes:

class Circle inherits Shape {
    method scale {....}
    method rotate {....}
    method draw {....}
    method fillup {....}  // NEW METHOD
  }
  class Rectangle inherits Shape {
    method scale {....}
    method rotate {....}
    method draw {....}
    method fillup {....}  // NEW METHOD
  }
  class Polygon inherits Shape {
    method scale {....}
    method rotate {....}
    method draw {....}
    method fillup {....}  // NEW METHOD
  }

Hence,in the process of software evolution, a programmer must accept that there is a possibility for certain methods or variants to arise. In such a case, to support the software over long term, there must be a method for protecting the structure of the software in order to overcome such changes.

Therefore Single Choice Principle can be stated as follows :

Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.

NOTE: This supports the Open-Closed Principle also.

Let us consider another example for better understanding. Assume the case of a library management system.

Consider the Publications of a library. In Pascal-Ada syntax, we can represent the Publications type as follows:

type PUBLICATION =
record
author, title: STRING;
publication_year: INTEGER

case pubtype: (book, journal, conference_proceedings) of
book: (publisher: STRING);
journal: (volume, issue: STRING);
proceedings: (editor, place: STRING) -- Conference proceedings
end

In this representation the fields author ,title and publication_year are common to all the instances and others are specific to individual variants.

Now consider a module which contains the above representative declaration and let the module be A.

When A is open : fields can be added or new variants can be implemented.

A must be closed when A must be enabled to have clients i.e. the listing of all fields and variants is completed now.

Consider B a client of A. If B has to manipulate publications through a variable like p it can be done in the following way :

p: PUBLICATION

If we must differentiate between the various cases of p, it can be done as follows:

case p of
book: ...Instructions which may access the field p l publisher...
journal: ...Instructions which may access fields p l volume, pl issue...
proceedings: ...Instructions which may access fields p l editor, pl place...
end

Hence, by using the case instruction, we can move choice control between variants.

The major point to be noted is that this coding sequence works fine for this list of variants of publication supported by A. But later on when a new variant like technical report of university, etc. is to be added, the definition of PUBLICATION has to be modified to cater the need of the new case.

Fair enough: you have modified the conceptual notion of publication, so you should update the corresponding type declaration. This change is logical and inevitable. Far harder to justify, however, is the other consequence: any client of A, such as B, will also require updating if it used a structure such as the above, relying on an explicit list of cases for p. This may, as we have seen, be the case for most clients.

Conclusion

References