Est-ce que trop d'abstraction peut être mauvais?

46

En tant que programmeurs, j'estime que notre objectif est de fournir de bonnes abstractions sur le modèle de domaine et la logique métier donnés. Mais où cette abstraction devrait-elle s'arrêter? Comment faire le compromis entre l'abstraction et tous ses avantages (flexibilité, facilité de changement, etc.) et la facilité de compréhension du code et de tous ses avantages.

Je crois que j'ai tendance à écrire du code trop abstrait et je ne sais pas à quel point il est bon; J'ai souvent tendance à l'écrire comme s'il s'agissait d'une sorte de micro-framework composé de deux parties:

  1. Micro-modules connectés au micro-framework: ces modules sont faciles à comprendre, à développer et à gérer en tant qu'unités individuelles. Ce code représente essentiellement le code qui exécute les tâches fonctionnelles décrites dans les exigences.
  2. Code de connexion; maintenant, je crois que le problème se pose. Ce code a tendance à être compliqué car il est parfois très abstrait et difficile à comprendre au début; cela est dû au fait qu'il ne s'agit que d'une abstraction pure, la base dans la réalité et la logique métier étant réalisées dans le code présenté 1; pour cette raison, ce code ne devrait pas être modifié une fois testé.

Est-ce une bonne approche en programmation? C’est cela, après avoir changé de code très fragmenté en de nombreux modules et très facile à comprendre et ne pas changer de code très complexe à partir du POV d’abstraction? Si tout le code est uniformément complexe (c'est-à-dire que le code 1 est plus complexe et interconnecté et que le code 2 est plus simple), afin que quiconque puisse le lire puisse le comprendre en un temps raisonnable, mais que le changement coûte cher ou que la solution présentée ci-dessus est bonne, où "Changer le code" est très facile à comprendre, déboguer, changer et "lier le code" est un peu difficile.

Remarque: il ne s'agit pas de lisibilité du code! Les codes 1 et 2 sont lisibles, mais le code 2 contient des abstractions plus complexes, tandis que le code 1 comporte de simples abstractions.

m3th0dman
la source
3
Des commentaires et des noms clairs sont inventés pour accélérer le temps nécessaire à la compréhension d'un code complexe. Il est parfaitement normal que votre code de niveau inférieur soit plus complexe. à un certain niveau, vous appelez certainement un niveau beaucoup plus complexe et beaucoup plus bas de toute façon.
DougM
25
«Trop» est mauvais par définition.
Jon Purdy
@ JimmyHoffa: Il faut garder ces types à leur place. Et ne soyez pas jaloux: je ne parviens pas à écrire à Haskell toute la journée. Il s’agit essentiellement de PHP, JavaScript et OCaml.
Jon Purdy

Réponses:

78

Les tous premiers mots de TC ++ PL4:

Tous les problèmes d’informatique peuvent être résolus par un autre niveau d’indirection, à l’exception du problème de trop nombreuses couches d’indirection. - David J. Wheeler

(David Wheeler était mon directeur de thèse. La citation sans la dernière ligne s’appelle parfois "La première loi de l’informatique".)

Bjarne
la source
6
Et comment savez-vous que vous avez trop de niveaux d'indirection? J'aurais tendance à dire que cela vient avec l'expérience, mais un programmeur plus expérimenté comprend facilement plus d'indirection et ne voit donc pas un problème avec trop de niveaux.
m3th0dman
2
@ m3th0dman - vous avez le bon niveau d'abstraction lorsqu'il devient facile de faire des changements dans le futur. Bien sûr, vous pouvez également demander comment vous savez quand se produira ce qui ne fait que répéter le cycle de questions d'une manière différente.
1
cette question est comme dépendante du niveau du programmeur .. vous aurez des programmeurs complexes qui comprendront votre architecture de couche folle à 8 niveaux et la trouveront brillante, tandis que d'autres codeurs simples mais tout en douceur la trouveront ridicule et discuteront de votre folle 8 niveaux Projet en couches. C’est là que la documentation est rentable. Elle vous permet non seulement de documenter votre code, mais également de le défendre
Ryan
1
pardonnez mon ignorance, mais je ne comprends pas "TC ++ PL4"
LastTunset
30

Oui définitivement. Le fait est qu'aucune abstraction n'est parfaite. Tous les détails de la couche sur laquelle se trouvent les abstractions sont là pour une raison, et cela peut simplifier beaucoup de choses, mais si cette complexité n'était pas nécessaire à un moment donné, elle ne le serait probablement pas au départ. Et cela signifie qu'à un moment donné, chaque abstraction va fuir d'une manière ou d'une autre.

Et c'est là que réside le vrai problème. Lorsque les abstractions échouent, plus vous en superposez le code que vous avez écrit et ce qui se passe réellement, plus il est difficile de comprendre le problème et de le résoudre, car il existe plus d'endroits où le problème se pose. Et plus il y a de couches, plus vous devez en savoir pour pouvoir la retrouver.

Maçon Wheeler
la source
1
"Et cela signifie qu'à un moment donné, chaque abstraction va couler d'une manière ou d'une autre.": Vrai. Une meilleure abstraction est une fuite qui fuit moins souvent.
Giorgio
11
À la lumière de la réponse de Bjarne (et du référencement de la page wiki de David Wheeler ), vous pouvez peut-être modifier l'attribution de votre devis? :)
congusbongus
2
@CongXu: Btw J'y suis allé de l'autre côté: googler pour "Bjarne Stroustrup quotes" et n'ai trouvé aucune référence de Bjarne ayant prononcé l'expression "ajouter une autre couche d'indirection" ... Pas décisif bien sûr mais le fait il est donc très improbable qu’il ait été le premier à le dire.
Marjan Venema
1
Plus de couches d'abstraction sont synonymes d'abstractions simples et donc moins de fuites par abstraction. Ainsi, dans une formulation mathématique (bien sûr, sans aucune preuve), la somme des pertes d'abstraction peut être constante lorsque le nombre de niveaux d'abstraction change.
m3th0dman
2
Une fois, j'ai naïvement pris le conseil d'une personne âgée d'ajouter une abstraction là où elle n'était pas nécessaire. Il n'a jamais été utilisé au-delà de ce que je voulais faire en premier lieu.
Cees Timmerman
15

Oui absolument.

L'analogie que j'aime utiliser pour expliquer la programmation est celle d'un tailleur. Lors de la confection d'un costume, un bon tailleur laissera toujours une petite quantité de tissu à des emplacements stratégiques du vêtement afin de permettre à celui-ci de passer ou de sortir sans modifier sa forme ou sa structure.

Good Tailor ne laissez pas des rames de tissu à chaque couture, juste au cas où vous développeriez un troisième bras ou deveniez enceinte. Trop de matériel aux mauvais endroits rendra le vêtement mal ajusté et le vêtement usé, le tissu supplémentaire gêne simplement l'utilisation normale. Trop peu de tissu et le vêtement est sujet aux larmes et ne pourra pas être modifié pour faire face à des modifications mineures du physique de son porteur, ce qui affecte la façon dont le vêtement s'assied.

Peut-être qu'un jour, notre bon tailleur aura pour tâche de confectionner une robe tellement serrée qu'il devra y coudre sa tenue. Et on demande peut-être à notre bon tailleur de confectionner des vêtements de maternité, où le style et la coupe seront les deuxièmes places en termes de confort et de capacité d'extension. Mais avant d’entreprendre l’un ou l’autre de ces emplois spéciaux, un bon tailleur serait assez sage pour que tout le monde soit au courant des compromis qui sont faits pour atteindre ces objectifs.

Parfois, ces compromis sont la bonne voie à suivre et les gens sont prêts à en accepter les conséquences. Mais dans la plupart des cas, l’approche consistant à laisser un peu plus d’importance l'emportera sur les avantages perçus.

Alors, relions ceci à l'abstraction. Il est tout à fait possible d'avoir beaucoup trop de couches d'abstraction, tout comme il est possible d'avoir peu de choses. Le véritable art du programmeur, comme celui de nos amis tailleurs, est de laisser un peu là où ça compte le plus.

Revenir sur le sujet.

Le problème avec le code n'est généralement pas l'abstraction, mais les dépendances. Comme vous l'avez souligné, c'est le code qui connecte les objets discrets qui pose problème, car il existe une dépendance implicite entre eux. À un moment donné, la communication entre les choses doit simplement être concrète, mais le jugement de cette situation nécessite généralement quelques devinettes.

Cela étant dit, "Micro" signifie généralement que vous avez trop structuré la présentation de votre objet et que vous utilisez probablement Type comme synonyme de ce que devrait être Data . Avoir moins de choses signifie également moins de dépendances nécessaires pour communiquer entre elles.

Pour cette raison, je suis un grand fan de la messagerie asynchrone entre les systèmes. Vous vous retrouvez avec deux systèmes dépendants du message plutôt que l'un l'autre. Vous offrant un couplage moins étroit entre les systèmes communicants. À ce stade, si vous avez besoin d'une dépendance entre systèmes, vous devez vous demander si vous avez les bits qui dépendent au bon endroit. Et c'est souvent le cas que vous ne faites pas.

Enfin, le code compliqué va être compliqué. Il n'y a souvent aucun moyen de contourner cela. Mais le code qui a moins de dépendances est beaucoup plus facile à comprendre que celui qui repose sur différents états externes.

Matt D
la source
2
+1 pour "Le bon tailleur ne laisse pas des rames de tissu à chaque couture juste au cas où tu aurais un troisième bras, ou deviendrais enceinte". Nous avons souvent tendance à concevoir des logiciels de cette façon, malheureusement.
Kemoda
En plus de la compréhensibilité, on peut également trouver l’abstraction utile lors du pliage d’une ligne courbe en une ligne droite. Ce qui signifie que vous réduisez la complexité et / ou l'entropie avec l'abstraction. Peut-être quelque chose comme un gestionnaire de données de type Curry où la graisse que vous rasez est encore utile plus tard.
Cody
13

Je pense que notre objectif est de fournir de bonnes abstractions sur le modèle de domaine et la logique métier donnés.

J'ai un point de vue différent: notre objectif est de résoudre un problème commercial. Les abstractions ne sont qu'une technique pour organiser une solution. Une autre réponse utilise l'analogie d'un tailleur confectionnant des vêtements. J'ai une autre analogie à laquelle je me plais à penser: un squelette. Le code est comme un squelette et les abstractions sont les articulations entre les os. Si vous n'avez pas d'articulation, vous vous retrouvez avec un seul os qui ne peut pas bouger du tout et qui est inutile. Mais si vous avez trop de joints, vous vous retrouvez avec un tas de gelée glissante qui ne peut pas tenir debout tout seul. L'astuce consiste à trouver le bon équilibre - suffisamment de joints pour permettre le mouvement, mais pas tant qu'il n'y ait pas de forme ou de structure définie.

Jordan Lev
la source