Pourquoi Bertrand Meyer pense-t-il (/ pensait-il) que le sous-classement est le seul moyen d'étendre un module «fermé»?

19

Dans Meyer Travaux logiciel orienté objet (1988) , il définit le principe ouvert / fermé les suivants:

  • Un module sera dit ouvert s'il est toujours disponible pour extension. Par exemple, il devrait être possible d'ajouter des champs aux structures de données qu'il contient ou de nouveaux éléments à l'ensemble des fonctions qu'il exécute.
  • Un module sera dite fermée si elle est disponible pour une utilisation par d'autres modules. Cela suppose que le module a reçu une description stable et bien définie (l'interface au sens de masquage des informations).

Il poursuit en disant:

Si vous rouvrez un module, vous devez également rouvrir tous ses clients pour les mettre à jour, car ils reposent sur l'ancienne version. … [Ce problème] se pose chaque fois qu'un module doit être étendu par une nouvelle fonction ou un nouvel élément de données, déclenchant des changements dans les clients directs et indirects. ... Avec les approches classiques de conception et de programmation, il n'y a aucun moyen d'écrire des modules à la fois ouverts et fermés.

La solution de Meyer à ce dilemme est: un module n'étendent la bibliothèque en modifiant les classes existantes; à la place, écrire un nouveau module qui sous-classe des classes existantes, et ont nouveaux clients dépendent de ce nouveau module.

Maintenant, en 1988, je suis Toy écrivais programmes (procédures) en Turbo Pascal et Blankenship de base, mon 21e siècle expérience professionnelle est sur la JVM, le CLR, en langages dynamiques, donc je ne sais pas ce que veut Meyer par "approches classiques de la conception et de la programmation".

Un de exemple concret de Meyer pourquoi modules clients doit être rouverte (un switch sur une liste qui compte désormais plus de membres, ce qui nécessite plus de cas) semble assez raisonnable, mais il ne justifie pas près de l'affirmation selon laquelle chaque fois que vous ajouter des fonctionnalités à une bibliothèque module, vous devez mettre à jour tous ses clients .

Y a-t-il une raison historique pour laquelle cette affirmation semblait évidente en 1988? Par exemple, l'ajout de fonctions ou de structures de données à une bibliothèque statique C a-t-il modifié la disposition de sorte que même avec des API rétrocompatibles, les clients devaient être recompilés? Ou Meyer parle-t-il vraiment d'un mécanisme pour appliquer la compatibilité descendante de l'API?

David Moles
la source
3
Question interessante! J'ai le sentiment que la réponse va être en quelque sorte liée à la différence fondamentale entre les types de données abstraits et l' abstraction des données orientées objet , qui sont les deux mécanismes dominants d'abstraction des données dans la programmation modulaire (ce que Betrand Meyer appelle des "approches classiques" ") et la programmation orientée objet (lire les commentaires!), respectivement.
Jörg W Mittag
C'est étrange. Il semble contredite de manière flagrante par la réalité (même en 1988). En outre, son approche préconisée se traduirait par une multiplication inutile des modules.
@ dan1111: l'approche de l'héritage d'Eiffel, y compris, mais sans s'y limiter, son approche de l' héritage multiple est différente de C ++, Java, C #, etc., il n'est donc pas surprenant que l'approche soit différente. Il a développé Eiffel spécifiquement pour soutenir ses vues sur OO, après tout.
Jörg W Mittag

Réponses:

18

Pour autant que je sache, Bertrand Meyer a lui-même répondu à cette question, et la réponse est que cette affirmation n'est pas exacte. Avec les approches classiques de conception et de programmation, il peut en effet y avoir un moyen d'écrire des modules qui sont à la fois ouverts et fermés.

Pour le savoir, vous devez étudier la deuxième édition de ce livre (publié neuf ans plus tard, en 1997). Selon avant - propos de la deuxième édition , il est

aucune mise à jour, mais le résultat d'un remaniement en profondeur. Pas un paragraphe de la version originale a été épargnée. (A peine une seule ligne, en fait.)

