New in Coding Standard 4: Long Line Breaks Automated and 3 Legacy Prevention Fixers

This post was updated at August 2020

Updated ECS YAML to PHP configuration since ECS 8.


Legacy code prevention, lines automated and clear naming of classes in huge projects. That all is coming to Coding Standard 4 (still in alpha).

Are you curious what work will now these 4 news fixers handle for you? Look inside.

1. Let Coding Standard handle Line Length for You

  Check the PR #749

I'm so happy to announce this fixer, because it saved my so many times and also motivates me to use decoupling to smaller, SRP classes.

If you use LineLengthSniff, you know it's painful to fix every error report it makes.

<?php

// ecs.php

declare(strict_types=1);

use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $services = $containerConfigurator->services();

    $services->set(LineLengthSniff::class)
        ->property('absoluteLineLimit', 120);
};

The most typical use case is constructor dependencies. You code start small:

public function __construct(OneLittleDependency $oneLittleDependency)
{
}

Then it grows...

public function __construct(OneLittleDependency $oneLittleDependency, AnotherLittleDependency $anotherLittleDependency)
{
}

...and grows...

public function __construct(OneLittleDependency $oneLittleDependency, AnotherLittleDependency $anotherLittleDependency, $someParameter)
{
}

...sniff screams, so you inline it...

public function __construct(
    OneLittleDependency $oneLittleDependency,
    AnotherLittleDependency $anotherLittleDependency,
    $someParameter
) {
}

...then you refactor and merge 2 services to 1...

public function __construct(
    OneLittleDependency $oneLittleDependency,
    $someParameter
) {
}

...and that is inconsistent and has no reason to be inlined, so you inline it...

public function __construct(OneLittleDependency $oneLittleDependency, $someParameter) {
}

...and that is one of many reasons people don't like to decouple classes and keep them small.


There are other cases, where parameters, arguments or array items can change up and down:

-$someObject = new SomeClass(
-    $shortArg
-);
+$someObject = new SomeClass($shortArg);
-$someArray = ['superlooongArgumentsover120chars', 'superlooongArgumentsover120chars', 'superlooongArgumentsover120chars'];
+$someArray = [
+    'superlooongArgumentsover120chars',
+    'superlooongArgumentsover120chars',
+    'superlooongArgumentsover120chars'
+];

What if I told you that you'll have to never deal with this manually. Ever!

Welcome LineLengthFixer.

How to Register It?

<?php

// ecs.php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;

return static function (ContainerConfigurator $containerConfigurator): void {
    $services = $containerConfigurator->services();
    $services->set(LineLengthFixer::class);
};

As you guessed, this fixer works with 120 chars as maximum line-size... by default ↓


2. Choose Line Length to Match Your Display

  Check the PR #751

<?php

// ecs.php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;

return static function (ContainerConfigurator $containerConfigurator): void {
    $services = $containerConfigurator->services();

    $services->set(LineLengthFixer::class)
        ->call('configure', [[
            'max_line_length' => 100, # default: 120
            'break_long_lines' => true, # default: true
            'inline_short_lines' => false, # default: true
        ]]);
};


3. Make your Static Classes visible

It started as one simple static method. A helper method. They say: it's ok to use static methods, when you know when to use them. And that's how cancer started to spread slowly and lethally through Symplify code.

One day you wake up and from 1 static method is 60 static factories all over your code - Dependency Injection for very poor. And that not the worst. When all code works and is easy to maintain, 1 static method can't hurt it, right?

Well until you need to replace one of nested dependencies that requires few more classes. And then you realized your work is to basically manually maintain dump of dependency injection container and that you're not coding anymore.

It took weeks to get from this position back to clear dependency injection and I don't want to do it ever again. That's why this PHPStan rule was born.

How to Register It?

rules:
    - Symplify\CodingStandard\Rules\NoClassWithStaticMethodWithoutStaticNameRule


4. Prevent & references with ForbiddenStaticFunctionSniff

  Check the PR #692

We all already know that &$references are bad practise, since they increase cyclomatic complexity and hide dependency logic.

function someFunction(&$var)
{
    $var + 1;
}

And that we should prefer explicit syntax:

function someFunction($var)
{
    return $var + 1;
}

I though I would never meet them again, but they somehow pop-up in PRs. So we made a PHPStan rule for it:

How to Register It?

# phpstan.neon
rules:
    - Symplify\CodingStandard\Rules\NoReferenceRule


5. Clear Child Class Naming Once and For All with ClassNameSuffixByParentFixer

  Check the PR #633

Often in the code of private companies there are classes like:

If you use PhpStorm and open file shortcut, you know where I aim.

Now, imagine you want to update the Command that sorts Products by price to Redis database. Inside, it looks like this:

final class ProductSorter extends Command
{
    // ...
}

Which one do you open?

I could also ask, which one is the interface and which is its implementation, but there is already checker for that.

Probably each of them manually until you find the right one, which really sucks. That why not only methods names, but also class names should be as descriptive and as deterministic as possible. Like this:

-final class ProductSorter extends Command
+final class ProductSorterCommand extends Command
 {
     // ...
 }

And then you have clear class names, that you're able to distinguish without their content:

And that's exactly what ClassNameRespectsParentSuffixRule helps you to do.

How to Register It?

# phpstan.neon
rules:
    - Symplify\CodingStandard\Rules\ClassNameRespectsParentSuffixRule

parameters:
    symplify:
        # it handles many default cases, but allows you to add your own
        forbidden_parent_classes: []



Happy sniffing and fixing!