
8. Marteau d'or
Un marteau d'or est un anti-modèle défini par la confiance qu'une solution particulière est universellement applicable. Exemples:-
Après avoir rencontré un problème et trouvé un modèle pour la solution parfaite, un programmeur essaie de coller ce modèle partout, en l'appliquant aux projets actuels et futurs, au lieu de rechercher les solutions appropriées pour des cas spécifiques.
-
Certains développeurs ont créé une fois leur propre variante de cache pour une situation spécifique (car rien d'autre ne convenait). Plus tard, sur le projet suivant qui n'impliquait aucune logique de cache spéciale, ils ont de nouveau utilisé leur variante au lieu d'utiliser des bibliothèques prêtes à l'emploi (par exemple, Ehcache). Le résultat a été un tas de bugs et d'incompatibilités, ainsi que beaucoup de temps perdu et de nerfs frits.
N'importe qui peut tomber dans cet anti-modèle. Si vous êtes débutant, vous ne connaissez peut-être pas les modèles de conception. Cela peut vous amener à essayer de résoudre tous les problèmes d'une manière que vous maîtrisez. Si nous parlons de professionnels, nous appelons cela déformation professionnelle ou nerdview. Vous avez vos propres modèles de conception préférés, et au lieu d'utiliser le bon, vous utilisez votre favori, en supposant qu'un bon ajustement dans le passé garantit le même résultat à l'avenir.
Cet écueil peut produire des résultats très tristes - d'une mise en œuvre mauvaise, instable et difficile à maintenir à un échec complet du projet. Tout comme il n'existe pas de pilule unique pour toutes les maladies, il n'existe pas de modèle de conception unique pour toutes les occasions.
9. Optimisation prématurée
L'optimisation prématurée est un anti-modèle dont le nom parle de lui-même.10. Code des spaghettis
Le code spaghetti est un anti-modèle défini par un code mal structuré, déroutant et difficile à comprendre, contenant toutes sortes de branchements, tels que des exceptions d'emballage, des conditions et des boucles. Auparavant, l'opérateur goto était le principal allié de cet anti-modèle. Les instructions Goto ne sont plus vraiment utilisées, ce qui élimine heureusement un certain nombre de difficultés et de problèmes associés.
public boolean someDifficultMethod(List<String> XMLAttrList) {
...
int prefix = stringPool.getPrefixForQName(elementType);
int elementURI;
try {
if (prefix == -1) {
...
if (elementURI != -1) {
stringPool.setURIForQName(...);
}
} else {
...
if (elementURI == -1) {
...
}
}
} catch (Exception e) {
return false;
}
if (attrIndex != -1) {
int index = attrList.getFirstAttr(attrIndex);
while (index != -1) {
int attName = attrList.getAttrName(index);
if (!stringPool.equalNames(...)){
...
if (attPrefix != namespacesPrefix) {
if (attPrefix == -1) {
...
} else {
if (uri == -1) {
...
}
stringPool.setURIForQName(attName, uri);
...
}
if (elementDepth >= 0) {
...
}
elementDepth++;
if (elementDepth == fElementTypeStack.length) {
...
}
...
return contentSpecType == fCHILDRENSymbol;
}
}
}
}
}
Ça a l'air horrible, n'est-ce pas ? Malheureusement, c'est l'anti-modèle le plus courant :( Même la personne qui écrit un tel code ne pourra pas le comprendre à l'avenir. D'autres développeurs qui verront le code penseront : "Eh bien, si cela fonctionne, alors d'accord - il vaut mieux ne pas y toucher". Souvent, une méthode est initialement simple et très transparente, mais au fur et à mesure que de nouvelles exigences sont ajoutées, la méthode est progressivement encombrée d'instructions de plus en plus conditionnelles, la transformant en une monstruosité comme celle-ci. Si une telle méthode apparaît, vous devez le refactoriser complètement ou au moins les parties les plus déroutantes. Généralement, lors de la planification d'un projet, du temps est alloué pour le refactoring, par exemple, 30 % du temps de sprint est pour le refactoring et les tests. Bien sûr, cela suppose qu'il n'y a pas de précipitation (mais quand cela arrive-t-il jamais).ici .
11. Numéros magiques
Les nombres magiques sont un anti-modèle dans lequel toutes sortes de constantes sont utilisées dans un programme sans aucune explication de leur but ou de leur signification. C'est-à-dire qu'ils sont généralement mal nommés ou dans les cas extrêmes, il n'y a aucun commentaire expliquant ce que sont les commentaires ou pourquoi. Comme le code spaghetti, c'est l'un des anti-modèles les plus courants. Quelqu'un qui n'a pas écrit le code peut avoir ou non une idée des nombres magiques ou de leur fonctionnement (et avec le temps, l'auteur lui-même ne pourra pas les expliquer). Par conséquent, la modification ou la suppression d'un nombre entraîne l'arrêt magique du code. Par exemple, 36 et 73. Pour lutter contre cet anti-modèle, je recommande une révision du code. Votre code doit être examiné par des développeurs qui ne sont pas impliqués dans les sections pertinentes du code. Leurs yeux seront frais et ils se poseront des questions : qu'est-ce que c'est et pourquoi as-tu fait ça ? Et bien sûr, vous devez utiliser des noms explicatifs ou laisser des commentaires.12. Programmation par copier-coller
La programmation par copier-coller est un anti-modèle dans lequel le code de quelqu'un d'autre est copié et collé sans réfléchir, ce qui peut entraîner des effets secondaires imprévus. Par exemple, copier et coller des méthodes avec des calculs mathématiques ou des algorithmes complexes que nous ne comprenons pas entièrement. Cela peut fonctionner pour notre cas particulier, mais dans d'autres circonstances, cela pourrait entraîner des problèmes. Supposons que j'ai besoin d'une méthode pour déterminer le nombre maximum dans un tableau. En fouillant sur Internet, j'ai trouvé cette solution :
public static int max(int[] array) {
int max = 0;
for(int i = 0; i < array.length; i++) {
if (Math.abs(array[i]) > max){
max = array[i];
}
}
return max;
}
Nous obtenons un tableau avec les nombres 3, 6, 1, 4 et 2, et la méthode renvoie 6. Super, gardons-le ! Mais plus tard, nous obtenons un tableau composé de 2,5, -7, 2 et 3, puis notre résultat est -7. Et ce résultat n'est pas bon. Le problème ici est que Math.abs() renvoie la valeur absolue. L'ignorance de cela mène au désastre, mais seulement dans certaines situations. Sans une compréhension approfondie de la solution, il existe de nombreux cas que vous ne pourrez pas vérifier. Le code copié peut également aller au-delà de la structure interne de l'application, à la fois stylistiquement et à un niveau architectural plus fondamental. Un tel code sera plus difficile à lire et à maintenir. Et bien sûr, nous ne devons pas oublier que copier directement le code de quelqu'un d'autre est une forme particulière de plagiat.
13. Réinventer la roue
Réinventer la roue est un anti-modèle, aussi parfois appelé réinventer la roue carrée. Essentiellement, ce modèle est l'opposé de l'anti-modèle copier-coller considéré ci-dessus. Dans cet anti-modèle, le développeur implémente sa propre solution à un problème pour lequel des solutions existent déjà. Parfois, ces solutions existantes sont meilleures que ce que le programmeur invente. Le plus souvent, cela n'entraîne qu'une perte de temps et une baisse de productivité : le programmeur peut ne pas trouver de solution du tout ou peut trouver une solution qui est loin d'être la meilleure. Cela dit, nous ne pouvons pas exclure la possibilité de créer une solution indépendante, car cela est une voie directe vers la programmation par copier-coller. Le programmeur doit être guidé par les tâches de programmation spécifiques qui se présentent afin de les résoudre avec compétence, que ce soit en utilisant des solutions toutes faites ou en créant des solutions personnalisées. Très souvent, la raison de l'utilisation de cet anti-modèle est simplement la hâte. Le résultat est une analyse superficielle de (recherche) de solutions toutes faites. Réinventer la roue carrée est un cas où l'anti-modèle considéré a un résultat négatif. Autrement dit, le projet nécessite une solution personnalisée et le développeur la crée, mais mal. En même temps, une bonne option existe déjà et d'autres l'utilisent avec succès. Résultat : une énorme quantité de temps est perdue. Premièrement, nous créons quelque chose qui ne fonctionne pas. Ensuite, nous essayons de le refactoriser, et finalement nous le remplaçons par quelque chose qui existait déjà. Un exemple est l'implémentation de votre propre cache personnalisé lorsque de nombreuses implémentations existent déjà. Quel que soit votre talent en tant que programmeur, vous devez vous rappeler que réinventer une roue carrée est à tout le moins une perte de temps. Et, comme vous le savez, le temps est la ressource la plus précieuse.14. Problème de yo-yo
Le problème du yo-yo est un anti-modèle dans lequel la structure de l'application est trop compliquée en raison d'une fragmentation excessive (par exemple, une chaîne d'héritage trop subdivisée). Le "problème yo-yo" survient lorsque vous avez besoin de comprendre un programme dont la hiérarchie d'héritage est longue et complexe, créant des appels de méthode profondément imbriqués. En conséquence, les programmeurs doivent naviguer entre de nombreuses classes et méthodes différentes afin d'inspecter le comportement du programme. Le nom de cet anti-motif vient du nom du jouet. A titre d'exemple, regardons la chaîne d'héritage suivante : Nous avons une interface Technologie :
public interface Technology {
void turnOn();
}
L'interface Transport en hérite :
public interface Transport extends Technology {
boolean fillUp();
}
Et puis nous avons une autre interface, GroundTransport :
public interface GroundTransportation extends Transport {
void startMove();
void brake();
}
Et à partir de là, nous dérivons une classe abstraite Car :
public abstract class Car implements GroundTransportation {
@Override
public boolean fillUp() {
/* some implementation */
return true;
}
@Override
public void turnOn() {
/* some implementation */
}
public boolean openTheDoor() {
/* some implementation */
return true;
}
public abstract void fixCar();
}
Vient ensuite la classe Volkswagen abstraite :
public abstract class Volkswagen extends Car {
@Override
public void startMove() {
/* some implementation */
}
@Override
public void brake() {
/* some implementation */
}
}
Et enfin, un modèle spécifique :
public class VolkswagenAmarok extends Volkswagen {
@Override
public void fixCar(){
/* some implementation */
}
}
Cette chaîne nous oblige à rechercher des réponses à des questions telles que :
-
Combien de méthodes a-
VolkswagenAmarok
t-il? -
Quel type doit être inséré à la place du point d'interrogation afin d'obtenir une abstraction maximale :
? someObj = new VolkswagenAmarok(); someObj.brake();
15. Complexité accidentelle
La complexité inutile est un anti-modèle dans lequel des complications inutiles sont introduites dans une solution.
public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description)throws Exception {
switch (type){
case CAR:
jdbcTemplate.update(CREATE_RELATION_WITH_CAR, languageId, serviceId, description);
case USER:
jdbcTemplate.update(CREATE_RELATION_WITH_USER, languageId, serviceId, description);
case FILE:
jdbcTemplate.update(CREATE_RELATION_WITH_FILE, languageId, serviceId, description);
case PLAN:
jdbcTemplate.update(CREATE_RELATION_WITH_PLAN, languageId, serviceId, description);
case CUSTOMER:
jdbcTemplate.update(CREATE_RELATION_WITH_CUSTOMER, languageId, serviceId, description);
default:
throw new Exception();
}
}
Et en conséquence, nous avons cette énumération :
public enum ServiceType {
CAR(),
USER(),
FILE(),
PLAN(),
CUSTOMER()
}
Tout semble simple et bon... Mais qu'en est-il des autres méthodes ? En effet, ils auront également tous un tas d' switch
instructions et un tas de requêtes de base de données presque identiques, ce qui à son tour compliquera et gonflera considérablement notre classe. Comment tout cela pourrait-il être simplifié ? Améliorons un peu notre énumération :
@Getter
@AllArgsConstructor
public enum ServiceType {
CAR("cars_descriptions", "car_id"),
USER("users_descriptions", "user_id"),
FILE("files_descriptions", "file_id"),
PLAN("plans_descriptions", "plan_id"),
CUSTOMER("customers_descriptions", "customer_id");
private String tableName;
private String columnName;
}
Désormais, chaque type a les noms des champs d'origine de sa table. En conséquence, la méthode de création d'une description devient :
private static final String CREATE_RELATION_WITH_SERVICE = "INSERT INTO %s(language_id, %s, description) VALUES (?, ?, ?)";
public void createDescriptionForElement(ServiceType type, Long languageId, Long serviceId, String description) {
jdbcTemplate.update(String.format(CREATE_RELATION_WITH_SERVICE, type.getTableName(), type.getColumnName()), languageId, serviceId, description);
}
Pratique, simple et compact, vous ne trouvez pas ? L'indication d'un bon développeur n'est même pas la fréquence à laquelle il utilise des modèles, mais plutôt la fréquence à laquelle il évite les anti-modèles. L'ignorance est le pire ennemi, car vous devez connaître vos ennemis de vue. Eh bien, c'est tout ce que j'ai pour aujourd'hui. Merci tout le monde! :)
GO TO FULL VERSION