# Metrix++ Project

# Overview

## Highlights

Metrix++ is a tool to collect and analyse code metrics. Any metric is useless if it is not used. Metrix++ offers ease of introduction and integration with a variety of application use cases.

- Monitoring trends (eg. on daily basis. In order to take actions or make right decisions earlier.)
- Enforcing trends (eg. on hourly basis, at every commit of code changes.)
- Automated asistance to review agains standards (eg. on per minute basis during code refactoring and code development.)

The workflow sections below demonstarate these basic application usecases.

## Languages supported

The tool can parse C/C++, C# and Java source code files. The parser identifies certain regions in the code, such as classes, functions, namespaces, interfaces, etc. It detects comments, strings and code for the preprocessor. The identified regions form a tree of nested source code blocks, which are subsequently refered to and scanned by metrics plugins. Thus the tool attributes metrics to regions, which provides fine grained data to analysis tools. The following example demonstrates the regions concept.

Source code | Regions tree [type: name: content type]
--- | ---

    // simple C++ code

    #include <myapi.h>

    // I explain the following class
    class MyClass {
    public:
        int m_var; // some member

        // I explain the following function
        MyClass(): m_var(0) {
            char str[] = "unused string"

            // nested region for good measure
            struct MyStruct {};
        }

        // Do not judge ugly code below
    #define get_max(a,b) ((a)>(b)?(a):(b))
        set_max(int b) {
            m_var = get_max(m_var, b);
        }
    };
    // this is the last line

    file: __global__: comment
    file: __global__: code
    file: __global__: preprocessor
    file: __global__: code
        class: MyClass: comment
        class: MyClass: code
        class: MyClass: code
        class: MyClass: code, comment
        class: MyClass: code
            function: MyClass: comment
            function: MyClass: code
            function: MyClass: code, string
            function: MyClass: code
                struct: MyStruct: comment
                struct: MyStruct: code
            function: MyClass: code
        class: MyClass: code
            function: set_max: comment
            function: set_max: preprocessor
            function: set_max: code
            function: set_max: code
            function: set_max: code
        class: MyClass: code
    file: __global__: comment

## Metrics

The metrics highlighed in blue are per file metrics. The other metrics are per region metrics.

Metric (enable option) | Brief description | Motivation / Potential use
--- | --- | ---

std.general.size

Size of a file in bytes.

- Monitoring the growth of source code base.
- Normalizing other metrics.
- Preventing large files and regions (large things are difficult to maintain).
- Predicting delivery dates by comparing S-shaped code base growth / change curves.

std.code.length.total | The same as 'std.general.size' metric, but attributed to code regions. |
std.code.lines.total | Number of non-blank lines of code of any content type (exectuable, comments, etc.) |
std.code.lines.code | Number of non-blank lines of code excluding preprocessor and comments. |

std.code.lines.preprocessor

Number of non-blank lines of preprocessor code.

- Enforcing localisation of preprocessor code in a single place.
- Encouraging usage of safer code structures instead of the preprocessor.

std.code.lines.comments

Number of non-blank lines of comments.

- Low number of comments may indicate maintainability problems.

std.code.complexity.cyclomatic

McCabe cyclomatic complexity metric.

- Identification of highly complex code for review and refactoring.
- Preventing complex functions (complexity is a reason of many defects and a reason of expensive maintaintenance).

std.code.complexity.maxindent

Maximum level of indentation of blocks within a region. For example, the following class has got the metric equal to 1 and the function has got it equal to 2:

    class WeekClass {
        int isWeekend(int day) {
            if (day == SATURDAY ||
                day == SUNDAY) {
                return true;
            }
            return false;
        }
    }

std.code.magic.numbers | Number of magic numbers. There is an option to exclude 0, -1 and 1 numbers from counting. | Magic numbers are dangerous. The discussion on stackoverflow explains why.
std.code.todo.comments, std.code.todo.strings | Number of TODO/FIXME/etc markers in comments and strings accordingly. There is an option to configure a list of markers. | Manage potentially incomplete work. If project manager dispatches issues only in a tracker tool, todo markers are lost in the source code. The metric could make these 'lost' issues visible.
std.code.mi.simple | Simple variant of maintainability index - a measure of maintainability. It uses std.code.lines:code and std.code.complexity:cyclomatic metrics to evaluate level of maintainability. Lower value of this index indicates better level maintainability | Identify code, which may benefit the most from refactoring.

std.suppress

An option enables collection of Metrix++ suppressions and 2 metrics: 'std.suppress:count' and 'std.suppress.file:count'. The first is number of suppressions per region. The second is the same but applies for file-scope metrics.

- Suppressing false-positives.
- Managing the amount of suppressions. There should be no false-positives to suppress with the right metric, but there could be exceptions in specific cases. Managing suppressions is about managing exceptions. If there are many exceptional cases, maybe something is wrong with a metric or the application of a metric.

std.general.procerrors

Number of errors detected by Metrix++ code parser.

- Cleaning up errors to ensure reliable code scanning.
- Errors, like mismatched brackets, may result in bad identification of regions.

std.general.proctime

Seconds spent on processing a file.

- Monitor and profile Metrix++ tool's performance.

# Download & Install

In order to get the tool working, dowload the archive with the latest stable version and unpack it to some folder. The first run of the tool will trigger the installation within the folder, where it was launched.

In order to checkout the latest released version from the version control system use this command:

    svn checkout svn://svn.code.sf.net/p/metrixplusplus/code/releases/latest Metrix++

In order to checkout the latest version under development, use this command:

    svn checkout svn://svn.code.sf.net/p/metrixplusplus/code/mainline Metrix++

#### Change and Release Notes

Change and release notes are available here.

#### Prerequisites

Python Runtime Environment (version 2.7.* or later. Version 3.* has not been tested)

#### License

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with the Metrix++; if not, contact Project Administrator

# Getting started

The tool is relatively simple to use. There are 3 fundamental steps:

- Collect the data, for example:

    > python "/path/to/metrix++.py" collect --std.code.lines.code --std.code.complexity.cyclomatic

- View the data, for example:

    > python "/path/to/metrix++.py" view

- Apply thresholds, for example:

    > python "/path/to/metrix++.py" limit --max-limit=std.code.complexity:cyclomatic:7

Please, check the advanced description of the workflow with real examples.

# Extending the tool

Want to enable a new metric or a language, need advanced post-analysis tool? Please, check the plugin development tutorial.

# Feeback and contribute

Now it is your turn. There are multiple ways how you can contribute and help to improve and progress Metrix++ project:

- Try Metrix++ and post review
- Submit new feature request or bug report
- Ask a question
- Share your patch files and ideas, colloborate by email to project administrator
- Create and publish your plugin. Request to refer to it from Metrix++ project space.
- Submit your plugin to include to the standard set
- ... and consider to join the project!