Jason Pugh
Devspace Conference 2016
”When you can measure what you are speaking about, and can express it in numbers, you know something about it; but when you cannot measure it, when you cannot express it in numbers, your knowledge is of a meager and unsatisfactory kind: It may be the beginning of knowledge, but you have scarcely in your thoughts advanced to the stage of science.” -Lord Kelvin
Introduction
Code Scanned
Definition
Why Software Design Metrics
The Bad
The Good
Process Integration
Products
Conclusion
Chidamber, S.R.; Kemerer, C.F.; , "A metrics suite for object oriented design," Software Engineering, IEEE Transactions on , vol.20, no.6, pp.476-493, Jun 1994
L. H. Etzkorn et al., “A comparison of cohesion metrics for object-oriented systems,” Information and Software Technology, vol. 46, no. 10, pp. 677-687, Aug. 2004.
wmc = 0
for ctor in c.Constructors:
if(calculateComplexity == True):
wmc += ctor.DecisionsCount + 1
else:
wmc += 1
for m in c.Methods:
if(calculateComplexity == True):
wmc += m.DecisionsCount + 1
else:
wmc += 1/// <summary>
/// Checks whether a given collection name is valid in this database.
/// </summary>
/// <param name="collectionName">The collection name.</param>
/// <param name="message">An error message if the collection name is not valid.</param>
/// <returns>True if the collection name is valid; otherwise, false.</returns>
public virtual bool IsCollectionNameValid(string collectionName, out string message)
{
if (collectionName == null)
{
throw new ArgumentNullException("collectionName");
}
if (collectionName == "")
{
message = "Collection name cannot be empty.";
return false;
}
if (collectionName.IndexOf('\0') != -1)
{
message = "Collection name cannot contain null characters.";
return false;
}
if (Encoding.UTF8.GetBytes(collectionName).Length > 121)
{
message = "Collection name cannot exceed 121 bytes (after encoding to UTF-8).";
return false;
}
message = null;
return true;
}/// <summary>
/// Checks whether a given collection name is valid in this database.
/// </summary>
/// <param name="collectionName">The collection name.</param>
/// <param name="message">An error message if the collection name is not valid.</param>
/// <returns>True if the collection name is valid; otherwise, false.</returns>
public virtual bool IsCollectionNameValid(string collectionName, out string message)
{
if (collectionName == null)
{
throw new ArgumentNullException("collectionName");
}
if (collectionName == "")
{
message = "Collection name cannot be empty.";
return false;
}
if (collectionName.IndexOf('\0') != -1)
{
message = "Collection name cannot contain null characters.";
return false;
}
if (Encoding.UTF8.GetBytes(collectionName).Length > 121)
{
message = "Collection name cannot exceed 121 bytes (after encoding to UTF-8).";
return false;
}
message = null;
return true;
}1
2
3
4
5
Total WMC = 5
J. Bansiya and C. Davis, “A hierarchical model for object-oriented design quality assessment,” Software Engineering, IEEE Transactions on, vol. 28, no. 1, pp. 4-17, 2002.
dcc = 0
types = []
for a in c.Fields:
if((a.Type.Name in types) == False and (a.Type.IsUserDefined == True)):
types.append(a.Type.Name)
for m in c.Methods:
for p in m.Parameters:
if((p.Type.Name in types) == False and (p.Type.IsUserDefined == True)):
types.append(p.Type.Name)
if((m.ReturnType.Name in types) == False and m.ReturnType.IsUserDefined == True):
types.append(m.ReturnType.Name)
dcc = len(types)/// <summary>
/// Runs an aggregate command with explain set and returns the explain result.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>The explain result.</returns>
public virtual CommandResult AggregateExplain(AggregateArgs args)
{
var messageEncoderSettings = GetMessageEncoderSettings();
var operation = new AggregateExplainOperation(_collectionNamespace,
args.Pipeline,
messageEncoderSettings)
{
AllowDiskUse = args.AllowDiskUse,
Collation = args.Collation,
MaxTime = args.MaxTime
};
var response = ExecuteReadOperation(operation);
return new CommandResult(response);
}/// <summary>
/// Runs an aggregate command with explain set and returns the explain result.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>The explain result.</returns>
public virtual CommandResult AggregateExplain(AggregateArgs args)
{
var messageEncoderSettings = GetMessageEncoderSettings();
var operation = new AggregateExplainOperation(_collectionNamespace,
args.Pipeline,
messageEncoderSettings)
{
AllowDiskUse = args.AllowDiskUse,
Collation = args.Collation,
MaxTime = args.MaxTime
};
var response = ExecuteReadOperation(operation);
return new CommandResult(response);
}Both are custom types, therefore, DCC is 2
instance variables used in a method
Chidamber, S.R.; Kemerer, C.F.; , "A metrics suite for object oriented design," Software Engineering, IEEE Transactions on , vol.20, no.6, pp.476-493, Jun 1994
L. H. Etzkorn et al., “A comparison of cohesion metrics for object-oriented systems,” Information and Software Technology, vol. 46, no. 10, pp. 677-687, Aug. 2004.
lcom = 0
I = [] # An empty list of sets
i = 0 # A counter
p = 0 # The cardinality of set P
q = 0 # The cardinality of set Q
N = 0 # The number of methods in class C
N = c.Methods.Count
for m in c.Methods:
methodSet = set() # empty set, initially
# Determine which of the accessed variables
# are instance variables of the current class.
for v in m.AccessedVariables:
tempSet = set()
tempSet.add(v)
if(c.IsInstanceVariable(v) == True):
methodSet = methodSet | tempSet
# Keep the sets of accessed instance variables around. We will
# need them for the next step of the calculation.
I.append(methodSet)
for i in range(0, N):
for j in range(0, N):
intersection = I[i] & I[j]
if(len(intersection) == 0): # i.e. is the empty set
p += 1
else:
q += 1
#
# Now p is the number of pairs of methods which don't have
# have any instance variable accesses in common.
#
# q is the number of pairs of methods which DO have an instance
# variable access in common
#
if(p > q):
lcom = p - q
else:
lcom = 0private readonly CollectionNamespace _collectionNamespace;
/// <summary>
/// Runs an aggregate command with explain set and returns the explain result.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>The explain result.</returns>
public virtual CommandResult AggregateExplain(AggregateArgs args)
{
var messageEncoderSettings = GetMessageEncoderSettings();
var operation = new AggregateExplainOperation(_collectionNamespace,
args.Pipeline,
messageEncoderSettings)
{
AllowDiskUse = args.AllowDiskUse,
Collation = args.Collation,
MaxTime = args.MaxTime
};
var response = ExecuteReadOperation(operation);
return new CommandResult(response);
}private readonly CollectionNamespace _collectionNamespace;
/// <summary>
/// Runs an aggregate command with explain set and returns the explain result.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>The explain result.</returns>
public virtual CommandResult AggregateExplain(AggregateArgs args)
{
var messageEncoderSettings = GetMessageEncoderSettings();
var operation = new AggregateExplainOperation(_collectionNamespace,
args.Pipeline,
messageEncoderSettings)
{
AllowDiskUse = args.AllowDiskUse,
Collation = args.Collation,
MaxTime = args.MaxTime
};
var response = ExecuteReadOperation(operation);
return new CommandResult(response);
}Instance Variable _collectionNamespace
- therefore p > q : LCOM is 1
Tom DeMarco
What Language are you using?
What are important aspects of the language?
Complexity: 0 - 49 is Good, 50-99 is Potential Issues, and >= 100 is Concerning
Cohesion: 0 - 499 is Good, 500-899 is Potential Issues, and >= 900 is Concerning
Coupling: 0 - 11 is Good, 12-39 is Potential Issues, and >= 40 is Concerning
Why design metrics are considered bad:
Incorrect usage of metrics
Using just one metric for a decision.
Using too many metrics for a decision.
Using a single threshold for separate projects and not adapting.
Sandy, Joe and Susan run in a race. Sandy comes in first, Joe second, and Susan third.
We assign Sandy the number 1 for first place and give her $10,000
We assign Joe the number 2 and give him $1,000
We assign Susan the number 3 and give her $100
We assigned the numbers according to a rule.
Questions
Is Sandy twice as fast as Joe and three times as fast as Susan?
Is Sandy 10 times as fast as Joe and 100 times as fast as Susan?
Isn’t the assignment of the numbers based on their speed?
Did we measure their speed or not?
Kaner, C. “Yes, But What Are We Measuring?,” 1999 PNSQC
Douglas Hoffman
Architect:
Scan Code and Documentation Monthly*
Retrieve Metrics and Review
Project Manager:
Review Architect Findings
Assign to Team Lead
Team:
Schedule Peer Reviews
Schedule Refactor Task (IF NECESSARY)
Understand
Cantata++
McCabe IQ
Coverity
Currently revamping CSMS (Custom Software Metric Suite)
SaaS and Atlassian Support – December Timeframe
Actively looking for Closed Beta Users