Measuring Cyclometric Complexity and Coupling
Thursday, September 7, 2006 – 8:15 PMI’ve been thinking about how one could measure technical dept to get a relative, rather than absolute, number reflecting the debt present in a codebase and how that changes over time. One of the things I considered measuring as something that might indicate or track debt was cyclometric complexity. I came across the a tool called CCMetrics while searching for tools. There are others but I figured I start with this one as in addition to measuring complexity it also measures coupling of classes and methods.
I ran this on a small tools project I worked on that we use internally and the results were pretty much what I expected:
Most complex methods:
(could be refactored for simplification)
1: XXX.Forms.EditTask.buttonOK_Click (57, troublesome )
2: XXX.Forms.EditTask.ValidateData (23, alarmingly complex )
3: XXX.Forms.EditTask.GetInterval (23, alarmingly complex )
4: XXX.Forms.EditTask.SetTaskFields (19, somewhat complex )
5: XXX.Pages.DoWork.WorkerThreadFunction (16, somewhat complex )
6: XXX.Forms.EditTask..ctor (15, somewhat complex )
7: XXX.Forms.EditTask.InitializeComponent (13, somewhat complex )
8: YYY.Loggers.EmailLogger.ParseParameters (13, somewhat complex )
9: XXX.Forms.EditTask.updateState (12, somewhat complex )
10: YYY.Core.Configuration.Load (12, somewhat complex )
11: YYY.Loggers.EmailLogger.eventSource_BuildFinished (12, somewhat complex )
12: YYY.Loggers.DditLogger.eventSource_CustomEventRaised (11, somewhat complex )
13: XXX.Forms.EditTask.SetupLoggerFields (10, somewhat complex )
14: YYY.Core.LoggerCollection.System.Xml.Serialization.IXmlSerializable.ReadXml (10, somewhat complex )
15: YYY.Core.ServiceEventLogger.WriteErrorEntry (9, manageable )
16: YYY.Loggers.EmailLogger.eventSource_CustomEventRaised (9, manageable )
17: YYY.Core.RecurringTask.OverdueBy (9, manageable )
18: YYY.Loggers.XmlLogger.set_Parameters (7, manageable )
19: YYY.Core.LoggerCollection.Remove (7, manageable )
20: YYY.Core.Task.ExecuteTask (7, manageable )
Most complex, but least called, methods:
(could be refactored for re-use)
1: XXX.Forms.EditTask.buttonOK_Click (53, troublesome )
2: XXX.Forms.EditTask.GetInterval (15, somewhat complex )
3: XXX.Forms.EditTask.ValidateData (15, somewhat complex )
4: XXX.Pages.DoWork.WorkerThreadFunction (12, somewhat complex )
5: YYY.Loggers.EmailLogger.eventSource_BuildFinished (11, somewhat complex )
6: XXX.Forms.EditTask..ctor (11, somewhat complex )
7: XXX.Forms.EditTask.SetTaskFields (11, somewhat complex )
8: YYY.Core.Configuration.Load (10, somewhat complex )
9: YYY.Loggers.DditLogger.eventSource_CustomEventRaised (10, somewhat complex )
10: YYY.Loggers.EmailLogger.ParseParameters (10, somewhat complex )
11: YYY.Core.LoggerCollection.System.Xml.Serialization.IXmlSerializable.ReadXml (8, manageable )
12: YYY.Loggers.EmailLogger.eventSource_CustomEventRaised (8, manageable )
13: YYY.Core.ServiceEventLogger.WriteErrorEntry (7, manageable )
14: YYY.Core.RecurringTask.OverdueBy (7, manageable )
15: YYY.Loggers.XmlLogger.set_Parameters (6, manageable )
16: YYY.Core.LoggerCollection.Remove (5, manageable )
17: YYY.Loggers.EmailLogger.get_Parameters (5, manageable )
18: XXX.Forms.EditTask.InitializeComponent (5, manageable )
19: YYY.Core.LoggerCollection.Contains (4, manageable )
20: YYY.Core.Task.Execute (4, manageable )
Average Class Complexity: 25.16
(rating: simple)
Complexity Re-Use: 73.81%
(rating: good amount of re-use)
Code Re-Use: 42.87%
(rating: some re-use, could be better)
Most Coupled Class: YYY.Core.Task (6)
(rating: some coupling, ok)
Class With Max CC: EditTask @ 187
(rating: somewhat complex)
Most of the complexity is in the YYY.Forms classes and the YYY.Loggers.EmailLogger. This isn’t surprising as the UI wasn’t written using TDD and the EmailLogger was code ported and heavily refactored but some of the original complexity remains. As it turns out the loggers were developed in isolation and there’s some common code that could be refactored. So none of this came as a big surprise. The tool and I agree at least to the first order as to where the areas of greatest technical debt are in this particular codebase.
CCMetrics is designed so that you can run it as part of a (nightly) build and track increases in coupling and complexity over time. Worth checking out if you ask me.
I was actually discussing this with Michael Puleio today and we came up with a bunch of other metrics that might be indicators of technical debt but more on these another time after I’ve formalized them a bit. Needless to say there are a lot to choose from!
Sorry, comments for this entry are closed at this time.