Dijkstra avait-il l'intention de modulariser le code, lorsqu'il a écrit sur la séparation des préoccupations?

9

Tout d'abord, j'ai lu un extrait du document de 1974 d'Edsger W. Dijkstra "Sur le rôle de la pensée scientifique":

Permettez-moi d'essayer de vous expliquer ce qui, à mon goût, est caractéristique de toute pensée intelligente. C'est que l'on est prêt à étudier en profondeur un aspect de son sujet de manière isolée pour sa propre cohérence, tout en sachant que l'on ne s'occupe que de l'un des aspects. Nous savons qu'un programme doit être correct et nous ne pouvons l'étudier que de ce point de vue; nous savons également qu'elle doit être efficace et nous pouvons étudier son efficacité un autre jour, pour ainsi dire. Dans une autre humeur, nous pouvons nous demander si, et si oui: pourquoi, le programme est souhaitable. Mais rien n'est gagné - bien au contraire! - en abordant ces différents aspects simultanément. C’est ce que j’ai parfois appelé «la séparation des préoccupations» qui, même si ce n’est pas parfaitement possible, est encore la seule technique disponible pour ordonner efficacement ses pensées, à ma connaissance. C'est ce que je veux dire par «concentrer son attention sur un aspect»: cela ne signifie pas ignorer les autres aspects, c'est simplement rendre justice au fait que du point de vue de cet aspect, l'autre est sans pertinence. Il est à l'esprit unique et à pistes multiples simultanément.

Je vois une séparation moderne des préoccupations parler de la modularisation de votre code. Cependant, en lisant la citation ci-dessus, je comprends que cela concentre votre esprit sur une tâche particulière à la fois, sans vous concentrer sur d'autres aspects. Cela ne signifie pas nécessairement pour moi que le code doit être séparé en morceaux modulaires.

C'est-à-dire, disons qu'il y a un code devant vous qui dans un fichier contient les concepts de vue, référentiel, contrôleur, gestion des événements, usine, etc. dans un seul fichier.

Pour un bref exemple, voici un code qui a accès aux données et affiche (sortie):

$sql = "SELECT * FROM product WHERE id = " . db_input($id);
$row = db_fetch_array(db_query($sql)); 
<option value="<?=$row['id']?>"<?= $row['ver'] == $row['ver'] ? '  selected="selected"' : '' ?>>Version <?=$row['ver']?></option>

En utilisant OO moderne, je pourrais placer l'accès aux données dans son propre fichier en utilisant le modèle de référentiel, le code View peut aller dans son propre modèle de fichier, et je peux les câbler ensemble pour communiquer via un contrôleur (ou Action ou Request Handler), et je peux ajouter une fabrique pour créer et câbler diverses dépendances. Et je peux avoir un fichier de configuration qui définit ces usines. C'est sûrement une étape loin de tout ce qui concerne un seul fichier.

Ma question sur la séparation des préoccupations est la suivante: en lisant la citation de Dijkstra, j'ai eu une idée que peut-être il ne voulait pas nécessairement dire que la séparation des préoccupations était "une séparation modulaire du code (dans des fichiers ou leurs propres fonctions / méthodes / etc)", et qu'il voulait davantage concentrer son esprit sur un aspect du programme, sans se contraindre à se concentrer sur d'autres aspects importants mais non actuellement à prendre en considération, qu'ils soient physiquement séparés dans le code ou non.

Pourquoi alors nous alourdissons-nous avec des modèles physiques de séparation et de conception de codes modulaires? Ne sera-t-il pas suffisant de se concentrer uniquement sur un aspect, quelle que soit la structure de votre code?

Je ne parle pas de rédiger le code de spaghetti le plus horrible et de n'en considérer qu'un aspect, ce serait probablement un fardeau. Mais à la fin, ce vers quoi je m'oriente, c'est pourquoi effectuer la séparation physique du code, pourquoi diviser le code en fichiers séparés ou en morceaux (méthodes), alors qu'il n'est pas nécessaire de se concentrer mentalement sur un aspect?

La séparation des préoccupations doit-elle rester un exercice mental plutôt que physique?
En d'autres termes, devrait-il y avoir une déconnexion entre les aspects mental (concentration) et physique (code sur papier) de la programmation?

Dennis
la source
5
Je suis à peu près sûr qu'en 1974, il considérait la programmation modulaire comme une évidence, et c'est pourquoi il n'en a pas explicitement parlé dans cet article. Le document de Parnas au sujet comment modularisation était en 1972, et à ce moment si modularisation était déjà plus question. En fait, ce que vous décrivez n'est même pas une programmation modulaire, c'est une programmation structurée , ce que Dijkstra lui-même a fortement soutenu en 1968 déjà dans son article classique "Go To Considered Harmful".
Jörg W Mittag
très bien alors peut-être que je peux comprendre la «séparation des préoccupations» plus comme un exercice de concentration mentale, et la modularisation comme un moyen d'encapsuler un aspect du code sur papier. Cependant, je vois maintenant la séparation des préoccupations et la modularisation davantage comme des concepts distincts.
Dennis
@ JörgWMittag, pouvez-vous définir une distinction entre programmation structurée et programmation modulaire? Certains liens sur Google suggèrent qu'ils sont identiques.
Dennis
Structuré = IF, WHILE, au FORlieu de GOTO. Modular = modules avec une API publique bien définie strictement séparée d'une implémentation et d'une représentation internes cachées. (Par exemple Modula, Mesa, Modula-2, Modula-3, plus tard les dialectes Pascal ( UNIT).)
Jörg W Mittag

