Mysql
 sql >> Base de données >  >> RDS >> Mysql

Enregistrer le calcul dans le code ou la base de données ?

Eval c'est le mal

Tout d'abord :n'utilisez pas eval() à moins qu'il y ait une bonne raison. Et il n'y a jamais de bonne raison .

dans le pire des cas eval() rend votre application vulnérable aux attaques par injection et elle est également très lente. Un peu de recherche révèle de nombreuses raisons pour lesquelles eval est un grand non-non.

N'enregistrez pas votre code de calcul dans la base de données

Si vous le faites et que vous souhaitez passer de PHP à un autre langage, vous aurez toujours du code PHP dans votre base de données. Cela rend très difficile la migration des langues. Vous devez toujours vous efforcer de rendre autant de parties de votre application aussi indépendantes que possible.

Dans ce cas, vous associeriez étroitement le langage que vous utilisez à la base de données. C'est une mauvaise pratique.

De plus, les seules possibilités d'exécuter vos calculs à partir de la base de données seraient de les évaluer (ce qui est mauvais, voir ci-dessus) ou de désassembler la chaîne avec des opérations de chaîne ou des regex qui causent des efforts inutiles.

Tout tourne autour de la Stratégie

Afin de résoudre votre problème, vous devez exécuter du code en fonction du calcul dont vous avez besoin. Cela peut être fait avec des instructions switch-case ou des instructions if. Mais ce n'est pas non plus une solution très élégante. Imaginez que vous auriez besoin d'exécuter d'autres opérations avant de calculer à l'avenir, ou d'étendre les fonctionnalités. Vous auriez besoin de mettre à jour tous vos cas ou déclarations if.

Il existe un joli modèle de conception qui s'appelle Strategy Pattern . Le modèle de stratégie résout les problèmes lorsqu'un cas d'utilisation peut être traité différemment, ce qui est probablement ce que vous souhaitez.

Vous voulez calculer quelque chose (cas d'utilisation) et il existe différents types de calcul pour cela (différentes stratégies)

Comment ça marche

Pour mettre en œuvre le modèle de stratégie, vous avez essentiellement besoin de trois choses.

  • Un cours où vous injectez vos stratégies. Il s'agit essentiellement d'un wrapper pour vos tâches stratégiques.
  • Une interface qui sera implémentée par vos stratégies
  • Vos stratégies

Votre interface pourrait ressembler à ceci :

<?php
interface CalculatableInterface {
    
    public function calculate();

}

L'interface s'assurera que toutes vos stratégies fournissent une méthode pour exécuter réellement le calcul. Rien de spécial.

Ensuite, vous voudrez peut-être avoir une classe de base qui prend vos opérateurs de calcul comme arguments de constructeur et les stocke dans des propriétés.

<?php
abstract class Calculatable {

    protected $valueA;
    protected $valueB;

    public function __construct($valueA, $valueB)
    {
        $this->valueA = $valueA;
        $this->valueB = $valueB;
    }

}

Maintenant ça devient sérieux. Nous mettons en œuvre nos stratégies.

<?php
class Division extends Calculatable implements CalculatableInterface {

    public function calculate()
    {
        return ($this->valueB != 0) ? $this->valueA / $this->valueB : 'NA';
    }

}

class Percentage extends Calculatable implements CalculatableInterface {

    public function calculate()
    {
        return ($this->valueB != 0) ? (100 / $this->valueB) * $this->valueA : 'NA';
    }

}

Bien sûr, vous pouvez nettoyer un peu celui-ci, mais ce que je veux souligner ici, c'est la déclaration de classe.

Nous étendons notre Calculatable class afin que nous puissions passer les opérations arithmétiques via le constructeur et nous implémentons la CalculatableInterface qui dit à notre classe :"Hé ! Vous devez fournir une méthode de calcul, peu m'importe que vous le vouliez ou non.

Nous verrons plus tard pourquoi cela fait partie intégrante du modèle.

Nous avons donc deux classes concrètes qui contiennent le code réel de l'opération arithmétique réelle. Si jamais vous en aviez besoin, vous pourriez le changer facilement comme vous le voyez. Pour ajouter plus d'opérations, ajoutez simplement une autre classe.

Nous allons maintenant créer une classe où nos stratégies peuvent être injectées. Plus tard, vous instancierez un objet de cette classe et travaillerez avec.

Voici à quoi cela ressemble :

<?php 
class Calculator {

    protected $calculatable;

    public function __construct( CalculatableInterface $calculatable )
    {
        $this->calculatable = $calculatable;
    }

    public function calculate()
    {
        return $this->calculatable->calculate();
    }

}

La partie la plus importante ici est le constructeur. Voyez comment nous tapons notre interface ici. En faisant cela, nous nous assurons que seul un objet peut être injecté (Injection de dépendance ) dont la classe implémente l'interface . Nous n'avons pas besoin d'exiger une classe concrète ici. C'est le point crucial ici.

Il y a aussi une méthode de calcul là-dedans. C'est juste un wrapper pour que notre stratégie exécute sa méthode de calcul.

En conclusion

Alors maintenant, nous avons juste besoin de créer un objet de notre Calculator et passez un objet de l'une de nos classes de stratégie (qui contient le code des opérations arithmétiques).

<?php
//The corresponding string is stored in your DB
$calculatable = 'Division';

$calc = new Calculator( new $calculatable(15, 100) );
echo $calc->calculate();

Essayez de remplacer la chaîne stockée dans $calculatable à Percentage et vous voyez que l'opération de calcul du pourcentage sera exécutée.

Conclusion

Le modèle de stratégie vous a permis de créer une interface propre pour travailler avec des tâches dynamiques qui ne sont rendues concrètes que pendant l'exécution. Ni votre base de données n'a besoin de savoir comment nous calculons les choses, ni votre calculatrice réelle. La seule chose dont nous devons nous assurer est de coder par rapport à une interface qui fournit une méthode pour nous permettre de calculer les choses.