Je lisais aujourd'hui un livre intitulé "Code propre" et je suis tombé sur un paragraphe où l'auteur parlait des niveaux d'abstraction par fonction, il a classé certains codes en niveaux d'abstraction faible / intermédiaire / élevé.
Ma question est: quels sont les critères pour déterminer le niveau d’abstraction?
Je cite le paragraphe du livre:
Afin de nous assurer que nos fonctions font «une chose», nous devons nous assurer que les déclarations de notre fonction ont toutes le même niveau d'abstraction. Il est facile de voir en quoi Listing 3-1 enfreint cette règle. Il y a des concepts à un très haut niveau d'abstraction, tels que getHtml (); d'autres qui sont à un niveau d'abstraction intermédiaire, tels que: String pagePathName = PathParser.render (pagePath); et d'autres encore qui sont remarquablement bas, tels que: .append ("\ n").
la source
Réponses:
L'auteur explique que, dans la sous-section "Lecture du code de haut en bas" de la partie qui traite des abstractions (mien d'indentation hiérarchique):
Le code qui irait avec ceci ressemblerait à ceci:
Etc. Chaque fois que vous approfondissez la hiérarchie des fonctions, vous devez modifier les niveaux d'abstraction. Dans l'exemple ci - dessus,
IncludeSetups
,IncludeTestPageContent
etIncludeTeardowns
sont tous au même niveau d'abstraction.Dans l'exemple donné dans le livre, l'auteur suggère que la grande fonction devrait être divisée en de plus petites fonctions très spécifiques qui ne font qu'une chose. Si cela est fait correctement, la fonction refactorisée ressemblerait aux exemples ici. (La version refactorisée est donnée dans l'extrait 3-7 du livre.)
la source
Je pense que pour comprendre cette question, il faut comprendre ce qu'est une abstraction. (Je suis trop paresseux pour trouver une définition formelle, donc je suis sur le point de m'énerver, mais voilà ...) Une abstraction est quand vous prenez un sujet complexe ou une entité et cachez la plupart de ses détails tout en exposant la fonctionnalité qui définit toujours l'essence de cet objet.
Je crois que l'exemple que le livre vous a donné était une maison. Si vous jetez un coup d'oeil très détaillé à la maison, vous verrez qu'elle est faite de planches, de clous, de fenêtres, de portes ... Mais le dessin humoristique d'une maison à côté d'une photo est toujours une maison, même s'il en manque beaucoup de ces détails.
Même chose avec un logiciel. Comme vous le recommandez, chaque fois que vous programmez, vous devez considérer votre logiciel sous forme de couches. Un programme donné peut facilement comporter plus d'une centaine de couches. En bas, vous pouvez avoir des instructions d'assemblage qui s'exécutent sur un processeur. À un niveau supérieur, ces instructions peuvent être combinées pour former des routines d'E / S de disque. À un niveau encore supérieur, vous n'avez pas besoin de travailler avec Disk I / O directement parce que vous pouvez utiliser les fonctions Windows pour simplement ouvrir / lire / écrire / chercher / fermer un fichier. Ce sont toutes des abstractions avant même que vous obteniez votre propre code d'application.
Dans votre code, les couches d'abstraction continuent. Vous pourriez avoir des routines de niveau inférieur / réseau / manipulations de données. À un niveau supérieur, vous pouvez combiner ces routines en sous-systèmes définissant la gestion des utilisateurs, la couche d'interface utilisateur et l'accès à la base de données. Encore une autre couche, ces sous-systèmes peuvent être combinés dans des composants de serveur qui s’unissent pour faire partie d’un système plus vaste.
La clé de chacune de ces couches d'abstraction est que chacune d'elles cache les détails exposés par la ou les couches précédentes et présente une interface très propre à utiliser par la couche suivante. Pour ouvrir un fichier, vous ne devriez pas avoir besoin de savoir comment écrire des secteurs individuels ni quelles interruptions matérielles traiter. Mais si vous commencez à voyager le long de la chaîne de la couche d'abstraction, vous serez certainement en mesure de tracer depuis l'appel de la fonction Write () jusqu'à l'instruction exacte envoyée au contrôleur de disque dur.
Ce que l’auteur vous dit de faire, c’est que lorsque vous définissez une classe ou une fonction, réfléchissez à la couche que vous êtes. Si vous avez une classe qui gère des sous-systèmes et des objets utilisateur, la même classe ne doit pas effectuer de manipulation de chaîne de bas niveau ni contenir un grand nombre de variables uniquement pour effectuer des appels de socket. Cela constituerait une violation des couches d'abstraction croisées et le fait d'avoir une classe / fonction ne ferait qu'une chose (PRS - Principe de responsabilité unique).
la source
Le niveau d'abstraction est censé être évident. C'est abstrait si cela fait partie du domaine du problème et non du langage de programmation. Il est difficile d’être plus clair que "hautement abstrait" == "pas réel" == "problème". Et "pas abstrait == concret == partie de la langue". C'est supposé être trivial de décider du niveau d'abstraction. Il ne doit y avoir aucune subtilité.
.append("\n")
n'est pas abstrait. Il met simplement un caractère sur une chaîne. Ce serait concret. Pas abstrait.String pagePathName = PathParser.render(pagePath);
traite des cordes. Des choses concrètes. En partie sur les fonctionnalités concrètes du langage de programmation. Utilisation partielle des concepts abstraits de "chemin" et de "parseur".getHtml();
Abstrait. Traite des "balises" et des choses qui ne sont pas triviales, concrètes, les fonctionnalités du langage.Résumé == pas une langue.
Concrete == une fonctionnalité de langue.
la source
Je pense que le niveau d'abstraction est simple ... Si la ligne de code n'implémente pas directement la responsabilité de la méthode, c'est un autre niveau d'abstraction. Par exemple, si mon nom de méthode est SaveChangedCustomers () et prend une liste de TOUS les clients en tant que paramètre, la seule responsabilité consiste à enregistrer tous les clients de la liste qui ont été modifiés:
Souvent, au lieu d'appeler la méthode CustomerIsChanged (), vous trouverez la logique permettant de déterminer si le client a été intégré dans la boucle foreach. Déterminer si la fiche client a changé n’est PAS la responsabilité de cette méthode! C'est un niveau d'abstraction différent. Mais que se passe-t-il si la logique pour prendre cette décision n’est qu’une ligne de code? Peu importe !!! C'est un niveau d'abstraction différent et doit être en dehors de cette méthode.
la source