Réponses:

2

Dijkstra fait une déclaration explicite sur la façon de penser. La modularisation des programmes (et des processus) - et c'est souhaitable - est peut-être le résultat de cette réflexion, mais le point clé qu'il fait est de savoir comment évaluer un problème. Le programme est généralement la solution à un problème, et en préconisant une "séparation des préoccupations", il offre des conseils avisés. Le meilleur exemple de cela est peut-être "l'optimisation". La blague était: "Lorsque vous envisagez d'optimiser un programme, votre première stratégie devrait être: Ne le faites pas." En d'autres termes, vous voulez vous concentrer d'abord sur la correction du programme. Le rendre rapide et sophistiqué est une préoccupation qui doit être séparée - mais pas non plus complètement supprimée.

MCL
la source
14

La séparation des préoccupations est une manière abstraite de penser qui consiste à considérer séparément des choses qui n'ont pas à être liées.

La modularisation (séparation d'un groupe de fonctions indépendantes en modules), l'encapsulation (masquage des détails internes des modules) et l'abstraction (séparation du général du spécifique et de l'idée de sa mise en œuvre) sont autant de moyens de mettre en œuvre cette façon de penser dans le domaine de la conception de logiciels.

Christophe
la source
9

Je dirais que, bien que le document présente un intérêt historique, ce que Dijkstra entendait par l'expression "séparation des préoccupations" il y a plus de 40 ans n'est pas particulièrement pertinent aujourd'hui. De nos jours, il est largement utilisé en référence à la modulation.

Il existe de nombreuses preuves que la modulation est extrêmement bénéfique et que ces avantages l'emportent de loin sur les "charges" qu'elle nous impose. Quoi que Dijkstra voulait dire à l'époque, cela ne change pas le fait que de petits morceaux de code, chacun axé sur une seule chose, conduisent à un code plus facile à écrire, à lire, à comprendre, à maintenir et à tester.

David Arno
la source
5
Je pense qu'il convient de noter qu'une grande partie de la réflexion moderne sur la séparation des préoccupations est venue des premiers articles qui ont finalement donné naissance à la programmation orientée aspect d'IBM. Je pense que les articles initiaux (fin des années 90-début des années 2000) sont la plus grande influence là-bas. Cela fait un moment et les sites Web ont tous changé. Je ne sais pas si je peux même les retrouver.
Berin Loritsch
2
La partie difficile étant d'essayer de définir ce que signifie "une chose". Sans cela, l'idée est inutile en termes d'écriture de code pratique, et se tromper a immédiatement des effets néfastes sur la difficulté d'écrire, de lire, de comprendre, de maintenir et de tester le code.
jpmc26
1
Cela nous aiderait vraiment à comprendre votre position si vous (a) expliquez ce que vous pensez que Dijkstra entendait par «séparation des préoccupations» et (b) expliquez POURQUOI vous pensez que ce qu'il veut dire n'est plus pertinent.
John R. Strohm
2

Je peux vous donner un exemple personnel de séparation des préoccupations qui, selon moi, est comparable aux concepts de Dijkstra. Lorsque j'analyse un sujet particulier dans un logiciel, je construis trois vues.

  1. Je considère d'abord les données. Les données représentent les prédicats logiques du problème. Les classes sont construites en entités abstraites dans le monde réel, leurs attributs étant les paramètres de l'abstraction. Les associations entre classes représentent des mappages fonctionnels entre les instances de classe. Il n'y a aucun code impliqué dans la réflexion à ce stade et aucune notion de traitement. Juste une vue statique de la logique impliquée dans le sujet.
  2. Deuxièmement, je considère la dynamique. Toute classe qui a un cycle de vie non trivial est modélisée comme une machine à états finis. Cela implique des considérations d'exécution de séquençage et de synchronisation. Encore une fois, aucun code ne permet de déterminer comment les choses interagissent et se séquencent.
  3. Troisièmement, je considère le traitement. Ici, le travail algorithmique réel qui doit être effectué lors des transitions d'état ou dans d'autres opérations synchrones.

En fin de compte, on obtient une vue à trois facettes de la matière qui peut ensuite être formulée sous forme de code dans tous les regroupements qui conviennent au code lui-même et à sa maintenance. Les trois facettes ne sont pas seulement un exercice mental. Je produis des descriptions écrites de toutes les facettes. Pourquoi? Parce que si le sujet est assez grand, je ne peux pas garder une seule facette complète dans la mémoire à court terme. Si le sujet est petit, presque n'importe quelle approche fonctionnera car vous pouvez tout tenir dans votre tête.

