Contexte
Je ne suis pas un grand fan d'abstraction. J'admettrai que l'on peut bénéficier de l'adaptabilité, de la portabilité et de la réutilisation des interfaces, etc.
Il y a l'autre "avantage" majeur de l'abstraction, qui est de cacher la logique d'implémentation et les détails aux utilisateurs de cette abstraction. L'argument est que vous n'avez pas besoin de connaître les détails et que l'on devrait se concentrer sur leur propre logique à ce stade. Est logique en théorie.
Cependant, chaque fois que je gère des applications de grande entreprise, j'ai toujours besoin de plus de détails. Cela devient un énorme tracas de creuser de plus en plus profondément dans l'abstraction à chaque tour juste pour savoir exactement ce que fait quelque chose; c'est-à-dire avoir à faire une "déclaration ouverte" environ 12 fois avant de trouver la procédure stockée utilisée.
Cette mentalité de «cacher les détails» semble juste se mettre en travers. Je souhaite toujours des interfaces plus transparentes et moins d'abstraction. Je peux lire du code source de haut niveau et savoir ce qu'il fait, mais je ne saurai jamais comment il le fait, quand il le fait, c'est ce que j'ai vraiment besoin de savoir.
Que se passe t-il ici? Est-ce que tous les systèmes sur lesquels j'ai déjà travaillé sont mal conçus (du moins dans cette perspective)?
Ma philosophie
Lorsque je développe un logiciel, j'ai l'impression d'essayer de suivre une philosophie qui me semble étroitement liée à la philosophie ArchLinux :
Arch Linux conserve les complexités inhérentes à un système GNU / Linux, tout en les maintenant bien organisées et transparentes. Les développeurs et les utilisateurs d'Arch Linux pensent qu'essayer de cacher les complexités d'un système se traduit en fait par un système encore plus complexe et doit donc être évité.
Et donc, je n'essaye jamais de cacher la complexité de mon logiciel derrière des couches d'abstraction. J'essaie d'abuser de l'abstraction, pas d'en devenir l'esclave.
Question au coeur
- Y a-t-il une réelle valeur à cacher les détails?
- Ne sacrifions-nous pas la transparence?
- Cette transparence n'est-elle pas précieuse?
Réponses:
La raison pour cacher les détails n'est pas de garder les détails cachés; c'est pour permettre de modifier l'implémentation sans casser le code dépendant.
Imaginez que vous avez une liste d'objets et que chaque objet possède une
Name
propriété et d'autres données. Et souvent, vous devez trouver un élément dans la liste quiName
correspond à une certaine chaîne.La manière la plus évidente consiste à parcourir chaque élément un par un et à vérifier s'il
Name
correspond à la chaîne. Mais si vous trouvez que cela prend beaucoup trop de temps (comme si vous aviez plusieurs milliers d'éléments dans la liste), vous pourriez le remplacer par une recherche par dictionnaire d'objets chaîne.Maintenant, si toutes vos recherches ont été effectuées en récupérant la liste et en la parcourant, vous avez un énorme travail à faire pour résoudre ce problème. C'est encore plus difficile si vous êtes dans une bibliothèque et que des utilisateurs tiers l'utilisent; vous ne pouvez pas sortir et réparer leur code!
Mais si vous aviez une
FindByName
méthode pour encapsuler le processus de recherche de nom, vous pouvez simplement changer la façon dont il est implémenté et tout le code qui l'appelle continuera de fonctionner, et sera beaucoup plus rapide et gratuit. C'est la vraie valeur de l'abstraction et de l'encapsulation.la source
Je viens de terminer la lecture de la section Code complet sur l'abstraction, c'est donc là que la plupart de ces sources.
Le point d'abstraction est de supprimer la nécessité de demander "comment est-ce mis en œuvre?". Lorsque vous appelez
user.get_id()
, vous savez queid
c'est ce que vous allez récupérer. Si vous devez demander "comment cela obtient-il l'ID utilisateur?" alors vous n'avez probablement pas besoin d'unid
ouget_id()
retourne quelque chose d'inattendu et de mal conçu.Vous utilisez l'abstraction pour vous permettre de concevoir:
pas de conception
la source
Oui. En présentant des abstractions, nous pouvons penser et programmer à un niveau supérieur.
Imaginez modéliser des systèmes physiques sans calcul ni algèbre matricielle. C'est complètement impraticable. De même, si nous ne pouvons programmer qu'à un niveau scalaire, nous ne pourrons pas résoudre des problèmes intéressants. Même des applications Web relativement simples peuvent grandement bénéficier d'abstractions telles que les bibliothèques de balises. Il est beaucoup plus facile d'insérer une balise qui signifie «champs de saisie d'adresse» que de créer à plusieurs reprises quatre champs de texte et une zone de sélection. Et si vous décidez de vous développer à l'étranger, vous pouvez simplement modifier la définition de la balise, plutôt que de corriger chaque formulaire pour gérer les adresses internationales. L'utilisation efficace de l'abstraction est ce qui rend certains programmeurs dix fois plus efficaces que d'autres.
Les humains ont une mémoire de travail limitée. L'abstraction nous permet de raisonner sur les grands systèmes.
Non. Si les abstractions ne sont pas utilisées, le but d'un composant logiciel est enfoui dans des détails répétés. Les développeurs passent leurs journées à parcourir le code comme ceci:
et penser "oh oui une autre boucle à quatre niveaux sur les kits", au lieu de voir
Comme vous l'avez souligné, l'indirection a un coût. Il est inutile de créer des calques "au cas où". Utilisez l'abstraction pour réduire la duplication et clarifier le code.
la source
Quand les gens disent que les abstractions cachent les détails de l'implémentation, cela ne signifie pas réellement "cacher" dans le sens où il est difficile à trouver. Ce qu'ils signifient, c'est séparer les détails d'implémentation de l'interface publique, pour garder l'interface simple, concise et gérable. Tout comme une voiture "cache" la plupart de ses parties vitales, et n'offre qu'un ensemble de commandes assez rudimentaire pour les faire fonctionner, un module logiciel "cache" la plupart de ses fonctionnalités au fond de ses entrailles et n'expose qu'un nombre limité de méthodes d'accès à conduit le. Imaginez une voiture où vous deviez faire fonctionner manuellement tous les composants internes du moteur (et il y en a beaucoup), vous auriez vraiment du mal à garder un œil sur la circulation et à trouver le chemin.
Mais garder l'interface simple n'est pas simplement une chose esthétique; cela peut faire la différence entre un projet réussi et une marche de la mort. Jouons l'avocat du diable pendant une minute; imaginez un projet logiciel sans aucune abstraction. Si vous devez conserver une valeur, vous utilisez une variable globale. Si vous devez utiliser plusieurs fois la fonctionnalité, vous la copiez-collez. Si vous avez besoin de deux versions différentes d'une certaine section de code, vous copiez-collez, encapsulez-la dans une
if
instruction et modifiez les deux branches. Techniquement parlant, cela fonctionne, mais quelques mois plus tard, vous allez vous battre contre quelques problèmes vraiment désagréables:Dans une base de code mal abstraite, l'impact augmente généralement de façon exponentielle avec la taille de la base de code, c'est-à-dire que l'ajout d'une quantité constante de code augmente l'effort de maintenance d'un facteur constant. Pour aggraver les choses, l'ajout de programmeurs à un projet n'augmente pas la productivité de manière linéaire, mais au mieux logarithmique (car plus votre équipe est grande, plus la charge nécessaire pour la communication est importante).
la source
Je pense que vous devriez comprendre comment cela fonctionne si nécessaire. Une fois que vous avez déterminé qu'il fait ce que vous pensiez qu'il ferait, alors vous avez la tranquillité d'esprit. Je n'ai jamais pensé que le but était de le cacher à jamais.
Une fois que vous avez réglé une alarme sur une horloge dont vous êtes certain qu'elle fonctionnera, vous pouvez dormir un peu en sachant qu'elle se déclenchera au moment correct. Se réveiller une heure plus tôt pour pouvoir regarder les secondes défiler est un gaspillage.
la source
Pour répondre spécifiquement à vos questions:
Oui. Comme vous le reconnaissez dans la première ligne de votre question.
Pas vraiment. Une abstraction bien écrite facilitera la compréhension des détails si nécessaire.
Oui. Les abstractions doivent être conçues et mises en œuvre pour faciliter la compréhension des détails lorsque cela est nécessaire / souhaité.
la source
Je dirais que cacher les détails est génial lorsque les choses cachées fonctionnent.
Par exemple, supposons que nous développions une interface qui définit les comportements (c.-à-d. GetListItems, SendListItem), qui sont deux fonctionnalités qui sont lancées par l'utilisateur via un clic sur un bouton ou quelque chose comme ça. MAINTENANT, chaque utilisateur peut avoir son propre "ListItemStore". l'un sur Facebook, ceux sur myspace .. (par exemple) .. et dire qu'il est enregistré en tant que propriété / paramètre utilisateur quelque part dans l'application via les préférences utilisateur .. et dire qu'il est possible pour les développeurs d'applications d'ajouter des ListItemStore supplémentaires au cours de temps (mybook, facespace, etc.)
maintenant, il y a beaucoup de détails pour se connecter à Facebook et obtenir des articles .. et il y a autant de détails lors de la connexion à myspace .. et ainsi de suite ...
maintenant, après l'écriture du code "d'accès au magasin" initial, il n'est peut-être pas nécessaire de le modifier (enfin dans le cas de facebook, nous avons probablement besoin d'un développeur à temps plein pour suivre les changements, zing ..),
donc quand vous utilisez le code, c'est quelque chose comme:
et maintenant vous avez les données de l'Utilisateur de l'endroit où elles les ont stockées, et puisque tout ce qui m'inquiète, c'est d'obtenir la liste des éléments et de faire quelque chose avec, et comme cela n'a pris que 2 lignes qui fonctionneront, peu importe comment beaucoup plus de magasins sont ajoutés je peux revenir à répondre / poster des questions sur la pile ... lol ..
Donc, toute la plomberie pour y arriver est "cachée" et qui se soucie vraiment de la façon dont elle le fait tant que j'obtiens la bonne liste d'articles. Si vous avez des tests unitaires, vous pouvez même vous reposer plus facilement car les résultats devraient ' ont déjà été quantifiés ..
la source
Ce que vous appelez «cacher», beaucoup le voient comme une séparation des préoccupations (par exemple, mise en œuvre vs interface).
À mon avis, un avantage majeur de l'abstraction est de réduire l'encombrement des détails inutiles de l'espace cérébral limité du développeur.
Si le code d'implémentation était obscurci, je pourrais voir cela comme un obstacle à la transparence, mais l'abstraction telle que je la vois, est juste une bonne organisation.
la source
Tout d'abord, tout ce qui dépasse une seule instruction de code machine est essentiellement une abstraction - une
while...do
boucle est un moyen symbolique cohérent de représenter les comparaisons et les appels d'adresse requis pour répéter un ensemble d'instructions jusqu'à ce qu'une condition soit remplie. De même, le type int est une abstraction pour X nombre de bits (selon votre système). La programmation est une question d'abstraction.Vous conviendrez probablement que ces abstractions primitives sont très utiles. Eh bien, c'est aussi la possibilité de construire le vôtre. OOAD et OOP sont tout au sujet.
Supposons que vous ayez une exigence où les utilisateurs veulent pouvoir exporter les données d'un écran dans une variété de formats: texte délimité, Excel et PDF. N'est-il pas pratique que vous puissiez créer une interface appelée "Exporter" avec une méthode d'exportation (données), sur la base de laquelle vous pouvez créer un DelimitedTextExporter, un ExcelExporter et un PDFExporter, chacun sachant comment créer sa sortie particulière? Tout ce que le programme appelant doit savoir, c'est qu'il peut appeler la méthode d'exportation (données), et quelle que soit l'implémentation utilisée, elle fera l'affaire. De plus, si les règles de texte délimité changent, vous pouvez modifier le DelimitedTextExporter sans avoir à jouer avec ExcelExporter, voire le casser.
Presque tous les modèles de conception bien connus utilisés dans la programmation OO dépendent de l'abstraction. Je recommanderais de lire Freeman et les modèles de conception Head First de Freeman pour mieux comprendre pourquoi l'abstraction est une bonne chose
la source
Je pense que je comprends votre sentiment à ce sujet, et je pense avoir une opinion similaire.
J'ai travaillé avec des développeurs Java qui transforment 50 classes de ligne de code en 3 classes et 3 interfaces car c'est facile à comprendre. Et je ne pouvais pas le supporter.
La chose était terriblement difficile à comprendre, presque impossible à déboguer et n'avait jamais eu besoin de "changer d'implémentation".
D'un autre côté, j'ai également vu du code où plusieurs objets partagent un comportement similaire et sont utilisés au même endroit, et pourraient vraiment utiliser des boucles de tri / traitement communes si les méthodes auraient été exposées via une interface commune.
Ainsi, à mon humble avis, les objets principaux qui sont susceptibles d'être utilisés dans des scénarios similaires bénéficient généralement d'un comportement commun qui devrait être accessible via l'interface. Mais c'est à peu près tout, abstraire des choses simples parce que c'est vrai, ou permet de changer d'implémentation est juste un moyen de rendre le code désordonné.
Là encore, je préfère des classes plus intelligentes plus longues à une quantité explosive de petites classes avec tous les problèmes de gestion de la vie, et des relations difficiles à voir et des graphiques d'appels de spaghetti. Donc, certaines personnes seront en désaccord avec moi.
la source
L'objectif caché de la dissimulation et de l'abstraction devrait être de découpler l'utilisateur de la mise en œuvre afin qu'ils puissent être modifiés indépendamment.Si le consommateur est associé aux détails de la mise en œuvre, en raison de la manipulation de leurs composants internes, les deux sont coulés dans la pierre et il devient plus difficile d'introduire de nouvelles fonctionnalités ou de meilleurs algorithmes à l'avenir.
Lors de l'écriture d'un module, les parties cachées de l'implémentation vous donnent la tranquillité d'esprit de pouvoir les modifier sans risquer de casser un autre code auquel vous ne pouvez pas penser.
Un autre avantage de fournir des interfaces opaques est qu'elles réduisent considérablement la surface entre les sous-systèmes. En réduisant la quantité de façons dont ils peuvent interagir, ils peuvent devenir plus prévisibles, plus faciles à tester et avoir moins de bogues. Les interactions entre les modules augmentent également de façon quadratique avec le nombre de modules, il est donc utile d'essayer de contrôler cette croissance de complexité.
Cela dit, il est bien sûr possible d'en cacher trop et d'imbriquer les interfaces trop profondément. C'est le travail du programmeur, en tant qu'être humain intelligent, de concevoir le système afin qu'il soit extrêmement utile tout en minimisant la complexité et en maximisant la maintenabilité.
la source
Dans de nombreux cas, vous n'avez tout simplement pas besoin de savoir comment les choses sont mises en œuvre. Je peux presque garantir que vous écrirez du code comme celui-ci
people.Where(p => p.Surname == "Smith")
tant de fois par jour, mais vous ne penserez presque jamais "comment cetteWhere()
méthode fonctionne-t-elle réellement?" Vous ne vous en souciez pas - vous savez que cette méthode est là et qu'elle vous donne les résultats que vous souhaitez. Pourquoi voudriez-vous savoir comment cela fonctionne?C'est exactement la même chose pour tout logiciel interne; ce n'est pas parce qu'il n'est pas écrit par Oracle, Microsoft, etc. que vous devriez avoir à chercher comment il est implémenté. Vous pouvez raisonnablement vous attendre à ce qu'une méthode appelée
GetAllPeopleWithSurname(string name)
vous renvoie une liste de personnes qui portent ce nom de famille. Il peut parcourir une liste, il peut utiliser un dictionnaire, il peut faire quelque chose de complètement fou, mais vous ne devriez pas vous en soucier .Il y a bien sûr une exception à cette règle (ce ne serait pas une règle sans elle!) Et c'est s'il y a un bug dans la méthode. Donc, dans l'exemple ci-dessus, si vous avez une liste avec 3 personnes et que vous savez que l'un d'eux a le nom de famille Smith et qu'ils ne sont pas retournés dans la liste, alors vous vous souciez de la mise en œuvre de cette méthode car elle est clairement cassée .
L'abstraction, lorsqu'elle est effectuée correctement, est merveilleuse car elle vous permet de filtrer tout ce qui n'est pas utile lorsque vous devez le lire à une date ultérieure. N'oubliez pas que vous passez beaucoup plus de temps à lire du code qu'à l'écrire, l'accent doit donc être mis sur la simplification de cette tâche. Vous pensez peut-être aussi que l'abstraction signifie une hiérarchie d'objets aussi longtemps que votre bras, mais cela peut être aussi simple que de refactoriser une méthode de 100 lignes en 10 méthodes, chacune de 10 lignes de long. Donc, ce qui était autrefois 10 étapes regroupées est maintenant 10 étapes distinctes vous permettant d'aller directement à l'endroit où se cache ce bug embêtant.
la source
PeopleFactory.People.Strategy.MakePeople.(CoutryLaw.NameRegistry.NameMaker.Make()) as People.Female
Les abstractions entraînent la dissimulation d'informations. Cela devrait se retrouver dans l'accouplement inférieur. Cela devrait entraîner moins de risques de changement. Cela devrait conduire les programmeurs heureux à ne pas devenir nerveux en touchant le code.
Ces idées s'expriment à travers trois lois essentielles de l'architecture logicielle:
La loi de Simon: "Les hiérarchies réduisent la complexité." (Les hiérarchies introduisent l'abstraction)
La loi de Parna: "Seul ce qui est caché peut être changé sans risque."
Loi de Constantin: les programmes robustes nécessitent un faible couplage et une forte cohésion
la source
Je suis également dans le domaine des applications d'entreprise, et cette question a attiré mon attention parce que j'ai la même question moi-même. J'ai eu un aperçu de la question de l'abstraction au cours de ma carrière jusqu'à présent, mais mon aperçu n'est en aucun cas la réponse universelle. Je continue à apprendre / écouter de nouvelles idées et pensées, donc ce que je crois maintenant peut changer.
Lorsque je maintenais une application de soins de santé vaste et complexe, juste comme vous, je détestais toutes les abstractions là-bas. Déterminer où va tout le code était une douleur dans le cou. Sauter dans différentes classes m'a donné le vertige. Alors je me suis dit "l'abstraction craint, je minimiserai l'abstraction quand je crée des trucs".
Ensuite, il est venu le temps de concevoir une application (composant de service Web relativement petit) à partir de zéro. En me souvenant de toute la douleur, j'avais une conception assez plate du composant. Le problème était que lorsque les exigences changeaient, je devais changer à de nombreux endroits différents (les exigences étaient assez fluides et je ne pouvais rien y faire). C'était tellement mauvais, j'ai essentiellement abandonné ma conception initiale et ma re-conception avec l'abstraction, et les choses se sont améliorées - je n'ai plus eu à apporter de modifications à de nombreux endroits lorsque les exigences ont changé.
J'ai livré l'application, je me suis assis pendant quelques semaines, puis on m'a dit de commencer à maintenir l'application. Cela faisait un moment que je ne me souvenais pas de tout, j'ai donc lutté un peu pour comprendre mon propre code, et l'abstraction n'aidait pas.
J'ai ensuite été mis sur de nombreux autres projets différents et j'ai eu la chance de jouer avec les niveaux d'abstraction un peu plus. Ce que je trouve en fait, et ce n'est que mon opinion personnelle, l'abstraction aide beaucoup au développement mais a un impact négatif lorsque vous n'avez pas écrit le code et essayez de tout comprendre au niveau le plus profond d'une application; vous passerez plus de temps à sauter dans différentes classes et à essayer de faire le lien.
Mon sentiment est que l'abstraction est si précieuse pendant le temps de développement que le problème que nous traversons en tant que responsable en essayant de comprendre le code en vaut la peine. Les logiciels existent pour résoudre les problèmes commerciaux, les problèmes commerciaux évoluent avec le temps; par conséquent, le logiciel doit évoluer au fil du temps. Sans abstraction, l'évolution du logiciel est très difficile. On peut concevoir l'abstraction de manière à ce que le responsable puisse naviguer facilement dans la base de code une fois qu'il a vu le modèle de la structure du code, de sorte que seule la courbe d'apprentissage initiale est frustrante.
la source
Comme d'autres l'ont dit, «cacher des détails» derrière une abstraction permet de les modifier sans affecter les utilisateurs. Cette idée vient de Parnas ' On the Criteria to be used in Decomposing Systems Into Modules (1972) , et est liée à l'idée de types de données abstraits (ADT) et de programmation orientée objet.
À peu près à la même époque, Un modèle relationnel de données de Codd pour les grandes banques de données partagées (1970) était motivé (voir le résumé et l'intro) en voulant changer la représentation de stockage interne des bases de données, sans affecter les utilisateurs de la base de données. Il avait vu des programmeurs prendre régulièrement des jours, modifiant des pages de code, pour faire face à des changements de stockage mineurs.
Cela dit, une abstraction n'est pas très utile si vous devez voir ce qu'elle contient pour pouvoir l'utiliser. Il peut être très difficile de bien le concevoir. Un exemple d'une bonne abstraction est l'addition - à quand remonte la dernière fois où vous avez dû penser à ce qui se passe à l'intérieur? (mais parfois vous le faites, par exemple pour un débordement).
Le problème essentiel (à mon humble avis) est que pour bien concevoir les modules (au sens de Parnas), vous devez prévoir ce qui changera et ce qui ne changera pas. Il est difficile de prédire l'avenir - mais si vous avez beaucoup d'expérience avec quelque chose et que vous le comprenez clairement, vous pouvez faire un très bon travail de prévision. Et par conséquent, vous pouvez concevoir un module (abstraction) qui fonctionne bien.
Cependant, il semble que le sort de toutes les abstractions - même les meilleures - que finalement il y aura des changements imprévus (et sans doute, imprévisibles) qui nécessitent de briser l'abstraction. Pour résoudre ce problème, certaines abstractions ont un échappement, où vous pouvez accéder à un niveau plus profond si vous en avez vraiment besoin.
Tout cela semble très négatif. Mais je pense que la vérité est que nous sommes entourés d'abstractions qui fonctionnent si bien que nous ne les remarquons pas ou ne réalisons pas ce qu'elles cachent. Nous ne remarquons que les pauvres abstractions, nous en avons donc une vue jaunie.
la source
Les abstractions sont principalement à l'avantage de leurs consommateurs (par exemple, les programmeurs d'applications). Les programmeurs système (concepteurs) ont plus de travail à faire pour les rendre beaux et utiles, c'est pourquoi un bon design n'est généralement pas fait par les débutants.
Peut-être que vous n'aimez pas les abstractions car elles ajoutent toujours de la complexité? Peut-être que les systèmes sur lesquels vous avez travaillé avaient une abstractionite (surutilisation d'abstractions)? Ce n'est pas une panacée.
Le travail supplémentaire et la complexité d'une abstraction utile devraient porter leurs fruits, mais il est difficile de le savoir avec certitude. Si vous considérez une abstraction comme un point pivot, la conception du logiciel peut fléchir de chaque côté: les implémentations de l'abstraction peuvent être modifiées sans casser le code client, et / ou de nouveaux clients peuvent facilement réutiliser l'abstraction pour faire de nouvelles choses.
Vous pourriez presque mesurer le retour sur investissement des abstractions en montrant qu'elles ont été "fléchies" au fil du temps dans l'une ou les deux directions: changements de mise en œuvre relativement indolores et nouveaux clients supplémentaires.
Par exemple: en utilisant l'abstraction de la classe Socket en Java, je suis sûr que mon code d'application de Java 1.2 fonctionne toujours bien sous Java 7 (bien que leurs performances puissent être modifiées). Depuis Java 1.2, il y a certainement eu beaucoup de nouveaux clients qui ont également utilisé cette abstraction.
En ce qui concerne le mécontentement des abstractions, si je parlais aux développeurs qui ont maintenu le code derrière la classe Socket, leur vie n'est peut-être pas aussi peachy et rose que les clients qui ont utilisé Socket pour écrire des applications amusantes. Travailler sur la mise en œuvre d'une abstraction est certainement plus de travail que de l'utiliser. Mais cela ne fait pas de mal.
En ce qui concerne la transparence, dans une stratégie de conception descendante, une transparence totale entraîne une mauvaise conception. Les programmeurs intelligents ont tendance à tirer le meilleur parti des informations dont ils disposent, et le système devient alors étroitement couplé. Le plus petit changement de détail (par exemple, changer l'ordre des octets dans une structure de données) dans un module peut casser du code ailleurs, car un programmeur intelligent a utilisé ces informations pour faire quelque chose d'utile. David Parnas a souligné ce problème dans des articles datant de 1971 où il proposait de cacher des informations dans les dessins.
Votre référence à ArchLinux a du sens pour moi si vous considérez "l'intérieur" du système d'exploitation comme étant l'implémentation complexe de l'abstraction que sont l'OS des applications qui s'exécutent dessus. Restez simple dans les entrailles de l'abstraction.
la source
Je répondrai à votre question par une question; lorsque vous avez conduit au travail ce matin (je suppose que vous l'avez fait en fait), vous êtes-vous soucié exactement de la façon dont le moteur a ouvert les soupapes pour laisser entrer les mélanges air-carburant, puis les a allumées? Non. Vous ne vous souciez pas du fonctionnement du moteur de votre voiture lorsque vous conduisez sur la route. Vous souciez qu'il fait le travail.
Supposons qu'un jour votre voiture ne fonctionne pas. Ne démarre pas, lance une tige, brise une ceinture, laboure inexplicablement cette barrière de béton sans aucune faute de votre part pendant que vous étiez occupé à envoyer des SMS. Maintenant, vous avez besoin d'une nouvelle voiture (au moins temporairement). Vous souciez-vous exactement du fonctionnement de cette nouvelle voiture? Non. Ce qui vous importe, c'est d'abord que cela fonctionne, et deuxièmement que vous pouvez utiliser les mêmes connaissances et compétences que vous avez utilisées pour conduire votre ancienne voiture pour conduire la nouvelle. Idéalement, il devrait vous sembler qu'il n'y a eu aucun changement dans la voiture que vous conduisez. De façon réaliste, le fonctionnement de cette nouvelle voiture devrait vous donner le moins de "surprises" possible.
Ces principes de base sont le principe de base derrière l'encapsulation et l'abstraction. La connaissance de la façon dont un objet fait ce qu'il fait ne devrait pas être une condition préalable à son utilisation pour faire ce qu'il fait. Même en programmation informatique, les détails des chemins électriques au sein du CPU exécutant votre programme sont résumés derrière au moins une demi-douzaine de couches d'instructions d'E / S, de pilotes, de logiciels OS et d'exécution. De nombreux ingénieurs logiciels très performants écrivent du bon code sans se soucier une seule fois de l'architecture matérielle exacte, ni même de la construction du système d'exploitation, qui l'exécutera. Y compris moi.
L'encapsulation / la dissimulation de l'information permet à la mentalité de "ne pas se soucier de la façon dont elle le fait, juste de s'en soucier". Votre objet doit exposer ce qui est utile au consommateur, d'une manière que le consommateur puisse facilement consommer. Maintenant, dans le monde réel, cela ne signifie pas qu'une voiture ne devrait pas donner à l'utilisateur des informations sur le fonctionnement interne, ou que la voiture ne devrait permettre à l'utilisateur que les fonctionnalités les plus élémentaires comme l'allumage, le volant, et pédales. Toutes les voitures ont des compteurs de vitesse et des jauges de carburant, des tachymètres, des lumières idiotes et d'autres commentaires. Pratiquement toutes les voitures ont également des commutateurs pour divers sous-systèmes indépendants, tels que les phares, les clignotants, la radio, le réglage des sièges, etc. Certaines voitures permettent une entrée utilisateur assez ésotérique, comme la sensibilité du différentiel central à glissement limité. Dans tous les cas, si vous en savez assez, vous pouvez l'ouvrir et changer les choses pour le faire fonctionner d'une manière légèrement différente. Mais, dans la plupart des cas, peut-être, juste peut-être, l'utilisateur ne devrait pas être en mesure de contrôler directement et indépendamment les pompes à carburant de l'intérieur de la cabine? Peut-être, juste peut-être, que l'utilisateur ne devrait pas être en mesure d'activer ses feux de freinage sans appuyer sur la pédale de frein?
L'abstraction permet la mentalité "ce n'est pas la même chose que cela, mais parce qu'ils sont tous les deux XI, je peux les utiliser comme je le ferais avec n'importe quelle mentalité X". Si votre objet hérite ou implémente une abstraction, vos consommateurs doivent s'attendre à ce que votre implémentation produise le même résultat ou un résultat similaire à d'autres implémentations connues de l'abstraction. Une Toyota Camry et une Ford Fusion sont toutes deux des «voitures». En tant que tels, ils ont un ensemble commun de fonctionnalités attendues, comme un volant. Tournez-le dans le sens antihoraire, la voiture va à gauche. Tournez-le dans le sens des aiguilles d'une montre, la voiture va à droite. Vous pouvez monter dans n'importe quelle voiture aux États-Unis et vous attendre à ce que la voiture ait un volant et au moins deux pédales, celle de droite étant la pédale "car go" et celle du centre étant la pédale "car stops" .
Un corollaire de l'abstraction est la "théorie du moindre étonnement". Si vous preniez le volant d'une nouvelle voiture pour un essai routier, tourniez le volant dans le sens des aiguilles d'une montre et que la voiture tournait à gauche, vous seriez assez étonné pour le moins. Vous accuseriez le revendeur de colporter un point de vente et vous auriez peu de chances d'écouter l'une de ses raisons pour lesquelles le nouveau comportement est "meilleur" que ce à quoi vous êtes habitué, ou si ce comportement est "documenté" ou comment " transparent "est le système de contrôle. Malgré cette nouvelle voiture et toutes les autres que vous avez conduites étant toujours des "voitures", lorsque vous conduisez cette voiture, vous devez changer certains concepts fondamentaux de la façon dont une voiture est censée être conduite afin de conduire la nouvelle voiture avec succès. C'est généralement une mauvaise chose, et cela ne se produit que lorsqu'il y a un avantage intuitif au nouveau paradigme. L'ajout de ceintures de sécurité est peut-être un bon exemple; Il y a 50 ans, vous venez de monter et de partir, mais maintenant vous devez boucler votre ceinture, l'avantage intuitif étant que vous ne passez pas par le pare-brise ou sur le siège passager en cas d'accident. Même alors, les conducteurs ont résisté; de nombreux propriétaires de voitures ont coupé les ceintures de sécurité de la voiture jusqu'à l'adoption de lois rendant leur utilisation obligatoire.
la source