En particulier, l'affirmation selon laquelle vous confond a disparu. Il est toujours principe ouvert-fermé chapitre de dans "§3.3 Cinq principes", et il y a une discussion plus approfondie de ce sujet dans "§14.7 Introduction à l'héritage" mais la déclaration de la première édition n'est plus là.

Ce qui est là se concentre à la place sur la façon dont il est plus pratique et idiomatique dans l'approche OO par rapport aux méthodes précédentes,

Grâce à l'héritage, les développeurs OO peuvent adopter une approche beaucoup plus incrémentielle du développement logiciel qu'auparavant avec les méthodes antérieures ... (§3.3)

Cette double exigence (ouverte ou fermée) ressemble à un dilemme, et les structures de modules classiques offrent aucune idée. Mais l' héritage résout. Une classe est fermée, car il peut être compilé, stocké dans une bibliothèque, baselined et utilisés par les classes de clients. Mais il est également ouvert, étant donné que toute nouvelle classe peut l' utiliser en tant que parent, en ajoutant de nouvelles fonctionnalités et la nouvelle déclaration caractéristiques héréditaires; dans ce processus , il est inutile de modifier l'original ou de perturber ses clients ... (§14.7)

Puisque vous semblez aussi étonnant à ce que « les approches classiques » Meyer entend ici, vous trouverez explication de ceux - ci dans §4.7 structures traditionnelles modulaires . Cette section explique que ces moyennes « bibliothèques de routines » et des « packages » (pour ce dernier, l' auteur affirme que le terme est tiré de Ada et mentionne d' autres langues ayant cette fonction - groupes de CLU et modules en Modula).

Si vous pensez de celui-ci, aucune de ces approches a été à l'origine destiné à l'aide à l'écriture de code qui respecte ouvert-fermé principe. Cela pourrait conduire l'auteur à l'évaluation quelque peu prématuré qui a été corrigée par la suite dans la deuxième édition.


En ce qui concerne ce qui précisément fait du changement des auteurs d'avis sur cette déclaration entre les première et deuxième édition, je pense que l' on peut trouver une réponse, encore une fois, dans le livre lui - même, notamment dans la partie F: L' application de la méthode de langues différentes et des » Dans. ce chapitre, l' auteur explique comment les méthodes orientées objet peuvent être utilisés dans les langues anciennes:

Les langages classiques comme Fortran ne sont pas du tout OO, mais les personnes qui doivent encore les utiliser ... peuvent vouloir appliquer autant d'idées OO que possible dans les limites de ces anciennes approches.

En particulier, dans cette partie, Meyer explique en détail comment il serait possible d'implémenter l'héritage (avec quelques mises en garde et limitations, mais toujours) en C et même en Fortran.

Vous voyez, cela appelle vraiment à réviser cette déclaration de la première édition. Il semble pratiquement impossible d'expliquer comment concilier "avec les approches classiques ... il n'y a aucun moyen" avec des exemples réalistes sur la façon dont cela peut être fait exactement .

moucheron
la source
Intéressant, et je devrai certainement essayer de mettre la main sur la deuxième édition, mais je ne comprends toujours pas pourquoi même une bibliothèque "classique" non OO ne pouvait pas ajouter (au moins certains types de) fonctionnalités sans perturber son clients.
David Moles
Chose de @DavidMoles est, il pourrait , et dernière partie de ma réponse explique que, et que Meyer se rendit compte que (quand il a retravaillé pour la 2ème édition) et a même donné des exemples de cela peut être fait. "Quant à ce qui a spécifiquement poussé l'auteur à changer d'avis ..." etc
gnat
Hmm. Je ne vois pas "la version 2 de cette bibliothèque, qui remplace la version 1 et qui est rétrocompatible avec elle, ajoute les fonctions suivantes ..." comme "héritage" sauf de la manière conceptuelle la plus large possible.
David Moles
(Héritage, pour moi, indique que la version 1 est toujours là et appelé par la version 2.)
David Moles
@DavidMoles remplacer par la version 2 (comme dans, changer le code source et recompiler ) ne serait pas considéré comme "fermé pour modification", vous pouvez simplement vérifier cela dans l'article Wikipedia : "l'entité peut autoriser son comportement à être étendu sans modifier son code source ... "
moucher