web-dev-qa-db-fra.com

Signification de l'abstraction qui fuit?

Que signifie le terme "Abstraction Leaky"? (S'il vous plaît expliquer avec des exemples. J'ai souvent du mal à énoncer une simple théorie.)

63
Geonne

Voici un meatspace example:

Les automobiles ont des abstractions pour les conducteurs. Dans sa forme la plus pure, il existe un volant, un accélérateur et un frein. Cette abstraction cache beaucoup de détails sur ce qu'il y a sous le capot: moteur, cames, courroie de distribution, bougies d'allumage, radiateur, etc.

La particularité de cette abstraction est que nous pouvons remplacer des parties de l’implémentation par des parties améliorées sans requalifier l’utilisateur. Disons que nous remplaçons le capuchon du distributeur par un allumage électronique et que nous remplaçons la came fixe par une came variable. Ces modifications améliorent les performances, mais l'utilisateur continue de piloter avec le volant et utilise les pédales pour démarrer et arrêter.

C'est en fait assez remarquable ... un homme de 16 ans ou de 80 ans peut faire fonctionner cette machine complexe sans vraiment en savoir plus sur son fonctionnement à l'intérieur!

Mais il y a des fuites. La transmission est une petite fuite. Dans une boîte de vitesses automatique, vous pouvez sentir que la voiture perd un instant de la puissance en changeant de vitesse, alors que dans la CVT, vous ressentez un couple impeccable à fond.

Il y a aussi des fuites plus importantes. Si vous faites tourner le moteur trop vite, vous risquez de l'endommager. Si le bloc moteur est trop froid, la voiture peut ne pas démarrer ou ses performances peuvent être médiocres. Et si vous lancez la radio, les phares et la climatisation en même temps, votre consommation d'essence diminue.

79
Mark E. Haase

Cela signifie simplement que votre abstraction expose certains des détails de l'implémentation ou que vous devez être au courant des détails de l'implémentation lorsque vous utilisez l'abstraction. Le terme est attribué à Joel Spolsky , circa 2002. Voir le wikipedia article pour plus d’informations.

Un exemple classique sont les bibliothèques réseau qui vous permettent de traiter les fichiers distants comme locaux. Le développeur qui utilise cette abstraction doit être conscient du fait que des problèmes de réseau peuvent entraîner l'échec de cette opération, contrairement aux fichiers locaux. Vous devez ensuite développer du code pour traiter spécifiquement les erreurs en dehors de l'abstraction fournie par la bibliothèque réseau.

39
tvanfosson

Wikipedia a un très bonne définition pour cela 

Une abstraction qui fuit fait référence à toute abstraction implémentée, destinée à réduire (ou masquer) la complexité, lorsque les détails sous-jacents ne sont pas complètement masqués.

Ou, en d'autres termes, dans le cas d'un logiciel, vous pouvez observer les détails de la mise en œuvre d'une fonctionnalité via des limitations ou des effets secondaires dans le programme. 

Un exemple rapide serait les fermetures C #/VB.Net et leur incapacité à capturer les paramètres ref/out. La raison pour laquelle ils ne peuvent pas être capturés est due à un détail d'implémentation du processus de levage. Cela ne veut cependant pas dire qu'il existe un meilleur moyen de le faire. 

12
JaredPar

Voici un exemple familier pour les développeurs .NET: La classe Page d'ASP.NET tente de masquer les détails des opérations HTTP, en particulier la gestion des données de formulaire, afin que les développeurs n'aient pas à traiter les valeurs publiées (car elle mappe automatiquement les valeurs de formulaire sur commandes du serveur).

Mais si vous vous écartez des scénarios d'utilisation les plus élémentaires, l'abstraction Page commence à couler et il devient difficile de travailler avec des pages à moins de comprendre les détails d'implémentation de la classe.

Un exemple courant est l'ajout dynamique de contrôles à une page - la valeur des contrôles ajoutés dynamiquement ne sera mappée que si vous les ajoutez à juste au bon moment: avant que le moteur sous-jacent mappe les valeurs de formulaire entrantes. aux contrôles appropriés. Lorsque vous devez apprendre cela, l'abstraction a fuite.

11
Jeff Sternal

Eh bien, d’une certaine manière, c’est une chose purement théorique, mais non sans importance.

Nous utilisons des abstractions pour rendre les choses plus faciles à comprendre. Je peux utiliser une classe de chaîne dans certaines langues pour masquer le fait que je traite un ensemble ordonné de caractères qui sont des éléments individuels. Je traite un ensemble ordonné de caractères pour cacher le fait que je traite avec des nombres. Je traite avec des nombres pour cacher le fait que je traite avec des 1 et des 0.

Une abstraction qui fuit n’est pas celle qui cache les détails qu’elle est censée cacher. Si vous appelez string.Length sur une chaîne de 5 caractères en Java ou .NET, je pourrais obtenir une réponse de 5 à 10, en raison de détails d’implémentation dans lesquels les caractères d’appel de ces langages sont réellement des points de données UTF-16 pouvant représenter 1 ou .5 d'un personnage. L'abstraction a coulé. Ne pas la laisser couler signifie cependant que trouver la longueur nécessiterait plus d’espace de stockage (pour stocker la longueur réelle) ou passerait de O(1) à O(n) (travailler). quelle est la longueur réelle). Si je me soucie de la vraie réponse (souvent vous ne le faites pas vraiment), vous devez travailler sur la connaissance de ce qui se passe réellement.

