Skip to content

Repo sync for protected CLA branch #6286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions docs/code-quality/code-metrics-class-coupling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: Code metrics - Class coupling
ms.date: 1/8/2021
description: Learn about the class coupling metric for code metrics in Visual Studio.
ms.topic: conceptual
author: mikejo5000
ms.author: mikejo
manager: jillfra
ms.workload:
- multiple
---

# Code metrics - Class coupling

Class coupling also goes by the name Coupling Between Objects (CBO) as originally defined by [CK94](#ck94). Basically, class coupling is a measure of how many classes a single class uses. A high number is bad and a low number is usually good with this metric. Class coupling has been shown to be an accurate predictor of software failure and recent studies have shown that an upper-limit value of 9 is the most efficient [S2010](#s2010).

According to the Microsoft documentation, class coupling “measures the coupling to unique classes through parameters, local variables, return types, method calls, generic or template instantiations, base classes, interface implementations, fields defined on external types, and attribute decoration. Good software design dictates that types and methods should have high cohesion and low coupling. High coupling indicates a design that is difficult to reuse and maintain because of its many interdependencies on other types.”

The concepts of coupling and cohesion are clearly related. To keep this discussion on topic, we will not get into depth with cohesion other than to give a brief definition from [KKLS2000](#kkls2000):

“Module cohesion was introduced by Yourdon and Constantine as ‘how tightly bound or related the internal elements of a module are to one another’ [YC79](#yc79). A module has a strong cohesion if it represents exactly one task […], and all its elements contribute to this single task. They describe cohesion as an attribute of design, rather than code, and an attribute that can be used to predict reusability, maintainability, and changeability.”

## Class Coupling Example

Let’s look at class coupling in action. First, create a new console application and create a new class called Person with some properties in it then immediately calculate the code metrics:

![Class coupling example 1](media/class-coupling-example-1.png)

Notice the class coupling is 0 since this class doesn’t use any other classes. Now create another class called PersonStuff with a method that creates an instance of Person and sets the property values. Calculate the code metrics again:

![Class coupling example 2](media/class-coupling-example-2.png)

See how the class coupling value goes up? Also notice that, no matter how many properties you set, the class coupling value just goes up by 1 and not by some other value. Class coupling measures each class only once for this metric no matter how much it is used. In addition, can you see that `DoSomething()` has a 1 but the constructor, `PersonStuff()`, has a 0 for its value? Currently there is no code in the constructor that is using another class.

What if you put code in the constructor that used another class? Here is what you get:

![Class coupling example 3](media/class-coupling-example-3.png)

Now the constructor clearly has code that uses another class and the class coupling metric shows this fact. Again, you can see the overall class coupling for `PersonStuff()` is 1 and `DoSomething()` is also 1 to show that only one external class is being used no matter how much internal code you have that uses it.

Next, create another new class. Give this class some name and create some properties inside it:

![Class coupling example - add new class](media/class-coupling-example-add-new-class.png)

Now consume the class in our `DoSomething()` method within the `PersonStuff` class and calculate code metrics again:

![Class coupling example 4](media/class-coupling-example-4.png)

As you can see, the class coupling for the PersonStuff class goes up to 2 and, if you drill into the class, you can see that the `DoSomething()` method has the most coupling in it but the constructor still only consumes 1 class. Using these metrics, you can see the overall max number for a given class and drill down into the details on a per-member basis.

## The Magic Number

As with cyclomatic complexity, there is no limit that fits all organizations. However, [S2010](#s2010) does indicate that a limit of 9 is optimal:

“Therefore, we consider the threshold values […] as the most effective. These threshold values (for a single member) are CBO = 9[…].” (emphasis added)

## Code Analysis

Code analysis includes a category of Maintainability rules. For more information, see [Maintainability rules](/dotnet/fundamentals/code-analysis/quality-rules/maintainability-warnings). When using legacy code analysis, the Extended Design Guideline rule set contains a maintainability area:

![Class coupling Extended Design Guideline rules](media/class-coupling-extended-design-guideline-rules.png)

Inside the maintainability area is a rule for class coupling:

![Class coupling rule](media/class-coupling-maintainability-area-rules.png)

This rule issues a warning when the class coupling is excessive. For more information, see [CA1506: Avoid excessive class coupling](/dotnet/fundamentals/code-analysis/quality-rules/ca1506).

For a description of this rule, see the archived Code Analysis blog post: [Code Metrics as Check-in Policy](/archive/blogs/codeanalysis/code-metrics-as-check-in-policy) and the threshold description *Warning at above 80 for class and above 30 for a method*. These values seem abnormally high, but at least provide an extreme upper limit. If you hit this warning, then something is almost certainly wrong.

## Citations

### CK94

Chidamber, S. R. & Kemerer, C. F. (1994). A Metrics Suite for Object Oriented Design (IEEE Transactions on Software Engineering, Vol. 20, No. 6). Retrieved May 14, 2011, from the University of Pittsburgh web site: [http://www.pitt.edu/~ckemerer/CK%20research%20papers/MetricForOOD_ChidamberKemerer94.pdf](http://www.pitt.edu/~ckemerer/CK%20research%20papers/MetricForOOD_ChidamberKemerer94.pdf)

### KKLS2000

Kabaili, H., Keller, R., Lustman, F., and Saint-Denis, G. (2000). Class Cohesion Revisited: An Empirical Study on Industrial Systems (Proceedings of the Workshop on Quantitative Approaches in Object-Oriented Software Engineering). Retrieved May 20, 2011, from Université de Montréal web site [http://www.iro.umontreal.ca/~sahraouh/qaoose/papers/Kabaili.pdf](http://www.iro.umontreal.ca/~sahraouh/qaoose/papers/Kabaili.pdf)

### SK2003

Subramanyam, R. & Krishnan, M. S. (2003). Empirical Analysis of CK Metrics for Object-Oriented Design Complexity: Implications for Software Defects (IEEE Transactions on Software Engineering, Vol. 29, No. 4). Retrieved May 14, 2011, from University of Massachusetts Dartmouth web site [http://moosehead.cis.umassd.edu/cis580/readings/OO_Design_Complexity_Metrics.pdf](http://moosehead.cis.umassd.edu/cis580/readings/OO_Design_Complexity_Metrics.pdf)

### S2010

Shatnawi, R. (2010). A Quantitative Investigation of the Acceptable Risk Levels of Object-Oriented Metrics in Open-Source Systems (IEEE Transactions on Software Engineering, Vol. 36, No. 2).

### YC79

Edward Yourdon and Larry L. Constantine. Structured Design. Prentice Hall, Englewood Cliffs, N.J., 1979.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: Code metrics - Maintainability index range and meaning
ms.date: 1/8/2021
description: Learn about the maintainability index range metric for code metrics in Visual Studio.
ms.topic: conceptual
author: mikejo5000
ms.author: mikejo
manager: jillfra
ms.workload:
- multiple
---
# Code metrics - Maintainability index range and meaning

Question: The maintainability index has been reset to lie between 0 and 100. How and why was this done?

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)`

The use of this formula meant that it ranged from 171 to an unbounded negative number. 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. 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 rebase the 171 or less range to be from 0 to 100. For this reason, 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)`

In addition to 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:

For the thresholds, we decided to break down this 0-100 range 80-20 to keep the noise level low and we only flagged code that was suspicious. We've used the following thresholds:

- 0-9 = Red
- 10-19 = Yellow
- 20-100 = Green
4 changes: 2 additions & 2 deletions docs/code-quality/code-metrics-values.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ For information about how to generate code metrics data in Visual Studio, see [H

The following list shows the code metrics results that Visual Studio calculates:

- **Maintainability Index** - Calculates an index value between 0 and 100 that represents the relative ease of maintaining the code. A high value means better maintainability. Color coded ratings can be used to quickly identify trouble spots in your code. A green rating is between 20 and 100 and indicates that the code has good maintainability. A yellow rating is between 10 and 19 and indicates that the code is moderately maintainable. A red rating is a rating between 0 and 9 and indicates low maintainability. For more information, see the [Maintainability index range and meaning](/archive/blogs/codeanalysis/maintainability-index-range-and-meaning) blog post.
- **Maintainability Index** - Calculates an index value between 0 and 100 that represents the relative ease of maintaining the code. A high value means better maintainability. Color coded ratings can be used to quickly identify trouble spots in your code. A green rating is between 20 and 100 and indicates that the code has good maintainability. A yellow rating is between 10 and 19 and indicates that the code is moderately maintainable. A red rating is a rating between 0 and 9 and indicates low maintainability. For more information, see [Maintainability index range and meaning](code-metrics-maintainability-index-range-and-meaning.md).

- **Cyclomatic Complexity** - Measures the structural complexity of the code. It is created by calculating the number of different code paths in the flow of the program. A program that has complex control flow requires more tests to achieve good code coverage and is less maintainable. For more information, see the [Uncyclopedia entry for cyclomatic complexity](https://wikipedia.org/wiki/Cyclomatic_complexity).

- **Depth of Inheritance** - Indicates the number of different classes that inherit from one another, all the way back to the base class. Depth of Inheritance is similar to class coupling in that a change in a base class can affect any of its inherited classes. The higher this number, the deeper the inheritance and the higher the potential for base class modifications to result in a breaking change. For Depth of Inheritance, a low value is good and a high value is bad.

- **Class Coupling** - Measures the coupling to unique classes through parameters, local variables, return types, method calls, generic or template instantiations, base classes, interface implementations, fields defined on external types, and attribute decoration. Good software design dictates that types and methods should have high cohesion and low coupling. High coupling indicates a design that is difficult to reuse and maintain because of its many interdependencies on other types. For more information, see the [Class coupling](/archive/blogs/zainnab/code-metrics-class-coupling) blog post.
- **Class Coupling** - Measures the coupling to unique classes through parameters, local variables, return types, method calls, generic or template instantiations, base classes, interface implementations, fields defined on external types, and attribute decoration. Good software design dictates that types and methods should have high cohesion and low coupling. High coupling indicates a design that is difficult to reuse and maintain because of its many interdependencies on other types. For more information, see [Class coupling](code-metrics-class-coupling.md).

::: moniker range=">=vs-2019"

Expand Down
11 changes: 3 additions & 8 deletions docs/code-quality/how-to-generate-code-metrics-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,10 @@ The .NET code-quality analyzers include several code metrics [analyzer](roslyn-a
- [CA1505](/dotnet/fundamentals/code-analysis/quality-rules/ca1505)
- [CA1506](/dotnet/fundamentals/code-analysis/quality-rules/ca1506)

These rules are disabled by default but you can enable them from [**Solution Explorer**](use-roslyn-analyzers.md#set-rule-severity-from-solution-explorer) or in a [rule set](using-rule-sets-to-group-code-analysis-rules.md) file. For example, to enable rule CA1502 as a warning, your .ruleset file would contain the following entry:
These rules are disabled by default but you can enable them from [**Solution Explorer**](use-roslyn-analyzers.md#set-rule-severity-from-solution-explorer) or in an [EditorConfig](use-roslyn-analyzers.md#set-rule-severity-in-an-editorconfig-file) file. For example, to enable rule CA1502 as a warning, your EditorConfig file would contain the following entry:

```xml
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules" Description="Rules" ToolsVersion="16.0">
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
<Rule Id="CA1502" Action="Warning" />
</Rules>
</RuleSet>
```cs
dotnet_diagnostic.CA1502.severity = warning
```

### Configuration
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion docs/code-quality/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,17 @@
href: how-to-generate-code-metrics-data.md
- name: Work with code metrics data
href: working-with-code-metrics-data.md
- name: Resources
items:
- name: Maintainability index range and meaning
href: code-metrics-maintainability-index-range-and-meaning.md
- name: Class coupling
href: code-metrics-class-coupling.md
- name: C++ code analysis
items:
- name: Analyze C and C++ code
href: /cpp/code-quality/code-analysis-for-c-cpp-overview
- name: EditorConfig formatting conventions
href: ../ide/cpp-editorconfig-properties.md
- name: C++ code analysis warnings
href: /cpp/code-quality/code-analysis-for-c-cpp-warnings
href: /cpp/code-quality/code-analysis-for-c-cpp-warnings
12 changes: 11 additions & 1 deletion docs/deployment/installchecks-element-bootstrapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,20 @@ The `InstallChecks` element supports starting a variety of tests against the loc
For example, to block installation on a computer running Windows 95, use code such as the following:

```xml
<!-- Block install on Windows 95 -->
<!-- Block install on Windows 95 -->
<FailIf Property="Version9X" Compare="VersionLessThan" Value="4.10" String="InvalidPlatform"/>
```

To skip running install checks if a FailIf or BypassIf condition is met, use the BeforeInstallChecks attribute. For example:

```xml
<!-- Block install and do not evaluate install checks if user does not have admin privileges -->
<FailIf Property="AdminUser" Compare="ValueEqualTo" Value="false" String="AdminRequired" BeforeInstallChecks="true"/>
```

>[!NOTE]
>The `BeforeInstallChecks` attribute is supported starting with the Visual Studio 2019 Update 9 release.

## See also
- [\<Commands> element](../deployment/commands-element-bootstrapper.md)
- [Product and package schema reference](../deployment/product-and-package-schema-reference.md)