Skip to end of metadata
Go to start of metadata
  • Measures of Software Quality


  • Correctness
    • Defects/KLOC
    • Defect is a verified lack of conformance to requirements
    • Failures/hours of operation
  • Maintainability
    • Mean time to change
    • Change request to new version (Analyze, design etc)
    • Cost to correct
  • Integrity
    • Fault tolerance, security & threats
  • Usability
    • Training time, skill level necessary to use, Increase in productivity, subjective questionnaire or controlled experiment



Size Oriented Metrics

MetricApplies toCalculated byInputCalculation
FileLines = "Source File Lines"

Source File (snapshot)

Project (snapshot)



source file


lines count

sum of all source files for that snapshot

LoC = "Lines of Code"



Source File (snapshot)

Project (snapshot)









bpos and epos for each statement

sum of all operations belonging to this module

sum of all modules belonging to this source file

sum of all source files for that snapshot

LoComm = "Lines of Comments"
Source File (snapshot)

Project (snapshot)





 counting of "comment" nodes

sum of all source files for that snapshot

NrStmts = "Number of Statements"


Source File (snapshot)

Project (snapshot)









counting of "comment" nodes

sum of all operations belonging to this module

sum of all modules belonging to this source file

sum of all source files for that snapshot

NrRoutines = "Number of Declared Routines"


Source File (snapshot)

Project (snapshot)




previous trivial select count
NrClickEvents = "Number of Click Events"
DoC = Density of Comments



Source File (snapshot)

Project (snapshot)

Not Used Yet



Density of Comments (DoC) provides the ratio of comment lines (LoComm) to
all lines (LOC).

Hence, DoC= LoComm/ LoC.

The density of comments value will be between 0.0 and 1.0 and it can be used as a quality indicator to see how much of the code is commented.

RefactorIT recommends a commenting of at least 20% of the code and a maximum of 40%. Thus, the lower limit for density of comments is 0.2 and the upper recommended value is 0.4


MetricApplies toCalculated byInputCalculation
NrModules = "Number of Modules"

Source File (snapshot)

Project (snapshot)



 trivial select count
NrConnections = "Number of Connections"

for each dependency type


Source File (snapshot)

Project (snapshot)





# of dependencies from and to this module

sum of all modules belonging to this source file

sum of all source files for that snapshot

NrDBCommands = "Number of Database Commands"


Source File (snapshot)

Project (snapshot)




 same as above where "dependency type"="db_command"




MetricApplies toCalculated byInputCalculation
NrUnusedModules = "Number of Unused Modules"
Project (snapshot)Thesaurus Modules with no in dependencies to this module. Must exclude modules that are UI entry points
NrUnresolvedSymbols = "Number of Unresolved Symbols"

(System APIs)

Source File (snapshot)

Project (snapshot)



 trivial select count
NrDeadRoutines = "Number of Dead Routines"

Source File (snapshot)

Project (snapshot)




Operations with no "call" dependencies to it. Must exclude events that are UI entry points

sum of all source files for that snapshot


Function Oriented Metrics


  • Indirect measure
  • Derived using empirical relationships based on countable (direct) measures of the software system (domain and requirements)





Computing Functions Points

  • Number of user inputs

 – Distinct input from user

  • Number of user outputs 

– Reports, screens, error messages, etc

  • Number of user inquiries 

– On line input that generates some result

  • Number of files 

– Logical file (database)

  • Number of external interfaces

– Data files/connections as interface to other systems


FP = Total Count * [0.65 + .01*Sum(Fi)]

Total count is all the counts times a weighting factor that is determined for each organization via empirical data
F i (i=1 to 14) are complexity adjustment values


UI Oriented Metrics

To be detailed

Complexity Metrics


Depth of call tree

Depth of a call chaining.


Applies toCalculated byInputCalculation
OperationsThesaurusSDG# of call edges starting from this operation
ModuleThesauruspreviousMax( DCallTree ) of all module operations
Source File (snapshot)ThesauruspreviousMax( DCallTree ) of all modules belonging to this source file
Project (snapshot)ThesauruspreviousMax( DCallTree ) of all source files belonging to this project snapshot


Halstead’s Metrics

