What are they and why do they matter
 Attila Bertók
C# technical lead
 Contact:
 bertok.atti@gmail.com
 https://www.linkedin.com/in/bertokattila/
 After a certain size, code becomes worse
 Sheer size
 Complexity
 Lack of ownership
 everyone’s code is no one’s code
 broken windows theory
 Duplication
 Conditional logic and logical exceptions
 Legacy code (the no dev’s land)
 code that other developers wrote
 code that you wrote, but more than two weeks ago
 Decreased performance
 Developers need more time to understand the code
 Developers need more time to implement changes to the code
 Developers’ confidence is decreased
 Increased bug count
 New bugs get introduced
 Old bugs surface and re-surface
 And how do I measure this “worse-ness”?
The things that my machine can do for me
 Static (as opposed to dynamic): Done without actually
executing the program
 Quantifiable measurements
 General code health
 Early warning system
 Visual Studio (Roslyn)
 Extensions:
 CodeIt.Right
 CodeRush
 FxCop
 StyleCop
 Static Analysis tool:
 SonarQube
 NDepend
 Critical & Non-Critical rules
 Critical rule violation breaks build
 Non-Critical rule violation adds a warning
 Non-Critical violations are still useful for monitoring and
code health, and prioritizing refactorings, and clean-up
efforts.
 Code readability
 Code comprehension
 Code maintainability
“Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.”
[Martin Fowler]
 Spacing, bracing, indenting, etc.
 Aim: give the code uniform look, so intent is obvious at the
first glance
 Common example: braces for single line statements
 Enforce braces:
if (areBracesEnforced)
{
return bracedCode;
}
 Omit braces:
if (areBracesOmitted)
return bracelessCode;
 The developers get used to the style and do their “internal
pattern-matching” based on their expectations
 Inconsistent style leads to errors
 Code should always convey intent
 and do so as clearly as possible
 Patterns in code should always be obvious
 and easy to recognize
 on any level
 be it codestyle
 or architectural design
private static Bitmap ConvolutionFilter(
Bitmap sourceBitmap,
double[,] filterMatrix) {
var lockedRectangle =
new Rectangle(
0,
0,
sourceBitmap.Width,
sourceBitmap.Height);
BitmapData sourceData =
sourceBitmap.LockBits(lockedRectangle);
// […]
if (sourceBitmap.IsGreyScale) {
for (int k = 0; k < buffer.Length; k += 4) {
rgb = buffer[k] * 0.11f;
buffer[k] = (byte)rgb;
}
}
}
private static Bitmap ConvolutionFilter(
Bitmap sourceBitmap,
double[,] filterMatrix)
{
var lockedRectangle =
new Rectangle(
0,
0,
sourceBitmap.Width,
sourceBitmap.Height);
BitmapData sourceData =
sourceBitmap.LockBits(lockedRectangle);
// […]
if (sourceBitmap.IsGreyScale)
{
for (int k = 0; k < buffer.Length; k += 4)
{
rgb = buffer[k] * 0.11f;
buffer[k] = (byte)rgb;
}
}
}
xxxxxxx xxxxxx xxxxxx xxxxxxxxxxxxxxxxx(
xxxxxx xxxxxxxxxxxx,
xxxxxx[,] xxxxxxxxxxxx) {
xxx xxxxxxxxxxxxxxx =
xxx xxxxxxxxx(
x,
x,
xxxxxxxxxxxx.xxxxx,
xxxxxxxxxxxx.xxxxxx);
xxxxxxxxxx xxxxxxxxxx =
xxxxxxxxxxxx.xxxxxxxx(xxxxxxxxxxxxxxx);
// […]
xx (xxxxxxxxxxxx.xxxxxxxxxxx) {
xxx (xxx x = x; x < xxxxxx.xxxxxx; x += x) {
xxx = xxxxxx[x] * x.xxx;
xxxxxx[x] = (xxxx)xxx;
}
}
}
xxxxxxx xxxxxx xxxxxx xxxxxxxxxxxxxxxxx(
xxxxxx xxxxxxxxxxxx,
xxxxxx[,] xxxxxxxxxxxx)
{
xxx xxxxxxxxxxxxxxx =
xxx xxxxxxxxx(
x,
x,
xxxxxxxxxxxx.xxxxx,
xxxxxxxxxxxx.xxxxxx);
xxxxxxxxxx xxxxxxxxxx =
xxxxxxxxxxxx.xxxxxxxx(xxxxxxxxxxxxxxx);
// […]
xx (xxxxxxxxxxxx.xxxxxxxxxxx)
{
xxx (xxx x = x; x < xxxxxx.xxxxxx; x += x)
{
xxx = xxxxxx[x] * x.xxx;
xxxxxx[x] = (xxxx)xxx;
}
}
}
 Lay down some foundations
 Common expectations
 Rules that the environment and the tools enforce
 Rules that code reviews should enforce
 Rules for:
 Documentation
 File layout
 Maintainability
 Naming
 Ordering
 Readability
 Spacing
