Git Product home page Git Product logo

churn-php's Introduction

churn-php

Helps discover good candidates for refactoring.

Build Status codecov Scrutinizer Code Quality Code Climate Packagist Packagist Packagist Donate

Table of Contents

What is it?

churn-php is a package that helps you identify php files in your project that could be good candidates for refactoring. It examines each PHP file in the path it is provided and:

  • Checks how many commits it has.
  • Calculates the cyclomatic complexity.
  • Creates a score based on these two values.

The results are displayed in a table:

A file that changes a lot and has a high complexity might be a better candidate for refactoring than a file that doesn't change a lot and has a low complexity.

churn-php only assists the developer to identify files for refactoring. It's best to use the results in addition to your own judgment to decide which files you may want to refactor.

Compatibility

  • PHP 7.1+
  • Composer 2.0+

How to Install?

Download the last release of churn.phar or install it with Phive:

phive install churn

You can also install churn-php via Composer:

composer require bmitch/churn-php --dev

How to Use?

churn run <one or more paths to source code> ...
churn run src
churn run src tests

# the command name can be skipped if directoriesToScan is set in churn.yml
churn

How to Configure?

You may add an optional churn.yml file which can be used to configure churn-php. The location of this file can be customized using the --configuration option:

# Default: "churn.yml" or "churn.yml.dist"
churn run --configuration=config-dir/ <path>
churn run --configuration=my-config.yml <path>

A sample churn.yml file looks like:

# The maximum number of files to display in the results table.
# Default: 10
filesToShow: 10

# The minimum score a file need to display in the results table.
# Disabled if null.
# Default: 0.1
minScoreToShow: 0

# The command returns an 1 exit code if the highest score is greater than the threshold.
# Disabled if null.
# Default: null
maxScoreThreshold: 0.9

# The number of parallel jobs to use when processing files.
# Default: 10
parallelJobs: 10

# How far back in the VCS history to count the number of commits to a file
# Can be a human readable date like 'One week ago' or a date like '2017-07-12'
# Default: '10 Years ago'
commitsSince: One year ago

# Files to ignore when processing. The full path to the file relative to the root of your project is required.
# Also supports regular expressions.
# Default: All PHP files in the path provided to churn-php are processed.
filesToIgnore:
 - src/Commands/ChurnCommand.php
 - src/Results/ResultsParser.php
 - src/Foo/Ba*

# File extensions to use when processing.
# Default: php
fileExtensions:
 - php
 - inc

# This list is used only if there is no argument when running churn.
# Default: <empty>
directoriesToScan:
 - src
 - tests/

# List of user-defined hooks.
# They can be referenced by their full qualified class name if churn has access to the autoloader.
# Otherwise the file path can be used as well.
# See below the section about hooks for more details.
# Default: <empty>
hooks:
 - Namespace\MyHook
 - path/to/my-hook.php

# The version control system used for your project.
# Accepted values: fossil, git, mercurial, subversion, none
# Default: git
vcs: git

# The path of the cache file. It doesn't need to exist before running churn.
# Disabled if null.
# Default: null
cachePath: .churn.cache

If a churn.yml file is omitted or an individual setting is omitted the default values above will be used.

Output formats

You can configure churn to output the result in different formats. The available formats are:

  • csv
  • json
  • markdown
  • text (default)

To use a different format use --format option. Example command for json:

churn run --format json

Hooks

The hooks configuration allows you to customize churn.

A user-defined hook must implement at least one Hook interface:

Hook interface Corresponding event interface
AfterAnalysisHook AfterAnalysis
AfterFileAnalysisHook AfterFileAnalysis
BeforeAnalysisHook BeforeAnalysis

Similar Packages

Contact

Questions, comments, feedback? @bmitch2112

Contributing

  • Please run composer test on PHP 7.1 and ensure it passes.
  • If you don't have access to PHP 7.1 please make sure that CI build passes when you make pull request. If you are unable to get it to pass in the pull request please ping me and I can help.
  • Please see CONTRIBUTING.md

