CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Raymond Lewallen

Framework Design, Agile Coach, President Oklahoma City Developers Group, Microsoft MVP C#, TDD, Continuous Integration, Patterns and Practices, Domain Driven Design, Speaker, VB.Net, C# and Sql Server

Coupling, Abstractness, Stability - Measuring and Applying Code Metrics

In a comment to this post, Darrell suggested I describe where high factors of coupling are appropriate.  I’ll take it one step further and show you how to use those factors to determine the stability of an assembly and application, measure abstractness, and how to look at both to determine how useful your assembly actually is.

Stability is measured by determining how easily you can change an assembly without that change having impact on other assemblies within the application.

An assembly with high afferent coupling (other assemblies depend on it), which is a highly responsible assembly, is an assembly that has lots of reuse throughout your application.  These assemblies are also, by design, typically the most stable assemblies in the application because assemblies with a high level of responsibility to other assemblies are difficult to change without impacting its dependents.  An example of a highly responsible assembly (high afferent coupled assembly) would be an assembly that contains business objects, because business objects get used throughout the application, and if you change a business object, this has major impact on the rest of the application.

An assembly with high efferent coupling (depends on other assemblies), is an assembly that is highly dependent on other assemblies in your application.  These assemblies are OK with being instable, because changing them doesn’t involved a great deal of impact on other assemblies within the application.  Highly efferent coupled assemblies have little responsibility to the rest of the application, but are highly dependent on the other assemblies.  GUI layer assemblies (code-behind assemblies in Asp.Net) are a prime example of high efferent coupled, low afferent coupled assembly.

So now that we understand where afferent and efferent coupling takes place, how do you use that to figure out the instability of your assemblies?  Well, there is a formula for that:

I = Ce / (Ce + Ca)

Where:

  • I = degree of instability of an assembly ranging from zero to one
    • Zero indicates stability.  One indicates instability.
  • Ce = efferent coupling (outgoing dependencies)
  • Ca = afferent coupling (incoming dependencies)

The closer I is to zero, the more stable and responsible the assembly is.  This is an indication of more incoming dependencies (Ca) than outgoing dependencies (Ce).  Again, stable packages are difficult to change without impacting the rest of the application.  As I approaches one, this indicates a more instable, less responsible, more dependent, easier to change assembly.

So now, how do you make use of this?  You’re going to have assemblies that are both stable and instable in your application.  That’s the way things work.  You’re goal, as a developer, is to make an assembly as close to stable (I = 0) or instable (I = 1) as possible, given the particular assembly’s role in your application.  You’ll goal isn’t actually to reach a value of zero or one, but to get close to it.

In .Net, as in all OOP languages, we can use abstract classes to increase the stability of an assembly.  Abstract classes pull away what a class is supposed to do from how its actually done, which is handled in an inheriting class.  Abstract classes are completely stable classes themselves, and an assembly full of abstract types would qualify as a completely stable assembly.  Concrete classes do work and do not necessarily define what work.  Concrete classes typically get the “what am I supposed to do” by inheriting from an abstract class.  The concrete class then implements the “this is how to do that work”.  Concrete classes are more instable, because they encapsulate actual work and have less dependents/more dependencies.

So here’s the formula for determining the abstractness of an assembly:

A = Na / Nc

Where:

  • A = abstractness of an assembly
    • Zero is a completely concrete assembly. One is a completely abstract assembly.
  • Na = number of abstract classes in the assembly
  • Nc = number of concrete classes in the assembly

 By taking the design metrics we have talked about, you can determine just how useful your assembly is.  If you have an abstract assembly, but it is highly instable, you’ve really messed up somewhere, because you have an assembly that doesn’t do any work, but is highly dependent on other assemblies.  That is a very useless assembly.  In constract, if you have a highly concrete assembly that is also highly stable, you’re going to have a nightmare trying to make changes to that assembly, because it is doing a lot of work, and also is highly responsible to other assemblies in the application.

Last month I posted a few tools that analyze your assemblies and provide this information to you.  Definately check these out and look at some of your code metrics to determine what kind of path you’re on and headed down.



Comments

Jeffrey Palermo said:

Awesome!
# July 17, 2005 10:28 PM

Ranjan said:

Excellent article. I hope you can provide some insight on how to use Stability as a metric in real world applications.
As you said, a concrete stable assembly is going to be an issue, but thats what we are looking for, right? (atleast by the definition, "Stability is measured by determining how easily you can change an assembly without that change having impact on other assemblies within the application")
# July 18, 2005 2:09 AM

Raymond Lewallen said:

Jeffrey,

Thanks. I wonder how many people are unaware of the impact analyzing code metrics can have? The metrics I have described above can tell you so very much about the state of your application and how easy or hard it is to build upon and maintain. I hope a lot of people take this information and put it to use.
# July 18, 2005 6:47 AM

Raymond Lewallen said:

Ranjan,

Really not much insight to provide on using Stability. It is really as simple as this:

The more abstract an assembly is, the more stable it should be. The more concrete an assembly is, the more instable it should be.

The more stable and abstract an assembly is, the higher in the compile sequence it should be (higher meaning being compiled before other assemblies). The more concrete and instable an assembly is, the further down (compiled after other assemblies) in the compile sequence it should occur.

Instable abstract assemblies have very little use. They occur deep into the compile sequence of your application and have a high degree of dependence on other assemblies. That is not good use of an abstract assembly. Concrete and stable assemblies exist, especially in data access layers where work is being done. This does not make the assembly useless, but does make it very difficult to make changes to the assembly because so many other assemblies depend on it.
# July 18, 2005 6:52 AM

darrell said:

Very nice.
# July 18, 2005 8:21 AM

Raymond Lewallen said:

A beginner's look at refactoring, and 4 major design pitfalls to look for.
# July 18, 2005 11:58 AM

Robin Curry said:

# July 29, 2005 2:36 AM

Robin Curry said:

# August 1, 2005 11:17 AM

Robin Curry said:

# August 26, 2005 5:34 PM

Robin Curry said:

# August 26, 2005 5:43 PM

Robin Curry said:

# August 27, 2005 10:25 AM

Robin Curry said:

# August 29, 2005 9:49 PM

Robin Curry said:

# August 29, 2005 9:51 PM

Robin Curry said:

# August 29, 2005 11:14 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Raymond Lewallen

Working primarily in the public sector during his career, Raymond has designed and built several high profile enterprise level applications for all levels of the government. Raymond now works as a solutions architect for EMC. Raymond is an agile coach, Microsoft MVP C# and also president of the Oklahoma City Developers Group and Oklahoma Agile Developers Group. Raymond spends a lot of his time learning and teaching such things as Test Driven Development, Domain Driven Design, Design Patterns and Extreme Programming practices and principles, to name a few. Raymond is also an advocate of Alt.Net. Raymond is primarily a framework guy, so don't ask him anything about UI :) Check out Devlicio.us!