That are not merely stylistic in approach…
 The title says it all. 
 Recommendation:
 The best method is a method that has no arguments (niladic)
 One argument (monadic) or two (dyadic) is acceptable
 Three arguments (triadic) should be avoided whenever possible
 More than that (polyadic) require a rather good justification
 Move things to instance variables!
 Separate functions (initialization, ctor, etc.)
 Rearrange classes (are many of your methods accepting the
same class as argument? It is possible that those methods
belong to that class!)
 Avoid out parameters
 Avoid flag arguments
 The title says it all – again.
 Recommendation: keep it low. Anything above 8 is a serious
overkill, anything above 5 is potentially too many.
 Guess what.
 No overload is 1.
 Recommendation: keep it low. Many overloads can be
difficult to keep in mind. However, there are no hard rules for
this.
CC = 1 + …
the number of any of the following expressions found in the
method body:
 if/case/default/?:/??/.?
 while/for/foreach/continue
 goto
 &&/||
 catch
 Recommendations: The smaller the better. Static analysis
tools recommend a max of 15 per method.
 I’ve heard of companies where anything over 8 automatically breaks
the build.
 In case of .net it is generally lines of IL code (Logical LOC)
 Code style (and language) does not influence it
 Interfaces, abstract methods, enumerations have a LOC of 0.
 Namespaces, namespace references, and declarations have a
LOC of 0.
 LOC of classes is the sum of the LOC of their methods.
 Recommendation: keep as low as possible
 Simple as it sounds, the number of the lines containing
comment
 Inline comments and full-line comments are worth the same
 Recommendation: keep it as low as possible
 (100 * LOComments) / (LOComments + LOC)
 The amount of required comment strongly depends on the
quality of code
 Code should be self-explanatory and should not require comments
 Recommendation: keep as low as possible
 Percentage of code covered by (unit/acceptance) tests.
 Recommendation: The closer to 100% the better.
 If using test first, anything below 100% is pretty bad.
… and methods, in some cases.
Classes should have a small number of instance variables. Each
of the methods of a class should manipulate one or more of
those variables.
In general the more variables a method manipulates the more
cohesive that method is to its class.
A class in which each variable is used by each method is
maximally cohesive.
The strategy of keeping functions small and keeping parameter
lists short can sometimes lead to a proliferation of instance
variables that are used by a subset of methods.
When this happens, it almost always means that there is at
least one other class trying to get out of the larger class. You
should try to separate the variables and methods into two or
more classes such that the new classes are more cohesive.
M is the number of methods in class (both static and instance
methods are counted, it includes also constructors, properties
getters/setters, events add/remove methods).
F is the number of instance fields in the class.
MF is the number of methods of the class accessing a particular
instance field.
Sum(MF) is the sum of MF over all instance fields of the class.
LCOM = 1 – (sum(MF)/M*F)
LCOM HS = (M – sum(MF)/F)(M-1)
DI: Incoming dependencies: the number of classes that depend on
this class
DO: Outgoing dependencies: the number of classes that this class
depends on.
Instability: DO / (DI + DO) (0..1)
I = 0: no other components depend on this component.
I = 1: this component depends on no other components.
NC: the number of classes in the assembly
NA: the number of abstract classes in the assembly
A: Abstractness:
A = NA / NC
 Zone of Uselessness:
Abstract components that
are never inherited
 Zone of Pain: very stable,
thus difficult to change,
meanwhile very concrete,
thus difficult to extend
D = |A + I - 1 |
Recommendation: Classes should be as close to the main
sequence as possible.
 Methods
 Fields
 Recommendation: keep classes small.
For a class/namespace/assembly/etc.:
Sum of CC from methods/classes/assemblies.
 The title (almost) says it all. 
 For derived classes, it also includes the interfaces
implemented by the base class.
 Recommendation: keep low. ;)
 The title (almost) says it all (again). 
 (Including System.Object, so always starts from 1.)
 Recommendation: keep low. ;)
 Types
 Namespaces
 Assemblies
Average number of internal relationships per type.
Let R be the number of type relationships that are internal to
this assembly (i.e. that do not connect to types outside the
assembly).
Let N be the number of types within the assembly.
H = (R + 1)/ N.
Recommendation: Keep it high.
The things that my machine cannot do for me
 SOLID principles
 Consistent style
 Succinct but readable code
 Good naming
 The Boy Scout Rule and Opportunistic refactoring
Code metrics in Visual Studio:
https://msdn.microsoft.com/en-us/library/bb385914.aspx
A Short Primer on Code Quality Metrics:
https://ardalis.com/static-code-analysis-and-quality-metrics
NDepend Code Metrics:
https://www.ndepend.com/docs/code-metrics
NDepend
SonarQube
FxCop
StyleCop
Code Metrics