License

The MIT License (MIT). Please see License File for more information.

churn-php's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

churn-php's Issues

Sniff to disallow set methods.

Using set methods in a class is not advised, because:

  • if the class is instantiated and we forget to call the set methods it may work or not and cause side effects. Plus we may need to call them in the correct order.
  • if you need to inject Collaborators they must be strictly injected via constructor and any other values needed by the class should be passed as arguments to the method being called, preferable using Immutable Value Objects(the only exception to not inject an object via constructor).
  • objects are passed by reference in Php, therefore when the object is passed around any call to the set method will affect all places where the object is being used. This can cause undesired bugs, that sometimes are hard to track.

I can continue with more cases why we should not use set methods, but I think the above 3 ones are strong enough to justify the sniff.

Thanks for your excellent work.

Add some sort of header above table

<HEADER GOES HERE>
+-----------------------------------------------------------+---------------+------------+-------+
| File                                                      | Times Changed | Complexity | Score |
+-----------------------------------------------------------+---------------+------------+-------+
...

Limit git history when counting changes.

This can be a value added to the yml config. For example, if you have a large git commit history you may only want to limit the changes within the last year:

        $process = new Process(
            'git -C ' . getcwd() . " log --since=\"1 year ago\" --name-only --pretty=format: " . $file->getFullPath(). " | sort | uniq -c | sort -nr"
        );

Missing tests

  • Result #27
  • ResultCollection #30
  • ResultsGenerator #34
  • FileManager #31
  • ChurnCommand (hmm not sure if it is possible right now, going to skip)

Validate data being used to create config class

Here:

    /**
     * Config constructor.
     * @param array $rawData Raw config data.
     */
    public function __construct(array $rawData = [])
    {
        $this->filesToShow = $rawData['filesToShow'] ?? 10;
        $this->parallelJobs = $rawData['parallelJobs'] ?? 10;
        $this->commitsSince = $rawData['commitsSince'] ?? '10 years ago';
        $this->filesToIgnore = $rawData['filesToIgnore'] ?? [];
    }

Support mercurial/svn/etc.

Though git is the most popular, mercurial is heavily used as well and it would be interesting to put this to use.

Enhance readme / documentation

I'm open to reviews of the readme if anyone has any suggestions.

  • Any information missing or instructions missing.
  • Better layout/design/look.
  • Anything else you'd like to see in the readme.

Changes for next version

  • #38 - Run in parallel Done
  • #40 - Config file (yml) Saving for later and can be backwards compatible new feautre.
  • #41 - Add some sort of header above table Done
  • #42 - Add footer with misc data under table? Saving for later and can be backwards compatible new feautre.

Config file (yml)

In order to get the git commits we'll need to know the root folder so that we can run the git command.

We could also store other values in here:

  • How many commits to go back (with a default value if not provided).
  • How many of the top files to show (with a default)?
  • Score modifier? (maybe save for later) #55
  • Number of parallel jobs to run
  • Threshold (only show results where score > x) (will save for later) #56
  • Path of files (save for later) #57
  • files to ignore (exact path and name now, regex later?) #58

Also need to make sure it works without a yml file present or some options not set.

Add sniff to check for use of: instanceof

A sniff to disallow the use of instanceof function would be good to have.

The use of it is a code smell and represents a flaw in the project Software Architecture.

I love this package that helps us to write more SOLID and Clean Code.

Suggestion to change the scoring

Thanks for a nice tool!

