Metrics of Source Code
Source code metrics are used to assess and monitor the quality of code in software projects. Metrics related to object-oriented programming (OOP) and Functions Programming (FP) are accessible. However, little study has been done with source code metrics for a combination of OOP and FP. Conventional OOP and FP metrics are also not always appropriate. The use of changeable variable classes (OOP) within lambda function syntax (FP), for example, is an amalgamation that does not occur in a single paradigm on its own. Traditional OOP and FP measurements are thus inappropriate for indicating quality for these merged constructs.
Source code metrics quantify code qualities and can be used to identify code that is possibly unreliable or difficult to maintain. Metrics may be used to discover bad code throughout the development process before it enters production. Furthermore, analytics can point out why code is faulty. If we know that particular constructions nearly invariably cause problems, we may create and add patterns to tools to avoid their use.
There are several source code metrics available for Object-Oriented Programming (OOP) technologies such as Java and C#. Metrics for Functional Programming (FP) languages such as Haskell have also been defined. However, little study has been conducted on source code metrics in a combination of OOP and FP.
The majority of the metrics integrate readily computed aspects of the code itself, such as the amount of operands and operators and the source code's complexity. The amount of operators and operands, the level of complexity of the control process chart, the number of attributes and worldwide variables in routines are all examples of such parameters and global variables.
Metrics and heuristics may help us answer these questions, and additional tools can assist us be informed if our code surpasses specific agreed-upon threshold for any metrics we consider significant.
Type of Source Code Metrics
This section discusses two source code metrics: Halstead's effort equation and McCabe's cyclomatic complexity measure.
Halstead’s Effort Equation
Halstead devised a variety of measures that are calculated from easily acquired characteristics of the code's source. The total amount of operations in a program N1; the total amount of the operands in the program N2; the amount of distinctive operators in the program n; and overall number of distinct operands is n2. The FORTRAN procedure and the numbers are N1, N2, n, and n2.
Using these numbers, Halstead defines a number of quantities. The program length N, for example, is specified as N1+N2; (N1+N2=50). N=n log2 n1 + n2 log2 n2 is Halstead's estimate of program length.
Example.
N=10(3.2)+7(2.8)=52.9
V=(N1+N2) log2(n+n2) is the definition of program volume.
L=(2*n2)/(n1*N2) is the definition of language level (level of abstraction).
V/L
E = (n1*N2*(N1+N2)*log2(ni+n2))/(2*n2)
McCabe’s Cyclomatic Metric
McCabe discovered that the challenge of comprehending a program is primarily dictated by the level of detail of its control flow graph. A connoted graph's cyclomatic number V The number G on the graph represents the number of independent linear paths. V(G) may be calculated as follows: V(G)= E-n +2p
Where E is the total number of edges, N denotes the number of nodes, and P denotes the number of linked components.
Other tools and procedures for maintenance
Because maintaining software is a miniature of software development, a software maintainer's actions may span the whole range of software engineering.
- Assistance tools and support for management tools are examples of automated software maintenance tools.
- A text editor allows for the quick and easy alteration of source programs, test data, and supporting papers. Text editors are useful for inserting and replacing source code segments, private feedback, test data, as well as backing documentation.
- Debugging tools offer tricks, dumps, traces, assertion checks, and history files to assist in determining the source of known faults.
- The connection editor connects compiled code objet models to create an executable application.
- The comparator compares two data files and displays the differences.
- The use of metrics for complexity necessitates the use of automated methods for determining the measures of relevance.
- They may be used to monitor the history of every module of a system by keeping track of the different modules and what versions and which modules compose particular system releases.
Metrics for Basic Source Code
Many metrics for assessing software source code have been developed throughout the years. They range from the most basic, such as program length or the lines of code, to the most complicated, such as cyclomatic complexity. Microsoft's Visual Studio has tools for measuring these and other metrics. Different metrics inside an application make meaning at various points of abstraction:
Maintainability Index
Microsoft's maintainability index which goes from 0 to 100, where higher numbers indicating greater maintainability. This index can be beneficial, particularly at the method level as opposed to the class/namespace/project level. It combines various metrics into a single index. Visual Studio has color coding, and this is where this approach, in my opinion, goes off the rails. According to the color coding, anything from 20 and 100 is considered "good maintainability," whereas 10 to 19 is considered "moderately maintainable," and 0 to 9 is considered "low maintainability." Believe me when I say that a number of 20 for this ranking do not indicate "good maintainability." If the index has to be colored, I would suggest something like 76-100=Good/Green, 25-75=Moderate/Yellow, and 0-24=Low/Red.
Cyclomatic Complexity
This metric has been used for decades and can be evaluated for many different languages. It counts the number of distinct logical pathways that may be taken within a code structure. It is most useful at the approach level, because it is hard to tell if a greater number implies a class having a single extremely complex method or multiple tiny, relatively basic ones at higher levels. Aim for a cyclomatic complexity value not more than ten at the method level. Values among the numbers 10 and 20 are not uncommon, while values above 20 suggest very complicated methods that might be on your refactoring radar.
Generated code frequently has a significant cyclomatic complexity and should be ignored when assessing and monitoring your own source code quality. Techniques like NDepend enable it to be simple to separate the analysis of your own source code from that of included or produced code (Visual Studio's ability to support these metrics is limited to the project level).
Depth of Inheriting and Class Connectivity
At the class stage, lesser values are often preferable. A class with a substantial amount of inheritance has a more complicated object structure and the greater number of unique types it refers, the less secure it is, and because any changes made to any of the referred types may destroy the class is question.
Lines of Code
This is an approximation based upon the IL code. This statistic is usually used at the technique level, but it may also be used to compare the total size of two courses, projects, or apps. Lower numbers are preferred when applied to procedures, just as they are when applied to cyclomatic complexity. Any technique that you can't see in its fullon view on your monitor (without using a tiny sized font or regions) is most likely too lengthy.
Additional Metrics
There are various third-party programs available for extra metrics. My choice is for NDepend, which is the most mature.NET/C# package available. To be clear, as a Microsoft MVP, I was given a complimentary license to NDepend (as well as Visual Studio). NDepend really supports more metrics than I can present here - see the full list. In additional to the ones listed above, here are a few others that I find particularly useful.
Number of Methods
Classes having numerous methods may be attempting to accomplish too much, or they may be more hard to maintain in any case. A suitable threshold for research is twenty.
Field Count
As in methods, adding too many fields might signal a problem with maintenance. A suitable threshold for research is twenty.
Afferent Coupling
It is the inbound connection of types from outside the assembly.
Efferent Coupling
Outbound coupling is determined by the amount of kinds outside an assembly which are used by assembly child types.
Relational Cohesion
Relational Cohesion is defined as an average quantity of internal connections per type. Types in an assemblage should be closely related to one another but not too connected. For this parameter, NDepend suggests a range from 1.5 to 4.0.
Instability and Abstractness
These measurements are applicable to assemblies and may be used to calculate the assembly's distance from the main sequence, where the values of instabilities and abstractness total 1. Assembly that is too far away from the primary flow may be worthless (if too abstract) or uncomfortable to deal with (if too concrete and relied on).
Type Rank
Like Google Page Rank, NDepend'stype rank algorithm determines which types are most important to a given application. High type rank kinds should be the most established and well-designed, because faults in these types have a greater impact upon the application.
Method Rank
Method rank, like Type rank (and Google Site Rank), may be used to find the procedures that are most important to an application.
Number of Parameters
The total amount of parameters associated with a method. Methods having an excessive number of arguments are harder to invoke and are frequently more complicated.
Variables Declared
It specifies the total amount of variables that are specified within a method. Larger numbers typically equate to more difficult-to-maintain approaches.
Both NDepend and Visual Studio have code test coverage tools for identifying portions of coding that are/are not addressed by automation test cases. In my experience, they are only somewhat useful because the coverage of code is rarely significant in its raw% form. What's more useful is viewing a comparison of test coverage to defect frequency or code complexity. More tests should be placed around your most difficult code, as well as portions of the code where errors continue to be discovered. It can also be beneficial to evaluate if the code% coverage is keeping constant or improving, which is especially important in older systems that were created without tests.NDepend has various built-in queries to assist you get a greater understanding of your source code coverage statistics, in addition to the simple % number.
Metrics Visualization
NDepend has a source code metrics perspective that displays a tree map of the studied code (in its GUI or within Visual Studio, as seen below). The default view organizes methods so that the size of every box represents the amount of lines of code (LOC) and the hue of the gradient represents the method's cyclomatic complexity. The Source Code Metrics Views for Dapper, a prominent micro-ORM project, is seen in this snapshot (click to enlarge):
Red boxes in this image represent methods having an average complexity of no less than 30. The method with the most lines of code is represented by the biggest box in its upper left corner. If you're searching for opportunities to simplify your code, this point of view may assist you readily locate "hot spots" in a codebase. Later in this series, we'll go over how to use various tools to evaluate code.
Metrics of Trend
When you evaluate how metrics are trending, they become more important. This category would include the fundamental code coverage % score. It's not really fascinating what your source code coverage % is, but if it's stable or improving, that's a good sign. If it's falling since the team has stopped testing entirely, that's usually a terrible indicator.
Although Visual Studio does not explicitly offer trend metrics, you could easily independently track measures of interest on an Excel file if you so wished. NDepend does provide this assistance, either directly through its tools or by reports that may be incorporated into an on-going integration server.
In NDepend, most of the indicators described above may be monitored as trend metrics. Some of the most interesting ones to follow assist indicate where issues are starting so that they may be dealt with before they get into hand.
Methods of Minimum Lines of Code
You can change this to have a minimum, but stuff like automatic attributes will turn it off. The built-in criteria average methods having at least three distinct lines of code. You don't want this to keep increasing indefinitely.
Average Code Lines for Types
The same as before, except for kinds. You wish to keep it stable or diminish it.
Typical Cyclomatic Complexity for Procedures
Once again, you'll want to add a minimum amount of lines of code to that one so that it isn't biased by properties and so on. Keep it as low as feasible. Keep an eye out for large spikes or steady ascents.
Average C.R.A.P Score
The average C.R.A.P. score stands for Change Risks Analyzer and Predictor. I haven't used it a lot, but NDepend includes integrated assistance for calculating it.
Aggregate Complexity
This is a statistic I created to aggregate cyclic complexity to the category or project level. It's comparable to, but better than, the median CC of Methods metric stated above, because the ideal value (zero) is more obvious.
Conclusion
In conclusion, if you've never looked into objectively reviewing a codebase, you might be shocked at how many distinct metrics are available that can be used. Actually, the sheer quantity of them might be overpowering at times. In the next post, I'll go over some particular criteria that are based on these parameters and may be used to detect trouble areas in code. Depending on their severity, these rules can be configured similarly to compiler faults and warnings.