Evaluating Coupling

Tags: metrics, ScriptCS

In a previous post I described the metrics data in the ScriptCs.Metrics script pack. In this post I will describe one way where these metrics can be relevant - I'll be focusing on class coupling (or actually type coupling).

The Visual Studio metrics gives a number indicating the amount of types a particular component is coupled to. This is interesting, but it is more interesting to be able to drill into the coupling to understand whether or not this coupling is going to cause problems for your development and long term maintainability and modifiability.

The ITypeCoupling interface provides not only information about what type your are coupled to and which assembly this makes you dependent on, it also tells you which methods, properties and events you depend on. This gives you information about how you are using a specific dependency and can guide you as to how you may wish to abstract your dependency. If you depend only on a couple of methods or properties then you may wish to create a simple façade. If the dependency is deeper, or if you have the dependency across multiple locations, then you may wish to create a full abstraction layer.

Using the ScriptCS.Metrics script pack you can analyze your code and calculate the dependencies. Using the results, you can then start querying over your dependencies to determine what your dependencies look like. This could look something like:

var pack = Require<Metrics>();
var path = Path.GetFullPath(@"..\..\MySolution.sln");
var metrics = pack.Calculate(path).Result.Cast<IProjectMetric>().ToArray();

var fooDependants =
	array.SelectMany(x => x.ClassCouplings.Where(y => y.Assembly == "foo"))
	.GroupBy(x => x.ToString())
	.Select(x => new
	{
		Name = x.Key,
		UsedMethods = x.SelectMany(y => y.UsedMethods).GroupBy(y => y).Select(y => new KeyValuePair<string, int>(y.Key, y.Count())),
		UsedProperties = x.SelectMany(y => y.UsedProperties).GroupBy(y => y).Select(y => new KeyValuePair<string, int>(y.Key, y.Count())),
		UsedEvents = x.SelectMany(y => y.UsedEvents).GroupBy(y => y).Select(y => new KeyValuePair<string, int>(y.Key, y.Count()))
	});

This query will show how many times the methods, properties and events for each type in the 'foo' assembly is used. With this, you can decide how you may refactor to get a dependency picture which suits you better. It may also be worth drilling into the name of the type depended on - is this a type you wish to even depend on, or should you be depending on an interface?

The same query can also be used in the reverse way to understand how your platform code is being used. Suppose you have a platform project where you want to know which parts of it are heavily consumed and which may not even be used, you can perform the query across all dependent solutions and with the aggregate results you can compare against your API to see where the hotspots are. If there are parts of your API that nobody uses, they should obviously be cut, and less used parts can be candidates for obsolescence.

Latest Tweets