Halstead’s Software Science (entropy measures)

  • n1 - number of distinct operators
  • n2 - number of distinct operands
  • N1 - total number of operators
  • N2 - total number of operands


if (k < 2)
	if (k > 3) 
		x = x*k; 


Distinct operators: if ( ) { } > < = * ;

Distinct operands: k 2 3 x

n1 = 10

n2 = 4

N1 = 13

N2 = 7


Halstead’s Metrics

Length: N = N1 + N2

Vocabulary: n = n1 + n2

Estimated length: N'= n1 log2 n1 + n2 log2 n2

– Close estimate of length for well structured programs

Purity ratio: PR = N'/N


Program Complexity

Volume: V = N log2 n

– Number of bits to provide a unique designator for each of the n items in the program vocabulary.

Program effort: E=V/L

L = V*/V

V* is the volume of most compact design implementation

This is a good measure of program understandability


 McCabe’s Cyclomatic Complexity (CC)

Cyclomatic complexity (CC) is a calculation of function/method complexity.  It gives one indication of function readability.



OO Languages


Simple, low complexity



Moderate risk



High risk

Too complex

> 50

Not testable

Too complex


Set of independent paths through the graph (basis set)

CC(G) = E – N + 2

E is the number of flow graph edges

N is the number of nodes

CC(G) = P + 1

P is the number of predicate nodes



  • CC(G) is the number of (enclosed) regions/areas of the planar graph
  • Number of regions increases with the number of decision paths and loops.
  • A quantitative measure of testing difficulty and an indication of ultimate reliability
  • Experimental data shows value of CC(G) should be no more then 10.
  • Testing is very difficulty above this value.


Cyclomatic complexity is a count of the number of basic decision in a function by assigning 1 point to each of the following:

  • The function
  • Each if, while, switch, case, and for statement
  • Each || or && within a conditional.

For example the following function has a CC of 4.

void foo(int iLimit)
	int iFooVar1;

	for (iFooVar1 = 0; (iFooVar1 < iLimit) && (iFoovar1< 1000); iFooVar++)
		if (iSomeGlobal > 42)



Applies toCalculated byInputCalculation
OperationCAREAST or CFGSearch Predicate Nodes in the AST or counting nodes and edges of the CFG

different strategies: average of operations or max

For example: 60%*Max(CC) + 40%*Average(CC) giving a weight to the most complex operation bigger than the average

Source FileCAREpreviousdifferent strategies: average of modules or max

Cyclomatic Complexity Density

Cyclomatic Complexity Density = Cyclomatic Complexity / Lines of Code

This complexity density ratio is demonstrated to be a useful predictor of software maintenance productivity on a small pilot sample of maintenance projects


McClure’s Complexity Metric

Complexity = C + V

C is the number of comparisons in a module

V is the number of control variables referenced in the module

Similar to McCabe’s but with regard to control variables.


SEI's Maintainability Index2

The metric originally was calculated as follows:


Maintainability Index = 171 - 5.2 * ln(Halstead Volume) - 0.23 * (Cyclomatic Complexity) - 16.2 * ln(Lines of Code)


This meant that it ranged from 171 to an unbounded negative number.  We noticed that as code tended toward 0 it was clearly hard to maintain code and the difference between code at 0 and some negative value was not useful.   I'll post some tech ed sample code showing very low maintainability or you can try on your own code to verify.  As a result of the decreasing usefulness of the negative numbers and a desire to keep the metric as clear as possible we decided to treat all 0 or less indexes as 0 and then re-base the 171 or less range to be from 0 to 100. Thus, the formula we use is:


Maintainability Index = MAX(0,(171 - 5.2 * ln(Halstead Volume) - 0.23 * (Cyclomatic Complexity) - 16.2 * ln(Lines of Code))*100 / 171)


On top of that we decided to be conservative with the thresholds.  The desire was that if the index showed red then we would be saying with a high degree of confidence that there was an issue with the code.  This gave us the following thresholds (as mentioned in this blog previously):

For the thresholds we decided to break down this 0-100 range 80-20 so that we kept the noise level low and only flagged code that was really suspicious. We have:

  • 0-9 = Red
  • 10-19 = Yellow
  • 20-100 = Green

Applies toCalculated byInputCalculation

Other Metrics

Halstead, CC, LOC