Des cas plus discutables se produisent dans des cas tels que lorsqu'une méthode ou une propriété vous laisse pénétrer dans le fonctionnement interne, qu'il s'agisse de fuites d'abstraction ou de moyens bien définis pour passer à un niveau d'abstraction inférieur, peuvent parfois être un sujet de désaccord.

7
Jon Hanna

Je vais continuer dans la veine de donner des exemples en utilisant RPC.

Dans le monde idéal de RPC, un appel de procédure à distance doit ressembler à un appel de procédure local (ou du moins l’histoire va). Cela devrait être complètement transparent pour le programmeur, de telle sorte que lorsqu'il appelle SomeObject.someFunction(), il ne sache pas si SomeObject (ou simplement someFunction) est stocké et exécuté localement ou stocké et exécuté à distance. La théorie veut que cela simplifie la programmation.

La réalité est différente car il existe une énorme différence entre émettre un appel de fonction local (même si vous utilisez le langage interprété le plus lent au monde) et:

  • appeler via un objet proxy
  • sérialiser vos paramètres
  • établir une connexion réseau (si pas déjà établie)
  • transmission des données au proxy distant
  • avoir le proxy distant restaurer les données et appeler la fonction distante en votre nom
  • sérialiser les valeurs de retour
  • transmission des valeurs de retour au proxy local
  • réassemblage des données sérialisées
  • renvoyer la réponse de la fonction distante

En temps seul, cela représente environ trois ordres (ou plus!) De différence de magnitude. Ces trois ordres de grandeur vont faire une énorme différence de performances, ce qui fera que votre abstraction d’une fuite d’appel de procédure fuit de manière assez évidente la première fois que vous traitez par erreur un RPC comme un véritable appel de fonction. En outre, un véritable appel de fonction, à moins de problèmes graves dans votre code, comportera très peu de points d’échec en dehors des erreurs d’implémentation. Un appel RPC présente tous les problèmes possibles suivants qui seront traités comme des cas d'échec, au-delà de ce que vous attendez d'un appel local normal:

  • vous ne pourrez peut-être pas instancier votre proxy local
  • vous ne pourrez peut-être pas instancier votre proxy distant
  • les mandataires peuvent ne pas être en mesure de se connecter
  • les paramètres que vous envoyez peuvent ne pas le rendre intact ou pas du tout
  • la valeur de retour envoyée par la télécommande peut ne pas la rendre intacte ou pas du tout

Alors maintenant, votre appel RPC qui est "exactement comme un appel de fonction locale" a tout un tas de défaillances supplémentaires que vous n’aurez pas à affronter lors de vos appels de fonction locaux. L'abstraction a encore fui, encore plus fort.

En fin de compte, le RPC est une mauvaise abstraction car il fuit comme un tamis à tous les niveaux - en cas de succès et en cas d'échec des deux.

Exemple dans Exemple Django ORM plusieurs-à-plusieurs :

Remarquez dans l'exemple d'utilisation de l'API que vous avez besoin de .save () l'objet Article de base a1 avant de pouvoir ajouter des objets de publication à l'attribut plusieurs-à-plusieurs. Et notez que la mise à jour de l'attribut many-to-many est immédiatement sauvegardée dans la base de données sous-jacente, tandis que la mise à jour d'un attribut singulier n'est pas reflétée dans la base de données jusqu'à ce que le .save () soit appelé. 

L'abstraction est que nous travaillons avec un graphe d'objet, où les attributs à valeur unique et les attributs à valeurs multiples ne sont que des attributs. Mais l'implémentation en tant que magasin de données sauvegardé dans une base de données relationnelle fuit ... car le système d'intégrité du RDBS apparaît à travers le placage mince d'une interface objet.

2
hash1baby

Le fait que à un moment donné , qui sera guidé par votre échelle et votre exécution, vous devrez vous familiariser avec les détails de la mise en œuvre de votre cadre d'abstraction afin de comprendre pourquoi il se comporte de cette manière.

Par exemple, considérons cette requête SQL:

SELECT id, first_name, last_name, age, subject FROM student_details;

Et c'est une alternative:

SELECT * FROM student_details;

A présent, elles ressemblent à des solutions logiquement équivalentes, mais les performances de la première sont meilleures en raison de la spécification des noms de colonnes individuels. 

C'est un exemple trivial, mais cela revient finalement à la citation de Joel Spolsky:

Toutes les abstractions non triviales, dans une certaine mesure, ont des fuites.

À un moment donné, lorsque vous atteindrez une certaine ampleur dans votre opération, vous voudrez optimiser le fonctionnement de votre base de données (SQL). Pour ce faire, vous devez connaître le fonctionnement des bases de données relationnelles. Il vous a été résumé au début, mais il fuit. Vous devez apprendre à un moment donné.

0
Stas