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 modern OO 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 usine 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 un pas loin de tout-fichier-tout.
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 gênons-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 un décalage entre les aspects mental (concentration) et physique (code sur papier) de la programmation?
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.
Séparation des préoccupations est une manière de penser abstraite qui consiste à considérer séparément les choses qui ne doivent pas être liés.
Modularisation (séparation d'un groupe de fonctions indépendantes en modules), encapsulation (masquage des détails internes des modules) et abstraction (séparer le général du spécifique et 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 logicielle.
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.
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.
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ématiquement exclure 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.
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
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?