The calibration of this formula must take in consideration the language (e.g. adjusting the coefficients)
ModuleThesauruspreviousApply the formula to Module level or Max of operations
Source FileThesauruspreviousMax of modules

High level Design Metrics

  • Structural Complexity
  • Data Complexity
  • System Complexity




Fan in and Fan out metrics


  • Fan out " fout(i)" is the number of modules immediately subordinate (directly invoked) - SFanOut

  • Fan in "fin (i)" is the number of modules that invoke i - SFanIn


MetricsApplies toCalculated byInputCalculation
SFanIn = fin(i) = "Structural Fan-In Complexity"
Coupling between modules (callers)



Source FIle (snapshot)

Package (snapshot)

Thesaurus SDG

In dependencies of type "call and new"

Sum of Operations

Sum of Modules

Sum of Source Files

SFanOut = fout(i) = "Structural Fan-Out Complexity"

Coupling between modules (calls)



Source FIle (snapshot)

Package (snapshot)

Thesaurus SDG

Out dependencies of type "call and new"

Sum of Operations

Sum of Modules

Sum of Source Files

SFanInFanOut = "Structural Fan-In Fan-Out Complexity"
Coupling between modules (calls and callers)



Source FIle (snapshot)

Package (snapshot)

SFanIn + SFanOut
IFanIn = "Informational Fan-In Complexity"
Input data



Source FIle (snapshot)

Package (snapshot)

Thesaurus Select count from ThParameter where mode="input" + dependencies in of category="io"
IFanOut = "Informational Fan-Out Complexity"
Output data



Source FIle (snapshot)

Package (snapshot)

Thesaurus Select count from ThParameter where mode="output" + dependencies out of category="io"
IFanInFanOut = "Informational Fan-In Fan-Out Complexity"



Source FIle (snapshot)

Package (snapshot)

IFanIn + IFanOut
StructC = "Structural Complexity"



Source FIle (snapshot)

Package (snapshot)


SFanOut **2

DataC = "Data Complexity"


Source FIle (snapshot)

Package (snapshot)

 Thesaurus previous
DataC = IFanInFanOut / (SFanOut + 1)
SystemC = "System Complexity"


Source FIle (snapshot)

Package (snapshot)

Thesaurus previous

 SystemC = StructC + DataC

Alternative calculations:

SystemC = LOC * SFanInFanOut**2

SystemC = Nodes(SDG) + Edges(SDG)

SystemC = Nodes(SDG) / Edges(SDG)

Afferent Couplings (Ca)

PFanIn (Afferent couplings) is the number of modules in other packages that depends on this package.
It is the same as FanIn Metrics

Structural Complexity (Design Metrics)

Structural Complexity S(i) of a module i.

StructC = S(i) = f



Data Complexity (Design Metrics)

This metric gives the ratio between the data consumption and the used code (called code).

Data Complexity D(i) of a module i.

DataC = D(i) = v(i)/[fout(i)+1]

v(i) is the number of inputs and outputs passed to and from i.

System Complexity (Design Metrics)

System Complexity C(i) of a module i.


SystemC = C(i) = S(i) + D(i)

As each increases the overall complexity of the architecture increases.

Another metric:

C(i) = length(i) * [fin(i) + fout(i)]2

Length is LOC


Graph based metrics:

Nodes + edges

Modules + lines of control

Depth of tree, arc to node ratio

Component Level Metrics

  • Cohesion (internal interaction)
  • Coupling (external interaction)
  • Complexity of program flow


– difficult to measure

– Data slice – from a program slice



Data and control flow

– di input data parameters

– ci input control parameters

– do output data parameters

– co output control parameters


– gd global variables for data

– gc global variables for control


– w fan in number of modules called

– r fan out number modules that call module


Metrics for Coupling

Mc = k/m, k=1

  • m = di + aci + do + bco + gd + cgc + w + r
  • a, b, c, k can be adjusted based on actual data


Package Instability (by Robert Cecil Martin)

Robert C. Martin's proposed that the number of incoming and outgoing dependencies is one indicator determining the stability and instability of a package.

PI = PFanOut / (PFanIn + PFanOut)


PFanIn (Afferent couplings) is the number of modules in other packages that depends on this package

PFanOut (Efferent couplings) is the number of modules in this package that depends on modules in other packages