La motivation pour séparer les préoccupations est de s'adapter aux limitations de mémoire à court terme des humains. Nous ne pouvons tout simplement pas tout transporter dans nos têtes à la fois, bien que les programmeurs informatiques aient tendance à être plus capables que la plupart des autres en ce qui concerne le nombre de concepts qu'ils peuvent manipuler dans leur mémoire à court terme. Pour être efficace, la séparation des préoccupations doit systématiquementexclure un ou plusieurs aspects d'un problème afin de se concentrer sur un autre aspect particulier. Bien sûr, l'exclusion d'un aspect ne le fait pas disparaître de la considération. Il doit y avoir un moyen de combiner tous les aspects du problème pour parvenir à une solution. L'expérience montre que souvent le résultat final de la séparation et de la recombinaison donne une solution plus compréhensible qu'un saut géant où de nombreux aspects peuvent être confondus. C'est particulièrement le cas lorsque la taille du problème est importante ou complexe.

andy mango
la source
1

La séparation des préoccupations est un concept logique qui se propage dans votre modèle d'organisation de code, quelle que soit la manière dont vous l'implémentez. Il est vrai qu'un fichier de code n'est qu'un détail technique, une façon de vous permettre de gérer votre logiciel. Un seul fichier avec un bon éditeur qui permet de réduire une expansion des régions pourrait également fonctionner pour vous (pendant un certain temps). Ou une base de données relationnelle qui stocke les classes et les méthodes de manière parent-enfant dans des tables séparées pourrait fonctionner comme support de stockage. Mais les fichiers texte sont difficiles à battre dans un monde où le code source doit être

  • portable
  • accessible par de nombreux outils externes différents
  • accessible par plusieurs programmeurs
  • versionnable et comparable
  • bien évoluer avec les systèmes d'exploitation qui sont très bons pour la gestion des fichiers

L'essentiel, c'est que nous, les humains, ne sommes pas très bons pour penser ou traiter des choses différentes à la fois. Nous avons donc besoin d'un modèle qui permette de penser et de travailler sur une chose à la fois sans risquer de ruiner une autre partie que nous ne considérons pas à ce moment-là. Nous construisons donc, en posant une brique à la fois, en nous assurant que les briques que nous avons posées plus tôt n'interfèrent pas avec les briques posées plus tard. Et si nous voulons changer une brique plus tard, les choses ne doivent pas s'effondrer. C'est un modèle qui fonctionne pour nos esprits à voie unique.

Ce n'est pas ainsi que les champignons ou les algues poussent ... Comment est-ce pour un fait humiliant?

Martin Maat
la source
-1

Je pense que la réponse spécifique à la citation de Dijkstra a été abordée, cependant, puisque vous déclarez "En utilisant OO moderne, je pourrais placer l'accès aux données dans son propre fichier" et demander "La séparation des préoccupations doit-elle rester un exercice mental plutôt que physique?" permettez-moi d'attirer votre attention sur la direction vers laquelle les directeurs OO modernes nous dirigent.

Il faut suivre les principes SOLID dans le développement utilisant OO. Voici un bon lien pour eux, mais le TLDR sur la "séparation des préoccupations" se trouve principalement dans le S de SOLID: The Single Responsibility Principle ou SRP.

Il s'agit très certainement d'un exercice physique et non pas d'un exercice mental. Pour votre exemple spécifique, MVC (ou ses frères et sœurs MVVM et MVP) ordonne à l'un de séparer physiquement les concerts de Model, View et Controller / Presenter / ViewModel dans des fichiers séparés. J'ai vu quelques implémentations MVVM où celles-ci sont implémentées dans des assemblages séparés pour limiter davantage la tendance à «mélanger les concepts».

Mais. Cela va au-delà du simple "ceci est une vue et ceci est un modèle", si vous suivez le point de vue de l' oncle Bob à ce sujet.

Il faut également considérer la source des exigences pour tout élément OO particulier. Si vous mélangez, disons, ce que le client veut avec ce que veut le personnel d'exploitation, vous violez également le SRP. Ou, pour le dire comme le fait l'oncle Bob: Une classe devrait avoir une et une seule raison de changer.

Je vous recommande fortement de poursuivre votre recherche en utilisant les liens fournis ou de faire une recherche sur le Web pour des "principes solides".

Bleu Reginald
la source
Non. Les principes SOLID sont si éloignés de la réalité de l'écriture de code (= philosophique) qu'ils ne peuvent être compris de manière utile à distance qu'une fois que vous savez déjà comment écrire un bon code, à quel point ils sont au mieux redondants. Les utiliser comme principes directeurs sans avoir déjà l'expérience et les capacités produit un code extrêmement pauvre.
jpmc26