Code Metrics

  • 1.
    What are theyand why do they matter
  • 2.
     Attila Bertók C#technical lead  Contact:  bertok.atti@gmail.com  https://www.linkedin.com/in/bertokattila/
  • 3.
     After acertain size, code becomes worse  Sheer size  Complexity  Lack of ownership  everyone’s code is no one’s code  broken windows theory  Duplication  Conditional logic and logical exceptions  Legacy code (the no dev’s land)  code that other developers wrote  code that you wrote, but more than two weeks ago
  • 4.
     Decreased performance Developers need more time to understand the code  Developers need more time to implement changes to the code  Developers’ confidence is decreased  Increased bug count  New bugs get introduced  Old bugs surface and re-surface
  • 5.
     And howdo I measure this “worse-ness”?
  • 6.
    The things thatmy machine can do for me
  • 7.
     Static (asopposed to dynamic): Done without actually executing the program  Quantifiable measurements  General code health  Early warning system
  • 8.
     Visual Studio(Roslyn)  Extensions:  CodeIt.Right  CodeRush  FxCop  StyleCop  Static Analysis tool:  SonarQube  NDepend
  • 9.
     Critical &Non-Critical rules  Critical rule violation breaks build  Non-Critical rule violation adds a warning  Non-Critical violations are still useful for monitoring and code health, and prioritizing refactorings, and clean-up efforts.
  • 10.
     Code readability Code comprehension  Code maintainability
  • 11.
    “Any fool canwrite code that a computer can understand. Good programmers write code that humans can understand.” [Martin Fowler]
  • 12.
     Spacing, bracing,indenting, etc.  Aim: give the code uniform look, so intent is obvious at the first glance  Common example: braces for single line statements
  • 13.
     Enforce braces: if(areBracesEnforced) { return bracedCode; }  Omit braces: if (areBracesOmitted) return bracelessCode;
  • 14.
     The developersget used to the style and do their “internal pattern-matching” based on their expectations  Inconsistent style leads to errors
  • 15.
     Code shouldalways convey intent  and do so as clearly as possible  Patterns in code should always be obvious  and easy to recognize  on any level  be it codestyle  or architectural design
  • 16.
    private static BitmapConvolutionFilter( Bitmap sourceBitmap, double[,] filterMatrix) { var lockedRectangle = new Rectangle( 0, 0, sourceBitmap.Width, sourceBitmap.Height); BitmapData sourceData = sourceBitmap.LockBits(lockedRectangle); // […] if (sourceBitmap.IsGreyScale) { for (int k = 0; k < buffer.Length; k += 4) { rgb = buffer[k] * 0.11f; buffer[k] = (byte)rgb; } } } private static Bitmap ConvolutionFilter( Bitmap sourceBitmap, double[,] filterMatrix) { var lockedRectangle = new Rectangle( 0, 0, sourceBitmap.Width, sourceBitmap.Height); BitmapData sourceData = sourceBitmap.LockBits(lockedRectangle); // […] if (sourceBitmap.IsGreyScale) { for (int k = 0; k < buffer.Length; k += 4) { rgb = buffer[k] * 0.11f; buffer[k] = (byte)rgb; } } }
  • 17.
    xxxxxxx xxxxxx xxxxxxxxxxxxxxxxxxxxxxx( xxxxxx xxxxxxxxxxxx, xxxxxx[,] xxxxxxxxxxxx) { xxx xxxxxxxxxxxxxxx = xxx xxxxxxxxx( x, x, xxxxxxxxxxxx.xxxxx, xxxxxxxxxxxx.xxxxxx); xxxxxxxxxx xxxxxxxxxx = xxxxxxxxxxxx.xxxxxxxx(xxxxxxxxxxxxxxx); // […] xx (xxxxxxxxxxxx.xxxxxxxxxxx) { xxx (xxx x = x; x < xxxxxx.xxxxxx; x += x) { xxx = xxxxxx[x] * x.xxx; xxxxxx[x] = (xxxx)xxx; } } } xxxxxxx xxxxxx xxxxxx xxxxxxxxxxxxxxxxx( xxxxxx xxxxxxxxxxxx, xxxxxx[,] xxxxxxxxxxxx) { xxx xxxxxxxxxxxxxxx = xxx xxxxxxxxx( x, x, xxxxxxxxxxxx.xxxxx, xxxxxxxxxxxx.xxxxxx); xxxxxxxxxx xxxxxxxxxx = xxxxxxxxxxxx.xxxxxxxx(xxxxxxxxxxxxxxx); // […] xx (xxxxxxxxxxxx.xxxxxxxxxxx) { xxx (xxx x = x; x < xxxxxx.xxxxxx; x += x) { xxx = xxxxxx[x] * x.xxx; xxxxxx[x] = (xxxx)xxx; } } }
  • 18.
     Lay downsome foundations  Common expectations  Rules that the environment and the tools enforce  Rules that code reviews should enforce
  • 19.
     Rules for: Documentation  File layout  Maintainability  Naming  Ordering  Readability  Spacing
  • 20.
    That are notmerely stylistic in approach…
  • 22.
     The titlesays it all.   Recommendation:  The best method is a method that has no arguments (niladic)  One argument (monadic) or two (dyadic) is acceptable  Three arguments (triadic) should be avoided whenever possible  More than that (polyadic) require a rather good justification
  • 23.
     Move thingsto instance variables!  Separate functions (initialization, ctor, etc.)  Rearrange classes (are many of your methods accepting the same class as argument? It is possible that those methods belong to that class!)  Avoid out parameters  Avoid flag arguments
  • 24.
     The titlesays it all – again.  Recommendation: keep it low. Anything above 8 is a serious overkill, anything above 5 is potentially too many.
  • 25.
     Guess what. No overload is 1.  Recommendation: keep it low. Many overloads can be difficult to keep in mind. However, there are no hard rules for this.
  • 26.
    CC = 1+ … the number of any of the following expressions found in the method body:  if/case/default/?:/??/.?  while/for/foreach/continue  goto  &&/||  catch
  • 27.
     Recommendations: Thesmaller the better. Static analysis tools recommend a max of 15 per method.  I’ve heard of companies where anything over 8 automatically breaks the build.
  • 28.
     In caseof .net it is generally lines of IL code (Logical LOC)  Code style (and language) does not influence it  Interfaces, abstract methods, enumerations have a LOC of 0.  Namespaces, namespace references, and declarations have a LOC of 0.  LOC of classes is the sum of the LOC of their methods.  Recommendation: keep as low as possible
  • 29.
     Simple asit sounds, the number of the lines containing comment  Inline comments and full-line comments are worth the same  Recommendation: keep it as low as possible
  • 30.
     (100 *LOComments) / (LOComments + LOC)  The amount of required comment strongly depends on the quality of code  Code should be self-explanatory and should not require comments  Recommendation: keep as low as possible
  • 31.
     Percentage ofcode covered by (unit/acceptance) tests.  Recommendation: The closer to 100% the better.  If using test first, anything below 100% is pretty bad.
  • 32.
    … and methods,in some cases.
  • 33.
    Classes should havea small number of instance variables. Each of the methods of a class should manipulate one or more of those variables. In general the more variables a method manipulates the more cohesive that method is to its class. A class in which each variable is used by each method is maximally cohesive.
  • 34.
    The strategy ofkeeping functions small and keeping parameter lists short can sometimes lead to a proliferation of instance variables that are used by a subset of methods. When this happens, it almost always means that there is at least one other class trying to get out of the larger class. You should try to separate the variables and methods into two or more classes such that the new classes are more cohesive.
  • 35.
    M is thenumber of methods in class (both static and instance methods are counted, it includes also constructors, properties getters/setters, events add/remove methods). F is the number of instance fields in the class. MF is the number of methods of the class accessing a particular instance field. Sum(MF) is the sum of MF over all instance fields of the class. LCOM = 1 – (sum(MF)/M*F) LCOM HS = (M – sum(MF)/F)(M-1)
  • 36.
    DI: Incoming dependencies:the number of classes that depend on this class DO: Outgoing dependencies: the number of classes that this class depends on. Instability: DO / (DI + DO) (0..1) I = 0: no other components depend on this component. I = 1: this component depends on no other components.
  • 37.
    NC: the numberof classes in the assembly NA: the number of abstract classes in the assembly A: Abstractness: A = NA / NC
  • 38.
     Zone ofUselessness: Abstract components that are never inherited  Zone of Pain: very stable, thus difficult to change, meanwhile very concrete, thus difficult to extend
  • 39.
    D = |A+ I - 1 | Recommendation: Classes should be as close to the main sequence as possible.
  • 40.
     Methods  Fields Recommendation: keep classes small.
  • 41.
    For a class/namespace/assembly/etc.: Sumof CC from methods/classes/assemblies.
  • 42.
     The title(almost) says it all.   For derived classes, it also includes the interfaces implemented by the base class.  Recommendation: keep low. ;)
  • 43.
     The title(almost) says it all (again).   (Including System.Object, so always starts from 1.)  Recommendation: keep low. ;)
  • 45.
  • 46.
    Average number ofinternal relationships per type. Let R be the number of type relationships that are internal to this assembly (i.e. that do not connect to types outside the assembly). Let N be the number of types within the assembly. H = (R + 1)/ N. Recommendation: Keep it high.
  • 47.
    The things thatmy machine cannot do for me
  • 48.
     SOLID principles Consistent style  Succinct but readable code  Good naming
  • 49.
     The BoyScout Rule and Opportunistic refactoring
  • 50.
    Code metrics inVisual Studio: https://msdn.microsoft.com/en-us/library/bb385914.aspx A Short Primer on Code Quality Metrics: https://ardalis.com/static-code-analysis-and-quality-metrics NDepend Code Metrics: https://www.ndepend.com/docs/code-metrics
  • 51.