Owning page access restriction: cannot display diagram

PI = 2 / (3+2) = 0.4

PI ranges between 0 to 1, where 0 means maximally stable and 1 maximally unstable.

This metrics calculates the positional stability of the package and helps to improve the maintainability and quality of the software.

Stable dependency principle (SDP)

The dependencies between packages in a design should be in the direction of the most unstable to the most stable, in other words, a package should only depend on more stable packages.

The following diagram shows a stable design with three packages.

Owning page access restriction: cannot display diagram

Cyclic Dependencies

The cyclic dependencies metric is an additional quality metric to assess the quality of your code. This metric will give you an estimation of how many package cycles in which a package is involved. You should try to avoid having cycles to comport with the Acyclic Dependencies Principle (ADP) defined by Robert C. Martin stating that no cycles should be allowed in the package dependency graph. A CYC value of 0 indicates that the package being measured is not engaged in any cyclic dependencies with other packages.

Packages involved in many cycles are more difficult to maintain. If you make a change in one cyclic involved package, it might have an effect on another package that you were not modifying in the first place because it is involved in a cycle with the package you were modifying. So packages with cycles in the dependency structure should be refactored because neither package can be used independent of the other.


Metrics for the Object Oriented


  • Metrics specifically designed to address object oriented software
  • Class oriented metrics


Weighted Methods per Class (WMC)

WMC = SUMi( Ci )

  • Ci is the complexity (e.g., volume, cyclomatic complexity, etc.) of each method
  • Must normalize
  • What about inherited methods?  – Be consistent
  • A class with a low WMC usually points to greater polymorphism.
  • A class with a high WMC indicates that the class is complex (application specific) and therefore harder to reuse and maintain

1Lower Limit  A class should consist of at least one function
50Upper LimitDifferent limits have been defined.
One way is to limit the number of methods in a class to, say, 20 or 50.
Another way is to specify that a maximum of 10% of classes can have more than 24 methods.
This allows large classes but most classes should be small.
Applies toCalculated byInputCalculation
Module (Class)Thesaurusother metricse.g. sum(CC)

Depth of Inheritance Tree (DIT)

  • DIT is the maximum length from a node to the root (base class)
  • Lower level subclasses inherit a number of methods making behavior harder to predict
  • However, more methods are reused in higher DIT trees.


Applies toCalculated byInputCalculation
Module (Class)ThesaurusSDG (Inheritance sub-graph)size of path from this to the root

Number of Children (NOC)

  • NOC is the number of subclasses immediately subordinate to a class
  • As NOC grows, reuse increases
  • But the abstraction may be diluted


Applies toCalculated byInputCalculation
Module (Class)ThesaurusSDG (Inheritance sub-graph)nr of nodes of the forward sub-graph starting from this

Coupling between Classes (CBO)

  • CBO is the number of collaborations between two classes
  • Excessive coupling between object classes is detrimental to modular design and prevents reuse
  • The larger the number of couples, the higher the sensitivity to changes in other parts of the design, and therefore maintenance is more difficult
  • CRC – lists the number of collaborations –Classes, Responsibilities, and Collaborations

Dependencies between the classes (e.g. calling, using, ...)

>14CBO>14 is too high, say Sahraoui, Godin & Miceli in their article
Applies toCalculated byInputCalculation
Module (Class)Thesaurus at request in the Analytics PortalSDG and the user selection (the two classes)nr of dependencies between the two chosen classes

Response for a Class (RFC)

  • The Response for Class (RFC) metric is the total number of methods that can potentially be executed in response to a message received by an object of a class;
  •  This number is the sum of the methods of the class, and all distinct methods are invoked directly within the class methods. Additionally, inherited methods are counted, but overridden methods are not, because only one method of a particular signature will always be available to an object of a given class.
  • Testing effort increases as RFC increases
< 50Good - RefactorIT recommends a default threshold from 0 to 50 for a class
50 < 100Acceptable
> 100Iit means that there is a high complexity


For example, if a method call on a class can result in a large number of different method calls on the target and other classes. It can be hard to test the behaviour of the class and to debug problems since comprehending class behaviour requires a deep understanding of the potential interactions that objects of the class can have with the rest of the system.


