Exemple
Je suis tombé sur un code monolithique qui fait "tout" en un seul endroit - charger des données à partir de la base de données, montrer le balisage HTML, agir comme un routeur / contrôleur / action. J'ai commencé à appliquer le code de base de données mobile SRP dans son propre fichier, fournissant une meilleure dénomination des choses, et tout semblait bien, mais j'ai ensuite commencé à douter de la raison pour laquelle je fais cela.
Pourquoi refactoriser? Quel est le but? Est-ce inutile? Quel est l'avantage? Notez que j'ai principalement laissé le fichier monolithique tel quel, mais que je n'ai refactorisé que la plus petite partie qui était pertinente pour la zone où j'avais besoin de faire un peu de travail.
Code d'origine:
Pour donner un exemple concret, je suis tombé sur cet extrait de code - il charge les spécifications du produit soit par un identifiant de produit connu, soit par un identifiant de version sélectionné par l'utilisateur:
if ($verid)
$sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid);
else
$sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ;
$result1 = query($sql1);
$row1 = fetch_array($result1);
/* html markup follows */
Refactoring:
Étant donné que je fais un travail me demandant de changer les choses dans cette partie spécifique du code, je l'ai changé pour utiliser le modèle de référentiel et l'ai mis à niveau pour utiliser les fonctionnalités MySQL orientées objet:
//some implementation details omitted
$this->repository = new SpecRepository($mysql);
if ($verid)
$row1 = $this->repository->getSpecByVersion($verid);
else
$row1 = $this->repository->getSpecByProductId($productid);
/* html markup follows to be refactored or left alone till another time*/
//added new class:
class SpecRepository extends MySqlRepository
{
function getSpecByVersion(int $verid)
{
return $this->getMySql()->paramQuery("
SELECT * FROM product_spec WHERE id = ?
", $verid)->getSingleArray();
}
function getSpecByProductId(int $productid)
{
return $this->getMySql()->paramQuery("
SELECT * FROM product_spec WHERE product_id = ?
", $productid)->getSingleArray();
}
}
Dois-je faire ça?
En regardant les changements, le code est toujours là, code avec la même fonctionnalité, mais dans des fichiers différents, des noms et des endroits différents, en utilisant un style plus orienté objet plutôt que procédural. En fait, il est amusant de noter que le code refactorisé semble beaucoup plus gonflé malgré les mêmes fonctionnalités.
Je prévois quelques réponses disant "si vous ne connaissez pas les raisons pour lesquelles vous refactorisez, ne le faites pas", et peut-être que je pourrais être d'accord. Mes raisons sont d'améliorer la qualité du code au fil du temps (et j'espère que je le ferai en suivant SRP et d'autres principes).
Ces raisons sont-elles suffisantes ou suis-je en train de perdre mon temps à "réorganiser le code" de cette façon? Pour être honnête, le refactoring global ressemble un peu à de l'eau - cela prend du temps et il devient plus "séparé" en ce qui concerne SRP, mais malgré mes bonnes intentions, je n'ai pas l'impression de faire des améliorations incroyables. Par conséquent, débattre s'il est préférable de laisser le code comme avant et non de refactoriser.
Pourquoi ai-je refactorisé en premier lieu?
Dans mon cas, j'ajoute de nouvelles fonctionnalités pour une nouvelle gamme de produits, je dois donc soit suivre la structure de code existante pour des gammes de produits similaires, soit écrire la mienne.
Select * from ..
peut être considéré comme un anti-modèle. Voir stackoverflow.com/q/3639861/31326select *
devient une "meilleure pratique".Réponses:
Dans l'exemple concret que vous avez donné, la refactorisation n'était peut-être pas nécessaire, du moins pas encore. Mais vous avez vu qu'il y avait un potentiel de code plus désordonné à l'avenir qui aurait conduit à une refactorisation plus longue et plus fastidieuse, alors vous avez pris l'initiative et nettoyé les choses maintenant.
Je dirais également que l'avantage que vous avez obtenu ici était un code plus facile à comprendre, du moins de mon point de vue, en tant que personne qui ne connaît pas votre base de code.
En général:
Le refactoring permet-il aux autres développeurs de comprendre plus facilement votre code?
Le refactoring facilite-t-il l'amélioration du code?
Le refactoring facilite-t-il la maintenance du code?
Le refactoring facilite-t-il le débogage?
Si la réponse à l'un d'entre eux était "oui", alors cela en valait la peine, et c'était plus que "déplacer du code?"
Si la réponse à toutes ces questions était «non», il n'était peut-être pas nécessaire de la refactoriser.
La taille finale de la base de code peut être plus grande en termes de LoC (bien que certains refactorings puissent réduire la base de code en rationalisant le code redondant), mais cela ne devrait pas être un facteur s'il y a d'autres gains.
la source
La refactorisation gonfle si vous démontez un monolithe.
Cependant, vous avez déjà trouvé l'avantage.
"Dans mon cas, j'ajoute de nouvelles fonctionnalités pour une nouvelle gamme de produits."
Vous ne pouvez pas ajouter des fonctionnalités à un monolithe très facilement sans casser des choses.
Vous avez dit que le même code récupère les données et effectue le balisage. Parfait, jusqu'à ce que vous souhaitiez modifier les colonnes que vous sélectionnez et manipulez pour les afficher dans certaines conditions. Soudain, votre code de balisage cesse de fonctionner dans un certain cas et vous devez refactoriser.
la source
if/else
bloc et suivrais le style de code d'origine pour ajouter des instructions SQL, puis je mettrais un nouveau balisage HTML dans le même fichier monolith. Et pour changer les colonnes, je trouverais le bloc if / else responsable du logement des lignes SQL, et éditerais ce SQL pour apporter des modifications aux colonnes, sans casser ce fichier.J'envisage de refactoring si je sais que je devrai travailler des mois voire des années avec ce projet. Si je dois faire un changement ici et là, alors je résiste à l'envie de déplacer le code.
La façon préférée de refactoriser est quand j'ai un code de base avec une sorte de tests automatisés. Néanmoins, je dois être très prudent avec ce que je change pour m'assurer que les choses fonctionnent comme avant. Vous perdrez confiance très bientôt si vous livrez des bogues dans d'autres domaines que celui que vous êtes censé travailler.
J'apprécie le refactoring pour les raisons suivantes:
comment
le code via les noms de variables, les noms de méthodesarchitect
la solution. Cela viendra lors de l'écriture - réécriture du code dans les deux sens.Dans un monde parfait, les refactorisations devraient être vérifiées par des tests unitaires, des tests d'intégration, etc. S'il n'y en a pas, essayez de les ajouter. De plus, certains IDE peuvent aider beaucoup. J'utilise généralement un plugin qui coûte de l'argent. Je veux passer peu de temps avec les refactorings et être très efficace à ce sujet.
J'ai également introduit des bugs. Je peux voir pourquoi certains QA demandent
are you guys doing refactoring? because everything stopped working!
C'est le risque que l'équipe doit assumer et nous devons toujours être transparents à ce sujet.Au fil des ans, j'ai constaté que le refactoring continu améliorait ma productivité. Était beaucoup plus facile d'ajouter de nouvelles fonctionnalités. De plus, les grandes reconstructions ne nécessitaient pas une réécriture complète, comme cela arrivait souvent lorsque la base de code n'était pas adaptée à l'évolution du produit. C'est aussi amusant.
la source
I
parto
cependant.Je pense que la question que vous devez vous poser n'est pas tant "Y a-t-il un avantage?" mais "Qui paiera pour ce travail?"
Nous pouvons tous discuter des avantages perçus jusqu'à la fin des jours, mais à moins que vous n'ayez un client qui croit en ces avantages et les valorise suffisamment pour payer les changements, vous ne devriez pas les faire.
C'est trop facile lorsque vous faites partie de l'équipe de développement quelque part pour voir le code et que vous souhaitez le refactoriser pour le rendre «meilleur». Mais mettre une valeur sur un «meilleur code» lorsque le produit fonctionne déjà est vraiment difficile.
Des choses comme «le développement plus rapide de nouvelles fonctionnalités» ne le coupent pas car ce ne sont que des coûts réduits. Vous devez générer des ventes.
la source
À mon avis, le refactoring est un bon investissement.
Sinon, vous obtiendrez bientôt des dettes techniques (problèmes non résolus, mauvais code qui ne fonctionne que sous certaines conditions, etc.). Les dettes techniques augmenteront bientôt de plus en plus, jusqu'à ce que le logiciel ne soit plus maintenable.
Mais pour que le refactoring fonctionne, il faut aussi investir dans les tests. Vous devez créer des tests automatisés, idéalement, vous devriez avoir des tests unitaires et des tests d'intégration. Cela vous empêche de casser le code existant.
Si vous devez convaincre votre patron ou vos collègues, vous devriez lire quelques livres sur les méthodes agiles (par exemple SCRUM) et le développement piloté par les tests.
la source