CSC/ECE 517 Summer 2008/wiki3 8 smr: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(12 intermediate revisions by the same user not shown)
Line 2: Line 2:
----
----


== Introduction ==
== Meyer's Principles ==  


What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?
=== Small Interfaces ===


=== Small Interfaces ===
Meyer’s principle of small [http://en.wikipedia.org/wiki/Interface_%28computer_science%29 interfaces] states that if two [http://en.wikipedia.org/wiki/Module_%28programming%29 modules] must interact, then the least amount of information should be shared between them [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1].  The correct implementation of this principle often depends on the programmer responsible for implementing the interface.  By designing and implementing a small interface, the programmer also minimizes [http://en.wikipedia.org/wiki/Coupling_%28computer_science%29 coupling] between modules.
 
Below is an example of a small interface written in [http://java.sun.com/javase/6/docs/technotes/guides/language/index.html Java].
 
  public class EmployeeDb {
    public List<Employee> findEmployees(string name, Date birthDate) { // implementation … }
    public Employee getEmployee(int employeeId) { // implementation… }
    public void saveEmployee(Employee emp) { // implementation… }
  }
 
In this example, the EmployeeDb interface was kept relatively small, which in turn will reduces coupling with clients.  Using this same example, we can violate the principle of small interfaces by exposing too much information to clients.
 
  public class EmployeeDb {
    public List<Employee> findEmployees(string name, Date birthDate) { // implementation … }
    public List<Employee> findEmployees(FindCriteria criteria) { // implementation … }
    public void setDb(DbConnection db) { // implementation… }
    public DbConnection getDb() { // implementation… }
    public void setTransaction(Transaction trx) { // implementation… }
    public Transaction getTransaction() {  // implementation… }
    public Employee getEmployee(int employeeId) { // implementation… }
    public void saveEmployee(Employee emp) { // implementation… }
    public class FindCriteria {
      public FindCriteria(int employeeId, String name, Date birthDate, String phone) { // implementation… }
      public getEmployeeId() { // implementation… }
      public getName() { // implementation… }
      public getBirthDate() { // implementation… }
      public getPhone() { // implementation… }
    }
  }


What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?
The above example adds five additional operations to our interface, which in turn increases the coupling of the EmployeeDb class to its clients.  This coupling hinders the ability to change the EmployeeDb class to use a different data source without affecting clients.  In addition to exposing extra operations, this version of the EmployeeDb class also exposes a nested class to its clients.  This again is additional information being shared that potentially counters the principle of small interfaces.  It is worth noting that the [http://docs.eiffel.com/eiffelstudio/docs_no_content.html Eiffel] language does not support nested classes.


"The small interface or weak coupling principle states that if any two modules or objects communicate they should exchange as little information as possible" [http://www.cit.gu.edu.au/~francis/sa2000/unit2.htm].
All [http://en.wikipedia.org/wiki/Object-oriented_programming object-oriented] languages support the ability to abide by this principle, but they also support the ability to violate this principle. Ultimately, programmers must choose to follow the principle of small interfaces, thereby reducing coupling within their applications.


=== Explicit Interfaces ===
=== Explicit Interfaces ===


What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?
Meyer’s principle of explicit interfaces states that if two modules must interact, then the interaction should be plainly visible [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1].  Similar to the principle of small interfaces, this principle also speaks to the degree of coupling within a system.  For instance, two modules may inadvertently interact with one another through their individual interaction with a common [http://en.wikipedia.org/wiki/Global_variable global variable].  This is an example of [http://www.site.uottawa.ca:4321/oose/commoncoupling.html common coupling] and violates the principle of explicit interfaces.
 
Most object-oriented languages will support the principle of explicit interfaces, but programmers must be sure to keep this principle in check.
 
=== Uniform-access ===


"The principle of explicit interfaces maintains that all communications between modules must be visible. This means that as well as minimizing the number of interfaces and the amount of communication, all communications must also be clearly represented in the system:
Meyer’s principle of uniform-access states that operations of a module must be accessible using a uniform notation.  In addition, this notation should not reveal to callers whether the evaluated operation was performed by accessing storage or by a computation [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1].  Languages that support the uniform-access principle allow the implementation of a storage based property to change to a computed property without requiring changes to clients.
In the following diagram we can see that a tightly coupled relationship exits between module A and module B, as they are both reliant on variable x. In order to adhere to the criteria of decomposability, composibilty, continuity and understandability the data relationship between A and B must be clearly marked:


[http://www.ruby-lang.org/en/ Ruby] supports the uniform-access principle as illustrated by this example.


It is not disirable that A can change the value of x without this being visible in its code. Similarly, B’s interests in x must also be clearly visible" [http://www.cit.gu.edu.au/~francis/sa2000/unit2.htm].
  class Circle
    # circumference and area are calculated and stored
    attr_accessor :circumference, :area
    PI = 3.142
   
    def initialize(radius)
      @circumference = PI*radius*2
      @area = PI*radius*radius
    end
  end


=== Uniform-access ===
  # create a new circle
  c = Circle.new(4)
  # access properties of circle
  puts c.circumference
  puts c.circumference()
  puts c.area
  puts c.area ( )
 
In the above example, the <code>circumference</code> and <code>area</code> properties of <code>Circle</code> were referenced from storage.  We can easily change those properties to be computed when accessed without any changes to the client. 
 
  class Circle
    # circumference and area are calculated and stored
    PI = 3.142
   
    def circumference()
      PI*@radius*2
    end
 
    def area()
      PI*@radius*radius
    end
   
    def initialize(radius)
      @radius = radius
    end
  end


What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?
  # create a new circle
  c = Circle.new(4)
  # access properties of circle
  puts c.circumference
  puts c.circumference()
  puts c.area
  puts c.area ( )


[http://en.wikipedia.org/wiki/Uniform_access_principle]
[http://msdn.microsoft.com/en-us/vcsharp/aa336809.aspx C#] is another language that supports the uniform-access through the use of its [http://en.wikipedia.org/wiki/Property_%28programming%29 properties] language feature.  Java, [http://en.wikipedia.org/wiki/C_(programming_language) C], and [http://en.wikipedia.org/wiki/C%2B%2B C++] are languages that do not support the uniform-access principle because accessing a field requires a different notation than accessing functions.


=== Self-documentation ===
=== Self-documentation ===


What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?
Meyer’s principle of self-documentation states that all information about a particular module should be included as part of that module [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1].  The self-documentation principle encourages keeping documentation related to a module embedded directly within the module, thereby encouraging the documentation of module to be synchronized with its functionality.  The Eiffel language does this very elegantly as shown in this [https://svn.origo.ethz.ch/eiffelstudio/branches/eth/origo_integration/Src/Eiffel/switch/communication/status/call_stack/eiffel_call_stack_classic.e example].
   
Java and many of the [http://www.microsoft.com/NET/ .NET] language such as C#, provide special language features to promote the self-documentation principle.  In Java, programmers can use the special [http://en.wikipedia.org/wiki/Javadoc Javadoc] notation to describe classes and methods.  Here is an example of that notation for describing a [http://java.sun.com/j2se/1.4.2/docs/api/java/util/Stack.html Stack].
  /**
  * The Stack class represents a last-in-first-out (LIFO) stack of objects.
  */
  public class Stack {
 
    /**
    * Creates an empty Stack.
    */
    public Stack() { // implementation... }
 
    /**
    * Tests if this stack is empty.
    */
    public boolean empty() { // implementation... }
 
    /**
    *  Looks at the object at the top of this stack without removing it from the stack.
    */   
    public Object peek() { // implementation... }
   
    /**
    * Removes the object at the top of this stack and returns that
    * object as the value of this function.
    */
    public Object pop() { // implementation... }
   
    /**
    * Pushes an item onto the top of this stack.
    */
    public Object push(Object item) { // implementation... }
  }
 
C# also has a special syntax for embedding [http://msdn.microsoft.com/en-us/library/b2s063f7(VS.80).aspx XML Documentation] within its modules, which is highlighted by the following example.


"The designer of a module should strive to make all information about the module part of the module itself" [ftp://ftp.idc.ac.il/pub/courses/cs/oosc/ch1-3.ppt#288,34,Self-Documentation Principle].


=== Single-choice ===
  /// <summary>
  /// The Stack class represents a last-in-first-out (LIFO) stack of objects. 
  /// </summary>
  public class Stack {
 
    /// <summary>
    /// Creates an empty Stack.
    /// </summary>
    public Stack() { // implementation... }
 
    /// <summary>
    /// Tests if this stack is empty.
    /// </summary>
    public bool empty() { // implementation... }
 
    /// <summary>
    ///  Looks at the object at the top of this stack without removing it from the stack.
    /// </summary>   
    public object peek() { // implementation... }
 
    /// <summary>
    /// Removes the object at the top of this stack and returns
    /// that object as the value of this function.
    /// </summary>
    public object pop() { // implementation... }
   
    /// <summary>
    /// Pushes an item onto the top of this stack.
    /// </summary>
    public object push(object item) { // implementation... }
  }


What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?
This principle is a dificult to follow in C++, where syntax exists for creating comments, but there are not universally accepted conventions or tools for extracting documentation from the code.


[http://en.wikipedia.org/wiki/Single_choice_principle]
=== Single-choice ===


== Conclusion ==
Meyer’s principle of single-choice states that if a system provides a set of alternatives, then the complete list of alternatives are known by only one module [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1].  The single-choice principle limits the number of modules that must maintain the list of alternatives to one, thereby simplifying maintenance.  The single-choice principle has to do with separation of responsibility and encapsulation.  Like the small interfaces and explicit interfaces principles, following the single-choice principle is a design decision made by the programmer.  All object-oriented languages support the ability to abide by this principle, as long as the programmer follows good principles of object-oriented design.


== Also See ==  
== Also See ==  
Line 51: Line 186:
* [http://www.geocities.com/tablizer/meyer1.htm Critique of Bertrand Meyer's Object Oriented Software Construction]
* [http://www.geocities.com/tablizer/meyer1.htm Critique of Bertrand Meyer's Object Oriented Software Construction]
* [http://www.cetus-links.org/oo_eiffel.html Object Oriented Language: Eiffel]
* [http://www.cetus-links.org/oo_eiffel.html Object Oriented Language: Eiffel]
== References ==
# [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1 Object Oriented Software Construction, 2nd edition, page 48]
# [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1 Object Oriented Software Construction, 2nd edition, page 50]
# [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1 Object Oriented Software Construction, 2nd edition, page 57]
# [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1 Object Oriented Software Construction, 2nd edition, page 54]
# [http://www.amazon.com/Object-Oriented-Software-Construction-Prentice-Hall-International/dp/0136291554/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217110101&sr=8-1 Object Oriented Software Construction, 2nd edition, page 63]

Latest revision as of 01:15, 31 July 2008

Meyer's principles. Bertrand Meyer is a prominent author in o-o design. He has developed a set of principles, many of which are embodied in the Eiffel language. Consider the principles of small interfaces, explicit interfaces, the uniform-access principle, the self-documentation principle, and the single-choice principle. What are good examples of each? Do other languages besides Eiffel support them? Is it difficult to follow these principles in certain o-o languages?


Meyer's Principles

Small Interfaces

Meyer’s principle of small interfaces states that if two modules must interact, then the least amount of information should be shared between them [1]. The correct implementation of this principle often depends on the programmer responsible for implementing the interface. By designing and implementing a small interface, the programmer also minimizes coupling between modules.

Below is an example of a small interface written in Java.

 public class EmployeeDb {
   public List<Employee> findEmployees(string name, Date birthDate) { // implementation … }
   public Employee getEmployee(int employeeId) { // implementation… }
   public void saveEmployee(Employee emp) { // implementation… }
 }

In this example, the EmployeeDb interface was kept relatively small, which in turn will reduces coupling with clients. Using this same example, we can violate the principle of small interfaces by exposing too much information to clients.

 public class EmployeeDb {
   public List<Employee> findEmployees(string name, Date birthDate) { // implementation … }
   public List<Employee> findEmployees(FindCriteria criteria) { // implementation … }
   public void setDb(DbConnection db) { // implementation… }
   public DbConnection getDb() { // implementation… }
   public void setTransaction(Transaction trx) { // implementation… }
   public Transaction getTransaction() {  // implementation… }
   public Employee getEmployee(int employeeId) { // implementation… }
   public void saveEmployee(Employee emp) { // implementation… }
   public class FindCriteria {
     public FindCriteria(int employeeId, String name, Date birthDate, String phone) { // implementation… }
     public getEmployeeId() { // implementation… }
     public getName() { // implementation… }
     public getBirthDate() { // implementation… }
     public getPhone() { // implementation… }
   }
 }

The above example adds five additional operations to our interface, which in turn increases the coupling of the EmployeeDb class to its clients. This coupling hinders the ability to change the EmployeeDb class to use a different data source without affecting clients. In addition to exposing extra operations, this version of the EmployeeDb class also exposes a nested class to its clients. This again is additional information being shared that potentially counters the principle of small interfaces. It is worth noting that the Eiffel language does not support nested classes.

All object-oriented languages support the ability to abide by this principle, but they also support the ability to violate this principle. Ultimately, programmers must choose to follow the principle of small interfaces, thereby reducing coupling within their applications.

Explicit Interfaces

Meyer’s principle of explicit interfaces states that if two modules must interact, then the interaction should be plainly visible [2]. Similar to the principle of small interfaces, this principle also speaks to the degree of coupling within a system. For instance, two modules may inadvertently interact with one another through their individual interaction with a common global variable. This is an example of common coupling and violates the principle of explicit interfaces.

Most object-oriented languages will support the principle of explicit interfaces, but programmers must be sure to keep this principle in check.

Uniform-access

Meyer’s principle of uniform-access states that operations of a module must be accessible using a uniform notation. In addition, this notation should not reveal to callers whether the evaluated operation was performed by accessing storage or by a computation [3]. Languages that support the uniform-access principle allow the implementation of a storage based property to change to a computed property without requiring changes to clients.

Ruby supports the uniform-access principle as illustrated by this example.

 class Circle
   # circumference and area are calculated and stored
   attr_accessor :circumference, :area
   PI = 3.142
   
   def initialize(radius)
     @circumference = PI*radius*2
     @area = PI*radius*radius
   end
 end
 # create a new circle
 c = Circle.new(4)
 # access properties of circle
 puts c.circumference
 puts c.circumference()
 puts c.area
 puts c.area ( )

In the above example, the circumference and area properties of Circle were referenced from storage. We can easily change those properties to be computed when accessed without any changes to the client.

 class Circle
   # circumference and area are calculated and stored
   PI = 3.142
   
   def circumference()
     PI*@radius*2
   end
 
   def area()
     PI*@radius*radius
   end
   
   def initialize(radius)
     @radius = radius
   end
 end
 # create a new circle
 c = Circle.new(4)
 # access properties of circle
 puts c.circumference
 puts c.circumference()
 puts c.area
 puts c.area ( )

C# is another language that supports the uniform-access through the use of its properties language feature. Java, C, and C++ are languages that do not support the uniform-access principle because accessing a field requires a different notation than accessing functions.

Self-documentation

Meyer’s principle of self-documentation states that all information about a particular module should be included as part of that module [4]. The self-documentation principle encourages keeping documentation related to a module embedded directly within the module, thereby encouraging the documentation of module to be synchronized with its functionality. The Eiffel language does this very elegantly as shown in this example.

Java and many of the .NET language such as C#, provide special language features to promote the self-documentation principle. In Java, programmers can use the special Javadoc notation to describe classes and methods. Here is an example of that notation for describing a Stack.

 /** 
  * The Stack class represents a last-in-first-out (LIFO) stack of objects.
  */
 public class Stack {
 
   /**
    * Creates an empty Stack.
    */
   public Stack() { // implementation... }
 
   /**
    * Tests if this stack is empty.
    */
   public boolean empty() { // implementation... }
 
   /**
    *  Looks at the object at the top of this stack without removing it from the stack.
    */    
   public Object peek() { // implementation... }
   
   /**
    * Removes the object at the top of this stack and returns that 
    * object as the value of this function.
    */
   public Object pop() { // implementation... }
   
   /**
    * Pushes an item onto the top of this stack.
    */
   public Object push(Object item) { // implementation... }
 }

C# also has a special syntax for embedding XML Documentation within its modules, which is highlighted by the following example.


 /// <summary> 
 /// The Stack class represents a last-in-first-out (LIFO) stack of objects.  
 /// </summary>
 public class Stack {
 
   /// <summary>
   /// Creates an empty Stack.
   /// </summary>
   public Stack() { // implementation... }
 
   /// <summary>
   /// Tests if this stack is empty.
   /// </summary>
   public bool empty() { // implementation... }
 
   /// <summary>
   ///  Looks at the object at the top of this stack without removing it from the stack.
   /// </summary>    
   public object peek() { // implementation... }
 
   /// <summary>
   /// Removes the object at the top of this stack and returns 
   /// that object as the value of this function.
   /// </summary>
   public object pop() { // implementation... }
   
   /// <summary>
   /// Pushes an item onto the top of this stack.
   /// </summary>
   public object push(object item) { // implementation... }
 }

This principle is a dificult to follow in C++, where syntax exists for creating comments, but there are not universally accepted conventions or tools for extracting documentation from the code.

Single-choice

Meyer’s principle of single-choice states that if a system provides a set of alternatives, then the complete list of alternatives are known by only one module [5]. The single-choice principle limits the number of modules that must maintain the list of alternatives to one, thereby simplifying maintenance. The single-choice principle has to do with separation of responsibility and encapsulation. Like the small interfaces and explicit interfaces principles, following the single-choice principle is a design decision made by the programmer. All object-oriented languages support the ability to abide by this principle, as long as the programmer follows good principles of object-oriented design.

Also See

References

  1. Object Oriented Software Construction, 2nd edition, page 48
  2. Object Oriented Software Construction, 2nd edition, page 50
  3. Object Oriented Software Construction, 2nd edition, page 57
  4. Object Oriented Software Construction, 2nd edition, page 54
  5. Object Oriented Software Construction, 2nd edition, page 63