Applies toCalculated byInputCalculation
Module (Class)Thesaurus select count from ThOperation where visibility!="private" 

Lack of Cohesion in Methods

LCOM1 by Chidamber & Kemerer

  • Class Ck with n methods M1,…Mn
  • Ij is the set of instance variables used by Mj
  • There are n such sets I1 ,…, In
  • P = {(Ii, Ij) | (Ii ∩ Ij ) = ∅}
  • Q = {(Ii, Ij) | (Ii ∩ Ij ) ≠∅ }
  • If all n sets Ii are ∅ then P = ∅


  • LCOM = | P| - |Q|, if |P| > |Q|
  • LCOM = 0 otherwise


Example LCOM1:

Take class C with M1, M2, M3

  • I1 = {a, b, c, d, e}
  • I2 = {a, b, e}
  • I3 = {x, y, z}
  • P = {(I1, I3), (I2, I3)}
  • Q = {(I1, I2)}

Thus LCOM1 = 1



  • LCOM is the number of empty intersections minus the number of nonempty intersections
  • This is a notion of degree of similarity of methods.
  • If two methods use common instance variables then they are similar
  • Low cohesion increases complexity, thereby increasing the likelihood of errors during the development process
  • LCOM of zero is not maximally cohesive 
  • |P| = |Q| or |P| < |Q| 
Applies toCalculated byInputCalculation
Module (Class)CAREASTusing nr of instances of Variable declarations of User Defined Classes (excluding base types)

LCOM2 by Henderson-Sellers, Constantine & Graham

To overcome the problems of LCOM1, two additional metrics have been proposed: LCOM2 and LCOM3.

A low value of LCOM2 or LCOM3 indicates high cohesion and a well-designed class. It is likely that the system has good class subdivision implying simplicity and high reusability. A cohesive class will tend to provide a high degree of encapsulation. A higher value of LCOM2 or LCOM3 indicates decreased encapsulation and increased complexity, thereby increasing the likelihood of errors.

Which one to choose, LCOM2 or LCOM3? This is a matter of taste. LCOM2 and LCOM3 are similar measures with different formulae. LCOM3 varies in the range [0,1] while LCOM2 is in the range [0,2]. LCOM2>=1 indicates a very problematic class. LCOM3 has no single threshold value.

It is a good idea to remove any dead variables before interpreting the values of LCOM2 or LCOM3. Dead variables can lead to high values of LCOM2 and LCOM3, thus leading to wrong interpretations of what should be done.

LCOM2 formula

mnumber of procedures (methods) in class
anumber of variables (attributes) in class
mAnumber of methods that access a variable (attribute)
sum(ma)sum of mA over attributes of a class

LCOM2 = 1 - sum(mA)/(m*a)

Implementation details. m is equal to WMC. a contains all variables whether Shared or not. All accesses to a variable are counted.

LCOM2 equals the percentage of methods that do not access a specific attribute averaged over all attributes in the class. If the number of methods or attributes is zero, LCOM2 is undefined and displayed as zero.

More information here


LCOM3 by Henderson-Sellers, Constantine & Graham

Variables are the same as for LCOM2

LCOM3 = (m - sum(mA)/a) / (m-1)

LCOM3 varies between 0 and 2. Values 1..2 are considered alarming.

In a normal class whose methods access the class's own variables, LCOM3 varies between 0 (high cohesion) and 1 (no cohesion). When LCOM3=0, each method accesses all variables.

More information here


Class Size (CS)

  • Total number of operations (inherited, private, public)
  • Number of attributes (inherited, private, public)

May be an indication of too much responsibility for a class


Applies toCalculated byInputCalculation
Module (Class)Thesaurus select count from ThOperation + select count from ThField

Number of Operations Overridden (NOO)

  • A large number for NOO indicates possible problems with the design
  • Poor abstraction in inheritance hierarchy


Applies toCalculated byInputCalculation
Module (Class)ThesaurusSDG (Operation Overriden sub-graph)nr of nodes of the forward sub-graph starting from this

Number of Operations Added (NOA)

  • The number of operations added by a subclass
  • As operations are added it is farther away from super class
  • As depth increases NOA should decrease


Applies toCalculated byInputCalculation
Module (Class)Thesaurusdbrequires the pre-calculation of the signatures of methods