The way I understand it (and the way it's described in this article: https://www.sandimetz.com/blog/2017/9/13/breaking-up-the-behemoth), we should consider to refactor classes that are high on high on both complexity and times changed. Otherwise, we would start refactoring complex classes that change almost never (which is a waste of effort) or we would start refactoring simple classes that change often (which also makes no sense, since it's very easy to make the change, so it doesn't cost us much).

What do you think?

New screenshot

Still not entirely happy with the screenshot in the readme.md

  • It has a command prompt at the top and the bottom. Could remove both, neither are really needed.
  • It contains a really long file name (the CyclomaticComplexityAssessor.php) in the results which forces the table to be very wide. If that file was ignored the table would be smaller in width which I think would improve the screenshot.

Build failing - FileManager has too many indentation levels.

FILE: /home/bmitch/Code/ChurnPhp/src/Managers/FileManager.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 35 | ERROR | 3 indentation levels found. Maximum of 2 indentation levels
    |       | allowed. (Codor.Files.IndentationLevel)

Refactor churn command

  • Make process of getting all the *.php files from one object.
  • Make getting results of all the files from one object and should return an object.
  • Make display of results one object.

Bug in FileManager - regex to ignore files?

I think if you try to make a regex pattern like *.php to ignore files it won't give you the expected results.

I created this test:

        $fileManager = new FileManager(['php', 'inc'], ['Assets2/*.php']);
        $this->assertCount(1, $fileManager->getPhpFiles([__DIR__ . '/../Assets2']));

Which I would expect to pass but it fails.

Command to display results.

I am envisioning something like this:

vendor/bin/churn-php src

+--------------+---------------+---------------+---------------+
| File         | Times Changed | CycComplexity | Score         |
+--------------+---------------+---------------+---------------+
| src/Foo.php  | 10            | 5             | 50            |
| src/Bar.php  | 5             | 7             | 35            |
| src/Baz.php  | 2             | 1             | 2             |
+--------------+---------------+---------------+---------------+

Make results show files relative to provided path.

For example, when providing the path src right now it displays the files like:

+------------------------------------------------------------------------------------------------+---------------+------------+-------+
| File                                                                                           | Times Changed | Complexity | Score |
+------------------------------------------------------------------------------------------------+---------------+------------+-------+
| /home/bmitch/Code/ChurnPhp/src/Assessors/CyclomaticComplexity/CyclomaticComplexityAssessor.php | 4             | 4          | 8     |
| /home/bmitch/Code/ChurnPhp/src/Assessors/GitCommitCount/GitCommitCountAssessor.php             | 3             | 4          | 7     |
| /home/bmitch/Code/ChurnPhp/src/Commands/ChurnCommand.php                                       | 3             | 2          | 5     |
| /home/bmitch/Code/ChurnPhp/src/Managers/FileManager.php                                        | 1             | 3          | 4     |
| /home/bmitch/Code/ChurnPhp/src/Results/ResultsGenerator.php                                    | 1             | 2          | 3     |
| /home/bmitch/Code/ChurnPhp/src/Services/CommandService.php                                     | 2             | 1          | 3     |
| /home/bmitch/Code/ChurnPhp/src/Results/ResultCollection.php                                    | 1             | 1          | 2     |
| /home/bmitch/Code/ChurnPhp/src/Results/Result.php                                              | 1             | 1          | 2     |
+------------------------------------------------------------------------------------------------+---------------+------------+-------+

Would be nice if it was like this instead.

+-----------------------------------------------------------------+---------------+------------+-------+
| File                                                            | Times Changed | Complexity | Score |
+-----------------------------------------------------------------+---------------+------------+-------+
| Assessors/CyclomaticComplexity/CyclomaticComplexityAssessor.php | 4             | 4          | 8     |
| Assessors/GitCommitCount/GitCommitCountAssessor.php             | 3             | 4          | 7     |
| Commands/ChurnCommand.php                                       | 3             | 2          | 5     |
| Managers/FileManager.php                                        | 1             | 3          | 4     |
| Results/ResultsGenerator.php                                    | 1             | 2          | 3     |
| Services/CommandService.php                                     | 2             | 1          | 3     |
| Results/ResultCollection.php                                    | 1             | 1          | 2     |
| Results/Result.php                                              | 1             | 1          | 2     |
+-----------------------------------------------------------------+---------------+------------+-------+

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.