J'écris du code Ruby pour un exercice de chiffrement simple et j'ai souvent rencontré ce dilemme (l'exercice est un chiffre solitaire si vous devez le savoir). Il s'agit de savoir si je devrais compléter ma logique avec des variables descriptives et des instructions en une seule étape qui rendent la fonction lisible au lieu d'une instruction concise, voire dense, qui élimine la répétition et / ou minimise les risques d'erreurs.
Mon exemple le plus récent: mon programme accepte les entrées et, en raison de directives de format rigides, il peut facilement déterminer si les entrées doivent être chiffrées ou déchiffrées. Pour simplifier, une fois que la clé de cryptage et le message sont convertis / générés pour être compatibles, il s'agit de soustraire la clé du message crypté ou d'ajouter la clé à un message non crypté, pour obtenir la sortie souhaitée (pensez à la clé comme cryptage, message + cryptage = code; code - cryptage = message). La position DRY me dit que je devrais convertir mon message crypté différemment de mon message non crypté afin que la fonction qui prend la clé de cryptage et l'applique au message n'a jamais besoin de faire de distinction. J'ai trouvé que cela signifie que j'ai besoin de quelques instructions imbriquées if dans la fonction, mais la logique semble solide. Ce code, cependant, n'est pas facilement lisible.
Je pourrais, d'autre part, écrire deux fonctions différentes qui sont appelées en fonction d'un indicateur qui est défini lorsque l'application détermine le chiffrement ou le déchiffrement. Ce serait plus simple à lire, mais cela dupliquerait la fonction de haut niveau consistant à appliquer la clé de chiffrement à un message (en le faisant être chiffré ou déchiffré).
Dois-je m'orienter vers un code lisible ou un code concis? Ou ai-je manqué une autre façon d'obtenir cette fonctionnalité et de satisfaire les deux principes? S'agit-il d'une position à une échelle dans laquelle il faut considérer l'objectif du projet et prendre les meilleures décisions pour atteindre cet objectif?
Jusqu'à présent, j'ai tendance à mettre l'accent sur le code SEC concis sur le code lisible.
Réponses:
SEC est une ligne directrice, pas une religion. Ceux qui le portent au point de DRY par-dessus tout, l'ont poussé trop loin.
Tout d'abord, le code utilisable est primordial. Si le code n'est pas utile et utilisable, il ne l'est pas ... et il est inutile de l'écrire en premier lieu.
Deuxièmement, un jour, quelqu'un devra maintenir votre code. Si votre code n'est pas maintenable, ils briseront votre "belle" conception dense, concise et sèche tout en maudissant votre nom. Ne fais pas ça. J'ai été cette personne et chaque fois que je vois un certain nom dans l'annotation du code, je frissonne.
Faire du code dense qui manque de "variables descriptives" et tout coller dans des expressions ternaires imbriquées avec lambdas sans aucune documentation est intelligent. Il est bon de savoir que vous pouvez le faire - mais ne le faites pas. Le code intelligent est très difficile à déboguer. Évitez d'écrire du code intelligent .
La plupart du temps consacré au logiciel est consacré à la maintenance du logiciel - et non à sa première écriture. Écrivez le code afin que vous (ou quelqu'un d'autre) puissiez corriger rapidement et facilement les bogues et y ajouter des fonctionnalités selon les besoins avec le moins de modifications de conception idéales.
la source
Je ne suis pas sûr sur la base de la question que vous comprenez SEC. Le code DRY n'est pas le même que concis. C'est souvent le contraire.
Ici, je ne sais pas quel est le gros problème pour cet exemple. Créez une fonction pour crypter, une fonction pour décrypter, des assistants pour des fonctionnalités communes (mélanger des octets), et un simple frontal pour prendre des entrées et déterminer crypter / décrypter ... Pas de répétition.
En général cependant, DRY et la lisibilité existent pour aider à maintenir et à étendre le code. Tous les scénarios ne sont pas égaux, un gros coup de lisibilité pour supprimer une petite répétition n'est pas bon, ni un tas de duplication pour ajouter un peu de lisibilité.
Si vous appuyez dessus, je préférerais la lisibilité. Le code en double peut toujours être testé - un code illisible vous amène à faire (et à tester) la mauvaise chose.
la source
Je ne suis pas familier avec votre cas spécifique, mais je peux donner quelques directives générales.
Le but de la lisibilité et de DRY est la maintenabilité .
La maintenabilité est importante dans la plupart des situations, vous passerez plus de temps à maintenir le code qu'à l'écrire. Cela est particulièrement vrai si vous considérez l'écriture de code comme un type spécial de maintenance.
Malheureusement, DRY est souvent mal compris. C'est en partie parce que cela semble si simple, mais comme beaucoup de choses simples, cela peut être, bien ... compliqué.
L'intention de DRY est que chaque unité de fonctionnalité existe en un seul endroit. Si le principe est respecté, le responsable du code chargé de modifier ou de vérifier que la fonctionnalité peut traiter le code en une seule fois. Si DRY n'est pas suivi, il existe un danger très réel qu'une certaine copie de la fonctionnalité ne soit pas maintenue correctement.
La violation la plus flagrante de DRY est le codage copier-coller, où des blocs entiers de code sont répétés textuellement dans la base de code. Ceci est étonnamment commun dans mon expérience, et aucun moyen qui ajoute à la lisibilité. Par conséquent, la refactorisation du code pour introduire une méthode commune augmente invariablement la conformité DRY et la lisibilité.
La deuxième violation la plus flagrante est "copier-coller et changer un peu". Encore une fois, la refactorisation pour introduire une méthode commune avec des paramètres, ou la décomposition d'une fonction en étapes et l'abstraction des points communs augmente presque toujours la lisibilité.
Ensuite, il y a les violations les plus subtiles, où la fonctionnalité est dupliquée mais le code est différent. Ce n'est pas toujours facile à repérer, mais lorsque vous le voyez et que vous refactorisez le code commun en une seule méthode / classe / fonction, le code est généralement plus lisible qu'auparavant.
Enfin, il y a les cas de répétition du design. Par exemple, vous avez peut-être utilisé le modèle d'état plusieurs fois dans votre base de code et vous envisagez une refactorisation pour éliminer cette répétition. Dans ce cas, procédez avec prudence. Vous réduisez peut-être la lisibilité en introduisant davantage de niveaux d'abstraction. En même temps, il ne s'agit pas vraiment de duplication de fonctionnalité mais de duplication d'abstraction. Parfois ça vaut le coup ... mais souvent ça ne l'est pas. Votre principe directeur sera de demander "lequel des deux est plus facile à maintenir".
Chaque fois que je fais ces appels au jugement, j'essaie de considérer le temps que les gens passeront à maintenir le code. Si le code est une fonctionnalité métier principale, il aura probablement besoin de plus de maintenance. Dans ce cas, je vise à rendre le code maintenable pour les personnes qui connaissent la base de code et les abstractions impliquées. Je serais plus heureux d'introduire un peu plus d'abstraction pour réduire la répétition. En revanche, un script qui est rarement utilisé et rarement maintenu peut être moins facile à saisir pour les responsables s'il implique trop d'abstraction. Dans ce cas, je me tromperais du côté de la répétition.
Je considère également le niveau d'expérience des autres membres de mon équipe. J'évite les abstractions "fantaisistes" avec des développeurs inexpérimentés, mais je mets à profit des modèles de conception reconnus par l'industrie avec des groupes plus matures.
En concision, la réponse à votre question est de faire tout ce qui rend votre code plus maintenable. Ce que cela signifie dans votre scénario est à vous de décider.
la source
Si vos fonctions deviennent plus compliquées et plus longues (donc moins lisibles) lorsque vous essayez de les rendre SÈCHES, vous vous trompez. Vous essayez de mettre trop de fonctionnalités dans une fonction car vous pensez que c'est le seul moyen d'éviter de répéter les mêmes morceaux de code dans une deuxième fonction.
Rendre le code SEC signifie presque toujours refactoriser des fonctionnalités communes vers des fonctions plus petites. Chacune de ces fonctions devrait être plus simple (et donc plus lisible) que l'original. Pour conserver tout dans la fonction d'origine au même niveau d'abstraction, cela peut également signifier de refactoriser des pièces supplémentaires qui ne sont pas utilisées ailleurs. Votre fonction d'origine devient alors une "fonction de haut niveau", appelant les plus petites, et elle devient aussi plus petite et plus simple.
Faire cela conduit par conséquent principalement à différents niveaux d'abstractions dans votre code - et certaines personnes pensent que ce type de code est moins lisible. D'après mon expérience, c'est une erreur. Le point clé ici est de donner aux petites fonctions de bons noms, d'introduire des types de données et des abstractions bien nommés qui peuvent être facilement saisis par une deuxième personne. De cette façon, "SEC" et "lisibilité" ne devraient entrer en conflit que très, très rarement.
la source
Bien que je ne sois pas certain de la cause exacte du problème ici, mon expérience est que lorsque vous trouvez SEC et la lisibilité en conflit, cela signifie qu'il est temps de refactoriser quelque chose.
la source
Je choisirais lisible (= maintenable) au lieu de SEC n'importe quel jour de la semaine. En réalité, les deux s'alignent souvent, quelqu'un qui comprend le concept de DRY produira généralement (principalement) du code lisible.
la source
Très très très très très peu de fois dans ma carrière j'ai trouvé un cas légitime qui opposait la lisibilité à DRY. Rendez-le lisible en premier. Nommez bien les choses. Copiez et collez si besoin.
Maintenant, reculez et regardez la totalité que vous avez créée, comme un artiste qui prend du recul pour regarder sa peinture. Vous pouvez maintenant identifier correctement la répétition.
Le code répété doit être soit refactorisé dans sa propre méthode, soit retiré dans sa propre classe.
La répétition du code devrait être un dernier recours. Lisable ET SEC d'abord, à défaut de cette lisibilité si vous limitez la portée du code répété.
la source