Specialization Index 

SI = [NOO * L] / Mtotal

  • L is the level in class hierarchy
  • Mtotal is the total number of methods
  • Higher values indicate class in hierarchy that does not conform to the abstraction


Applies toCalculated byInputCalculation
Module (Class)Thesaurusdbrequires the calculation of the inheritance graph

Method Inheritance Factor (MIF)

MIF = SUMi ( Mi( Ci ) ) / SUMi( Ma( Ci ) )

  • Mi(Ci) is the number of methods inherited and not overridden in Ci
  • Ma(Ci) is the number of methods that can be invoked with Ci
  • Md(Ci) is the number of methods declared in Ci 
  • Ma(Ci) = Md(Ci) + Mi(Ci)
  • All that can be invoked = new or overloaded + things inherited
  • MIF is [0,1]
  • MIF near 1 means little specialization
  • MIF near 0 means large change


Applies toCalculated byInputCalculation
ProjectThesaurusSDG, dbrequires the calculation of the inheritance and overriden graph

Coupling Factor

CF = SUMi ( SUMj (is_client( Ci, Cj) ) ) / (TC**2 - TC)

  • is_client(x,y) = 1 iff a relationship exists between the client class and the server class.  0 otherwise.
  • (TC**2-TC) is the total number of relationships possible (Total Classes **2 – diagonal)
  • CF is [0,1] with 1 meaning high coupling


Applies toCalculated byInputCalculation
ProjectThesaurusSDG, db 

Polymorphism Factor

PF = .SUMi( Mo(Ci) ) / SUMi [ Mn(Ci) * DC(Ci) ]

  • Mn() is the number of new methods
  • Mo() is the number of overriding methods
  • DC() number of descendent classes of a base class
  • The number of methods that redefines inherited methods, divided by maximum number of possible distinct polymorphic situations


Applies toCalculated byInputCalculation
ProjectThesaurusSDG, db, previous metrics (e.g. NOO) 

Operational Oriented Metrics

  • Average operation size (LOC, volume)
  • Number of messages sent by an operator
  • Operation complexity – cyclomatic
  • Average number of parameters/operation – Larger the number the more complex the collaboration


  • Lack of cohesion
  • Percent public and protected
  • Public access to data members


  • Number of root classes
  • Fan in – multiple inheritance
  • NOC, DIT, etc

Metrics to Analyze

Stability Metric

The Active Set of Classes

Analytic Ratios

Test density

The test density is the ratio between the cyclomatic complexity of the application and the number of function points


Decision points/#FP

Decision points=Total of CC

FP=Function Points

0 - 60 A low test density indicates that the test effort could be mastered

60 - 100 Medium test density

> 100 Red zon

Complexity erosion

This is the rate of complex and very complex components with respect to all components of an application. For applications in new technology, this rate should be kept below 5%.

complexity rate = ratio of complex and very complex artifacts relative to the total number of artifacts

> 5% A high value of complexity erosion indicates an application that has been complicating with time...

Violation density

 #Critical rules violation/#FP

 Development quality

#Critical rules violation/KLOC

0 - 5  The quality level is under the common average 

> 5 Quality is compromised 

Transaction Risk Index (TRI)

TRI is the set of weights of all violations of components per transaction (that is to say by user "access point" ).

TRI = SUM(rules violation * weight) for any component used by that transaction

Propagated Risk Index (PRI)

The PRI is the risk spread across the application. It helps prioritize violations by the most central components, and to classify the following violations:

  • The importance and the criterion of violation
  •   The position of the violation in the architecture of the application (call graph

Over the PRI, the higher the risk of spread of a material breach is great
Calculation: PRI = VI * FLR

  • VI (Violation Index), represents the importance of the breach
  • RPF (Risk Propagation Factor), is the risk of propagation to other components


Function Point (FP)

Measures the size of software by quantifying the amount of features for users.


execution path through programs linking an application entry point represented by a user interface (display, batch launch control ...) and an output point represented by a data storage (database, file ... )

See Execution flow.

Technical debt

Represents the effort required (or if supported) to correct all programming errors.

Technical Debt is a metaphor referring to the possible consequences of poor software development. Debt can be seen as the effort to get a proper quality code.



Page Contents