CSC/ECE 517 Fall 2007/wiki3 8 as: Difference between revisions
No edit summary |
No edit summary |
||
(22 intermediate revisions by the same user not shown) | |||
Line 17: | Line 17: | ||
<h2>Packages</h2> | <h2>Packages</h2> | ||
[http://www.objectmentor.com/omTeam/martin_r.html Robert C. Martin] describes the term <b><i>“Package”</i></b> as | [http://www.objectmentor.com/omTeam/martin_r.html Robert C. Martin] describes the term <b><i>“Package”</i></b> as “a logical grouping of declarations that can be imported into other programs”. Since packages serve as a container for a group of classes, those classes need to be partitioned based on some criteria and then allocate the partitioned classes to their appropriate packages. The relationship between those packages identifies a high level organization of the application. Martin has put together many design principles for guiding the creation, interrelationship and use of packages. <br/><br/> | ||
Three principles of <i>[http://parlezuml.com/blog/?postid=361 Package Cohesion]</i> are – | Three principles of <i>[http://parlezuml.com/blog/?postid=361 Package Cohesion]</i> are – | ||
<li> Reuse/Release Equivalency principle </li> | <li> Reuse/Release Equivalency principle </li> | ||
<li> Common Closure principle </li> | <li> Common Closure principle </li> | ||
<li> Common Reuse principle </li> | <li> Common Reuse principle </li><br/> | ||
Three principles of <i>Package Coupling</i> are – | Three principles of <i>Package Coupling</i> are – | ||
<li> Acyclic Dependencies principle</li> | <li> Acyclic Dependencies principle</li> | ||
Line 31: | Line 31: | ||
<h3>Reuse/Release Equivalency principle</h3> | <h3>Reuse/Release Equivalency principle</h3> | ||
When developers reuse a class, it is a disadvantage when they have to recompile the code everytime | When developers reuse a class, it is a disadvantage when they have to recompile the code, everytime changes are done to the class. There should be a process of controlled release to enable maximum class reuse. The principle as stated by R.Martin in his article [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity] - <br/> | ||
“The Granule of Reuse is the granule of Release. | “The Granule of Reuse is the granule of Release. | ||
Only components that are released through a tracking system can be effectively reused. | Only components that are released through a tracking system can be effectively reused. | ||
Line 37: | Line 37: | ||
<br/> | <br/> | ||
The packages of a reusable component should be grouped based on the usage and not | The packages of a reusable component should be grouped based on the usage and not on common functionality or any other arbitrary category. Usually most of the classes like the containers and iterators are usually grouped based on their collaboration with other library classes. Reusuability is an important principle of OOD since it helps to eliminate the creation of duplicate code in the system. If a class in the package is being reused, then all the classes in the package have to be reused. Whenever the packages are fixed for bugs or enhanced by the author, a new version of the package can be added to the system.<br/> | ||
[[Image:Banking package.JPG|thumb|500px|right|Courtesy: [http://www.parlezuml.com/metrics/OO%20Design%20Principles%20&%20Metrics.pdf OO Design Principles & Metrics]]] | |||
<h4>Example</h4> | <h4>Example</h4> | ||
If | If the banking package is being used by many applications, then it should be a packaged into a single unit as shown in the diagram. Whenever a change is done to any class in the package, a revised version of the whole unit should be released. This helps the users of this package to keep track of the latest versions, even if they are using only a particular class in the package.<br/> | ||
<h4>Links</h4> | <h4>Links</h4> | ||
Line 49: | Line 51: | ||
<h3>Common Closure Principle</h3> | <h3>Common Closure Principle</h3> | ||
This principle ensures that classes within a released component share a common closure, i.e. if a class in a released package requires a change then all the classes in that package needs a change. The principle as stated by R. Martin in his article [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity] – <br/> | This principle ensures that classes within a released component, share a common closure, i.e. if a class in a released package requires a change, then all the classes in that package needs a change. The principle as stated by R. Martin in his article [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity] – <br/> | ||
“The classes in a package should be closed together against the same kinds of changes. | “The classes in a package should be closed together against the same kinds of changes. | ||
A change that affects a package affects all the classes in that package” | A change that affects a package affects all the classes in that package” | ||
<br/> | <br/> | ||
Maintainability is | Maintainability is an imporant concept of OOD than Reusability. If two classes are either physically or conceptually tightly bound, that they change together, then it is more reasonable to use them in a single package. The advantage is that it minimizes the workload of releasing, revalidating and redistributing the software and the impact of change on the programmer. In other words, it restricts changes to a fewer packages and also reduces the frequency of package release. | ||
<h4>Example</h4> | <h4>Example</h4> | ||
Since each class in the | Since each class in the banking package is dependent on one another, any changes made to one class is reflected on the other and hence, the classes should be used together. If the classes are available on different packages, then it would be a difficulty in releasing the application since each class that underwent change should be put into a package and then released. By packaging the classes that change together, maintainability is a lot easier. | ||
<h4>Links</h4> | <h4>Links</h4> | ||
Line 81: | Line 83: | ||
<h2>Package Coupling Principles</h2> | <h2>Package Coupling Principles</h2> | ||
<h3>Acyclic Dependencies principle</h3> | <h3>Acyclic Dependencies principle</h3> | ||
This principle ensures that the packages are not indirectly dependent on it. Martin’s solution to this problem of dependency is to partition the development environment into releasable packages. The dependency problem can be solved by drawing the dependency graph structure of the packages by using the packages as nodes and directed dependency releationships as edges. Such a structure is called the [http://en.wikipedia.org/wiki/Directed_acyclic_graph Directed Graph]. The principle in Martin’s article [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity] states the Acyclic Dependencies Principle as- | This principle ensures that the packages are not indirectly dependent on it. Martin’s solution to this problem of dependency is to partition the development environment into releasable packages. The dependency problem can be solved by drawing the dependency graph structure of the packages by using the packages as nodes and directed dependency releationships as edges. Such a structure is called the [http://en.wikipedia.org/wiki/Directed_acyclic_graph Directed Graph]. The principle in Martin’s article [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity] states the Acyclic Dependencies Principle as- | ||
Line 86: | Line 89: | ||
That is, there must be no cycles in the dependency structure”. | That is, there must be no cycles in the dependency structure”. | ||
[[Image:Package_dependency.JPG|thumb|300px|none|Courtesy: [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity]]] | |||
The article gives the effect of a cycle in a package dependency graph and explains how to break that cycle. <br/> | The article gives the effect of a cycle in a package dependency graph and explains how to break that cycle. <br/> | ||
In C++, packages depend on on another by using <code>#include</code> in the header of a class, which is present in a different class. Such a dependency relationship between packages can be depicted by the diagram. | In C++, packages depend on on another by using <code>#include</code> in the header of a class, which is present in a different class. Such a dependency relationship between packages can be depicted by the diagram. | ||
<h4>Example</h4> | <h4>Example</h4> | ||
Considering the package dependency graph displayed, we can see that there is a cycle in the dependency since the package MyDialogs has a dependency on MyApplication. For instance, if the developers of MyTasks want to make a release, then it must be compatible with Task, Database and MyDialogs. But with the cycle in place, | [[Image:Package_dependency_Graph.JPG|thumb|400px|right|Courtesy: [http://www.objectmentor.com/resources/articles/granularity.pdf Granularity]]] | ||
This situation can be prevented by breaking the cycle. There are two options to break the cycle - Applying the Dependency Inversion Principle or | |||
Considering the package dependency graph displayed, we can see that there is a cycle in the dependency since the package MyDialogs has a dependency on MyApplication. For instance, if the developers of MyTasks want to make a release, then it must be compatible with Task, Database and MyDialogs. But with the cycle in place, MyTasks has to compatible with MyApplication, TaskWindow and MessageWindow. In other words, MyTasks is now dependent on all the packages in the system. Another reason to break cycles is that if a unit test is to be done on any one of the package, it requires a complete build of all the packages since they are linked and have virtually become one large package. <br/> | |||
This situation can be prevented by breaking the cycle. There are two options to break the cycle - Applying the Dependency Inversion Principle or Creating a new package that depends on MyDialogs and MyApplication. All the classes that depend on both the packages are moved to the new package. | |||
<h4>Links</h4> | <h4>Links</h4> | ||
Line 105: | Line 111: | ||
A package should only depend upon packages that are more stable that it is.” | A package should only depend upon packages that are more stable that it is.” | ||
The article also explains about [http://en.wikipedia.org/wiki/Software_package_metrics Stability Metrics] which is used to measure the stability of the package. | The article also explains about [http://en.wikipedia.org/wiki/Software_package_metrics Stability Metrics] which is used to measure the stability of the package. The Instability(I) metric can be calculated using the afferent and efferent couplings and has a range [0,1]. When the I metric is 1, it means that this package depends on other packages but no other package depend on it. Such a package is very instable because there is no reason for the package to change due to non availability of dependents, and it changes only when the package it depends on undergoes a change. When the I metric is zero, there are packages depending on this package but it is not dependent on other packages. Such a class is responsible and independent. The principle says that the I metric of the package should be greater than the I metric of all the packages it depends on. | ||
The principle also mentions that not all packages can be maximally stable, since it would render the system unchangeable.<br/> | |||
<h4>Example</h4> | <h4>Example</h4> | ||
Instead of having separate classes like FileLogger or DBLogger, there can be a single interface called Logger | |||
<h4>Links</h4> | <h4>Links</h4> | ||
Line 121: | Line 129: | ||
<br/> | <br/> | ||
It also gives a way to measure the abstractness of a package. The mathematical explanation helps to decide if a package is abstract or concrete. The “main sequence” explained in the derivation is the position where a package is neither ‘too abstract’ nor ‘too instable’. | It also gives a way to measure the abstractness(A) of a package. The A metric is calculated as the ratio of the abstract classes in a package to the total number of classes in a package and ranges from 0 to 1. The value zero indicates that there are no abstract classes in the package and the value 1 indicates that there are no other classes except the abstract classes. Since this metric is not so perfect, Martin evaluates the abstractness based on the ratio of virtual and non-virtual functions. | ||
The mathematical explanation in the article helps to decide if a package is abstract or concrete. The “main sequence” explained in the derivation is the position where a package is neither ‘too abstract’ nor ‘too instable’. The article also provides a link [http://www.oma.com Object Mentor] which provides a bash script that scans C++ directory structure and calculate all the metrics. <br/> | |||
[[Image:Copy Class Diagram.JPG|thumb|200px|right|Courtesy: [http://www.objectmentor.com/resources/articles/stability.pdf Stability]]] | |||
<h4>Example</h4> | <h4>Example</h4> | ||
In the example, the Copy class contains the Reader and Writer abstract classes. The abstract classes are highly stable since they are not dependent on anything but are being depended upon by Copy class and its subclasses. Hence for a package to be stable, it should also contain abstract classes that allow it to be extended. | |||
<h4>Links</h4> | <h4>Links</h4> |
Latest revision as of 22:53, 28 November 2007
OO Package Design Principles
O-O design guru Bob Martin has developed a set of design principles that relate to packages (one level above the class-oriented strategies we consider in this course). Report on the
Find the best descriptions and examples of each that you can find on the Web.
Packages
Robert C. Martin describes the term “Package” as “a logical grouping of declarations that can be imported into other programs”. Since packages serve as a container for a group of classes, those classes need to be partitioned based on some criteria and then allocate the partitioned classes to their appropriate packages. The relationship between those packages identifies a high level organization of the application. Martin has put together many design principles for guiding the creation, interrelationship and use of packages.
Three principles of Package Cohesion are –
Three principles of Package Coupling are –
Package Cohesion Principles
Reuse/Release Equivalency principle
When developers reuse a class, it is a disadvantage when they have to recompile the code, everytime changes are done to the class. There should be a process of controlled release to enable maximum class reuse. The principle as stated by R.Martin in his article Granularity -
“The Granule of Reuse is the granule of Release. Only components that are released through a tracking system can be effectively reused. This granule is the package.”
The packages of a reusable component should be grouped based on the usage and not on common functionality or any other arbitrary category. Usually most of the classes like the containers and iterators are usually grouped based on their collaboration with other library classes. Reusuability is an important principle of OOD since it helps to eliminate the creation of duplicate code in the system. If a class in the package is being reused, then all the classes in the package have to be reused. Whenever the packages are fixed for bugs or enhanced by the author, a new version of the package can be added to the system.
Example
If the banking package is being used by many applications, then it should be a packaged into a single unit as shown in the diagram. Whenever a change is done to any class in the package, a revised version of the whole unit should be released. This helps the users of this package to keep track of the latest versions, even if they are using only a particular class in the package.
Links
Principles of Object-Oriented Design- gives a brief explanation about Reuse/Release Equivalency principle on page 15. It describes how packages of reusable components have to be grouped to enable maximum reuse.
Reuse/Release Equivalency Principle- is a blog that explains the REP principle and also provides the reason why not individual reusable classes are being released.
OO Design Principles- page 54 of this document gives the requirements of a reusable software and provides summary of this principle.
Common Closure Principle
This principle ensures that classes within a released component, share a common closure, i.e. if a class in a released package requires a change, then all the classes in that package needs a change. The principle as stated by R. Martin in his article Granularity –
“The classes in a package should be closed together against the same kinds of changes. A change that affects a package affects all the classes in that package”
Maintainability is an imporant concept of OOD than Reusability. If two classes are either physically or conceptually tightly bound, that they change together, then it is more reasonable to use them in a single package. The advantage is that it minimizes the workload of releasing, revalidating and redistributing the software and the impact of change on the programmer. In other words, it restricts changes to a fewer packages and also reduces the frequency of package release.
Example
Since each class in the banking package is dependent on one another, any changes made to one class is reflected on the other and hence, the classes should be used together. If the classes are available on different packages, then it would be a difficulty in releasing the application since each class that underwent change should be put into a package and then released. By packaging the classes that change together, maintainability is a lot easier.
Links
Principles of Object-Oriented Design - gives a brief explanation about the common closure principle on page 19. It also compares reusability and maintainability by specifying when to use REP, CCP and CRP.
Common Closure Principle - is a blog by Abhijit Nadgouda which gives a brief introduction to the Common Closure Principle.
OO Design Principles & Metrics – defines the principle with a basic diagram as an example.
Common Reuse Principle
The principle is stated by R.Martin in his article Granularity as –
“The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all”
This principle helps to decide how the classes can be put into a package. If the classes are being reused together, then they should be put into a package. In his article, Martin gives a simple example of a container class and its associated iterators which can be put into a package since the classes are tightly coupled to each other and hence they have to be placed in a single package.
Example
A package for matrix calculations, should consist of only matrix functions and not the trigonometric functions. It makes the principle of reuse a lot easier.
Links
Common Reuse Principle - is a link to a blog that describes the necessity of the common reuse principle. It also states the principle and gives an example about a package of matrix calculations.
Principles of Object-Oriented Design - gives bulleted hint about the principle. It also gives the Façade pattern as an example of a common reuse in practice.
Package Coupling Principles
Acyclic Dependencies principle
This principle ensures that the packages are not indirectly dependent on it. Martin’s solution to this problem of dependency is to partition the development environment into releasable packages. The dependency problem can be solved by drawing the dependency graph structure of the packages by using the packages as nodes and directed dependency releationships as edges. Such a structure is called the Directed Graph. The principle in Martin’s article Granularity states the Acyclic Dependencies Principle as-
"The Dependency Structure between packages must be a directed acyclic graph(DAG). That is, there must be no cycles in the dependency structure”.
The article gives the effect of a cycle in a package dependency graph and explains how to break that cycle.
In C++, packages depend on on another by using #include
in the header of a class, which is present in a different class. Such a dependency relationship between packages can be depicted by the diagram.
Example
Considering the package dependency graph displayed, we can see that there is a cycle in the dependency since the package MyDialogs has a dependency on MyApplication. For instance, if the developers of MyTasks want to make a release, then it must be compatible with Task, Database and MyDialogs. But with the cycle in place, MyTasks has to compatible with MyApplication, TaskWindow and MessageWindow. In other words, MyTasks is now dependent on all the packages in the system. Another reason to break cycles is that if a unit test is to be done on any one of the package, it requires a complete build of all the packages since they are linked and have virtually become one large package.
This situation can be prevented by breaking the cycle. There are two options to break the cycle - Applying the Dependency Inversion Principle or Creating a new package that depends on MyDialogs and MyApplication. All the classes that depend on both the packages are moved to the new package.
Links
Principles of Package Design - describes how to apply ADP and break any cycles that appear in the dependency graph. Although there is not much information, it gives quick points on the principle.
OptimalAdvisor - is a static code analysis and refactoring tool and It can be used to indicate problems and solutions. The tool finds problems in dependency structure and suggests solutions to fix them by using the acyclic dependencies principle.
Stable Dependencies principle
In his article Stability Martin gives detailed explanation and examples about stability and dependency. He stresses on the stability property of classes, as stables classes are both Independent and Responsible. The principle is states as –
“The dependencies between packages in a design should be in the direction of the stability of the packages. A package should only depend upon packages that are more stable that it is.”
The article also explains about Stability Metrics which is used to measure the stability of the package. The Instability(I) metric can be calculated using the afferent and efferent couplings and has a range [0,1]. When the I metric is 1, it means that this package depends on other packages but no other package depend on it. Such a package is very instable because there is no reason for the package to change due to non availability of dependents, and it changes only when the package it depends on undergoes a change. When the I metric is zero, there are packages depending on this package but it is not dependent on other packages. Such a class is responsible and independent. The principle says that the I metric of the package should be greater than the I metric of all the packages it depends on.
The principle also mentions that not all packages can be maximally stable, since it would render the system unchangeable.
Example
Instead of having separate classes like FileLogger or DBLogger, there can be a single interface called Logger
Links
OO Design Principles & Metrics– gives reasoning why stable dependencies principle should be applied on the package. It also explains the stability metrics with an example.
Stable Abstractions principle
This principle states that a stable package should be abstract too, so that it gives an opportunity to be extended. The article Stability by Martin gives the best description and example of the principle. It is stated as –
“Packages that are maximally stable should be maximally abstract. Instable packages should be concrete. The abstraction of a package should be in proportion to its stability.”
It also gives a way to measure the abstractness(A) of a package. The A metric is calculated as the ratio of the abstract classes in a package to the total number of classes in a package and ranges from 0 to 1. The value zero indicates that there are no abstract classes in the package and the value 1 indicates that there are no other classes except the abstract classes. Since this metric is not so perfect, Martin evaluates the abstractness based on the ratio of virtual and non-virtual functions.
The mathematical explanation in the article helps to decide if a package is abstract or concrete. The “main sequence” explained in the derivation is the position where a package is neither ‘too abstract’ nor ‘too instable’. The article also provides a link Object Mentor which provides a bash script that scans C++ directory structure and calculate all the metrics.
Example
In the example, the Copy class contains the Reader and Writer abstract classes. The abstract classes are highly stable since they are not dependent on anything but are being depended upon by Copy class and its subclasses. Hence for a package to be stable, it should also contain abstract classes that allow it to be extended.
Links
Stable Abstractions Principle - gives a brief description of stable abstractions principle. The blog speaks about the relationship between stability and abstractness. It refers to Martin’s mathematical explanation of measurement of abstractness in a package.
Principles of Package Design - gives a brief hint of the stable abstraction principle. It also describes the relationship between stability and abstractness.
Principles of Object-Oriented Design - defines the principle and describes how to measure the abstractness of a package.
References
1. Stability
2. Design Principles and Design Patterns
3. Granularity
4. OO Design Principles & Metrics
5. Principles of Object-Oriented Design
External Links
1. A Summary of OO Principles
2. Principles of Agile Version Control: From OOD to TBD
3. Object Mentor - Published Articles
4. Principles of OOD by Robert Martin
5. What Makes A Good Object-Oriented Design?
6. Principles Of Object Oriented Design