1. Anti pattern Flag parameter


Le flag parameter peut être considéré comme un anti-pattern.
Le principe est de passer un argument supplémentaire (le plus souvent de type boolean) à une méthode afin que celle-ci se comporte différemment selon ce paramètre.

Par exemple, supposons cette fonction :

function render(array $data, bool $flag)
{
    if ($flag) {
        // Premier comportement.
    } else {
        // Second comportement.
    }
}

// Code appelant
$data = getData();
$flag = getFlag();
render($data, $flag);


1.1. Solution 1 : découper la fonction en deux.

La fonction render doit être découpée en deux et c'est à l'appelant de ces fonctions de faire le if/else qui convient.

function firstRender(array $data)
{
    // Premier comportement.
}
function secondRender(array $data)
{
    // Second comportement.
}

// Code appelant
$data = getData();
$flag = getFlag();

if ($flag) {
    firstRender($data);
} else {
    secondRender($data);
}


1.2. Solution 2 : fusionner les deux paramètres

Si la fonction n'est pas simple à découper (plusieurs if/else interne). Même s'il conviendrait de la refactoriser, il peut être pertinent dans certaines conditions de faire porter la valeur du flag soit dans un objet que l'on transfère à la fonction, soit dans la classe qui contient la méthode.

1.2.1 Cas 1 : via un objet

class Renderer
{
    public function render(object $object)
    {
        $flag = $object->getFlag();
        // Suite des différentes conditions.
    }
}


1.2.2 Cas 2 : via un attribut de la classe

class Renderer
{
    protected bool $flag;

    function setFlag(bool $flag)
    {
        $this->flag = $flag;
    }

    function getFlag()
    {
        return $this->flag;
    }

    function render(object $object)
    {
        $flag = $this->getFlag();
        // Suite des différentes conditions.
    }
}


1.3. Solution 3 : créer plusieurs classes et une factory ou équivalent

Chaque classe possède un comportement propre. Ce comportement contient la logique selon le cas flag=true|false.
Le rôle de la Factory sera alors de fournir la bonne instance en fonction du paramètre flag.

// Code appelant
$rendererFactory = new RendererFactory();
$renderer = $rendererFactory->create($flag);
$renderer->render($data);


🧙‍♂️️Si la fonction existe déjà, il peut être long de tout refaire, il faut à ce moment là prendre un peu de temps de réflexion quant à l'intérêt de tout refaire pour un gain immédiat souvent faible.
Privilégier donc la réfacto des morceaux de code importants (à vous de définir cette importance en fonction du contexte).


1.4. Solution type Troll

🧙‍♂️️Cette solution n'est évidemment pas conseillée.


L'idée est de créer une instance Flag et de la passer à la fonction ; ainsi nous ne passons plus un boolean et donc nous sortons de l'anti-pattern.

<?php

class Flag
{
    protected bool $value;

    public function __construct(bool $value)
    {
        $this->value = $value;
    }

    public function isFalse(): bool
    {
        return !$this->isTrue();
    }

    public function isTrue(): bool
    {
        return true === $value;
    }
}

// Code appelant
$data = getData();
$flag = new Flag(true);
render($data, $flag);

2. Liste des anti patterns

Voici la liste des anti patterns les plus populaires.

2.1. 20 antipatterns généraux

* Accidental complexity
* Action at a distance
* Boat anchor
* Busy waiting
* Caching failure
* Cargo cult programming
* Coding by exception
* Design pattern
* Error hiding
* Flag parameter
* Hard code
* Lasagna code
* Lava flow
* Loop-switch sequence
* Magic numbers
* Magic strings
* Repeating yourself
* Shooting the messenger
* Shotgun surgery
* Soft code
* Spaghetti code

2.2. 12 antipatterns POO

* Anemic domain model
* Call super
* Circle–ellipse problem
* Circular dependency
* Constant interface
* God object
* Object cesspool
* Object orgy
* Poltergeists
* Sequential coupling
* Singleton Pattern
* Yo-yo problem

2.2.1 9 antipatterns méthodologiques

* Copy and paste programming
* Golden hammer
* Invented here
* Not invented here (NIH) syndrome
* Premature optimization
* Programming by permutation
* Reinventing the square wheel
* Silver bullet
* Tester-driven development

3. Anti Pattern : LoopSwitch


3.1. Exemple

Voici un exemple d'implémentation de cet anti pattern.

<?php

namespace App\Core;

/**
 * Class LoopSwitch
 */
class LoopSwitch
{
    protected const FIRST_STEP = 'first_step';
    protected const SECOND_STEP = 'second_step';

    /**
     * @var string[]
     */
    protected array $steps = [
        self::FIRST_STEP,
        self::SECOND_STEP,
    ];

    /**
     * Executes All the steps.
     */
    public function executeAllSteps()
    {
        foreach($this->steps as $step) {
            $this->executeStep($step) ;
        }
    }

    /**
     * @param string $step
     */
    public function executeStep(string $step)
    {
        switch ($step) {
            case self::FIRST_STEP:
                echo self::FIRST_STEP;
                break;
            case self::SECOND_STEP:
                echo self::SECOND_STEP;
                break;
        }
    }
}