À propos de M et de V et un peu de C

Les nouvelles parmi les agréablement inattendus ont réveillé toutes sortes de souvenirs, doux et pas si. Je suis également arrivée à cet article d'elle, et j'ai immédiatement été malade de nostalgie, et je voulais jouer une ellipse si lourde d'elle au cours des sept dernières années.


Dephi était une solution absolument brillante. Eh bien, vous savez, comme les Beatles, comme une interface graphique avec le contrôle de la souris, comme un moteur à combustion interne. La solution ingénieuse qui est entrée dans nos vies si largement que vous ne pouvez même pas croire qu’elle n’était pas là, et dessiner des fenêtres, des cases à cocher et des boutons dans Windows pourrait être une vraie douleur.


La partie ingénieuse, absolument, de Delphi était VCL - le même ensemble de cases à cocher et de boutons pour les fenêtres Windows, qui est soudainement devenu si facile et simple à glisser-déposer les uns sur les autres, et à créer de belles et inhabituelles applications Windows.


Et comme toute interface utilisateur décente, cela a fonctionné, bien sûr, selon le modèle d'événement. OnClick dans l'objet bouton décrit tout ce que fait le bouton, OnChange lors de la saisie dans un champ de texte, tout est comme chez les adultes. Mais par la suite - plus loin, malheureusement, il n'y avait encore rien.


Rien de ce que nous savons maintenant, je veux dire. MVC, par exemple - Delphi, considère qu'il était composé d'un V, puis tout est resté à la merci du développeur. Directement depuis OnClick pour extraire une demande de la base de données? Oui, s'il te plait. Dans OnChange, ouvrez un fichier et essayez d'écrire dessus, et si le fichier en place ne se bloque pas tranquillement avec quelque chose comme Memory Access Violation - à chaque étape (cependant, cela n'a rien à voir avec Delphi en tant que plate-forme).


Et je dois dire que pendant de nombreuses années, il a été complètement heureux pour tout le monde, et certains en sont encore très satisfaits. Les avantages d'une bibliothèque mince et belle de composants d'interface utilisateur sont immédiatement visibles, les avantages de tous les contrôleurs et modèles ne deviennent apparents ni dans la première année de développement, ni dans les cent premiers kilo-octets de codes source.


Et même si elle est devenue - il est facile de l'oublier, il y a un piège à esprit ici, comme ces illusions d'optique et de son dont on débat avec acharnement sur Internet. Permettez-moi donc d'essayer de jeter un petit pont de Delphi à une compréhension moderne de l'interface utilisateur et nous pouvons comprendre ce qui se passe.


Donc, l'idée clé: nous séparons la présentation des données, le widget séparément, tout le travail avec les informations qu'il contient est séparé. Dans quelle mesure? Disons que le bouton a toujours une inscription et parfois une icône. L'utilisateur lui-même peut insérer cette inscription dans le champ de texte, et parfois le champ de texte a une autre inscription expliquant à l'utilisateur exactement ce qu'il conduit. Règle générale: le widget est engagé dans l'affichage, au moins (SIC!) De la logique, celle qui peut y être présente ne doit être associée qu'à l'affichage et rien d'autre. Par exemple, si le bouton n'est pas prêt à s'étirer avec l'inscription dessus - l'inscription doit être coupée d'une manière ou d'une autre (par exemple, afficher les points de suspension et la version complète dans l'info-bulle), ou donner une erreur en essayant de définir la valeur plus qu'elle ne tient (bien que cela l'idée est telle, une telle erreur se produira très probablement déjà lors de l'exécution du programme, au moment le plus inopportun).


Un champ de saisie de texte peut effacer les traductions de chariot du texte s'il s'agit d'une seule ligne, mais il n'est pas nécessaire d'exiger, par exemple, de ne saisir que des chiffres - ce n'est pas son travail. Tout comme dans le gestionnaire de clic de bouton, aucune vérification n'est nécessaire, aucun appel à redessiner, le gestionnaire de bouton doit extraire le code externe, qui est déjà responsable de la logique de l'interface utilisateur et de l'application entière.


Et si vous vivez dans un nouveau monde de jet magnifique, en regardant tous ces événements OOP, le principe reste le même: appuyer sur un bouton change son état en ajoutant l'action correspondante, puis du code, le code ne fonctionne pas associés aux éléments de l'interface utilisateur, examinez cette action, tirez les conclusions appropriées et modifiez l'état de sorte qu'il y ait quelque chose à afficher sur l'interface utilisateur.


Autrement dit, quels que soient l'environnement, la plate-forme et le paradigme, les éléments visuels eux-mêmes comportent en eux-mêmes un minimum de fonctionnalités et aucune logique. Ils reçoivent des informations sous la forme la plus générale, donc si vous avez un TextBox, c'est aussi Input, c'est aussi un champ de saisie de texte, ça prend une chaîne et donne une chaîne. Et la tâche de transformer une ligne en un nombre, le nom d'une personne ou quelque chose de plus rusé n'est plus pour le widget.


Eh bien, le contrôleur ou le présentateur traite le résultat et produit le résultat. Appelez-le comme vous en avez l'habitude, mais ne lui insérez aucun élément visuel.


Quel est le profit? J'énumère dans l'ordre du plus évident au plus, à mon avis, l'essentiel.


Tout d'abord, la réutilisabilité. On peut consacrer beaucoup de temps à comprendre qu'un champ pour entrer une adresse postale, pour saisir un nom de famille et pour entrer une somme est, en fait, le même champ. Un seul et même widget, avec le même ensemble de fonctionnalités qui revient à extraire un événement de saisie de texte ou à mettre à jour un état. Et seule la logique de travailler avec le texte à l'intérieur peut différer. Un exemple de «comment ne pas faire» dans la vie: créer un champ pour entrer une somme d'argent (jusqu'à deux décimales), puis déconner pendant longtemps, en le refaisant pour que parfois vous puissiez entrer une quantité dans le même champ (jusqu'à 4 décimales) . Interrompez le processus tous les endroits où le montant est entré dans la demande et réparez-les d'urgence au milieu de la nuit. Et cela malgré le fait que, selon la logique de leur travail, ils avaient des différences à la troisième décimale. Vous pouvez écrire des poèmes sur la façon dont les champs de saisie des adresses e-mail se transforment en champs de saisie des adresses géographiques en utilisant l'héritage et les paroles de Dieu.


Deuxièmement: la testabilité. Vous pouvez également tester l'interface utilisateur. Presque n'importe quelle interface utilisateur. Mais cela coûtera cher, en termes de temps et de ressources consacrées au développement de tests et à l'exécution de tests, et il est peu probable qu'ils soient lancés à chaque reconstruction, mais lorsque les tests se bloqueront à la sortie, ce sera un cas de force majeure. Mais les composants de l'interface utilisateur sont les plus risqués en termes de pannes, ils cassent, en règle générale, le plus souvent, le plus clairement et le plus douloureusement. Mais le code, arraché aux widgets eux-mêmes, est vraiment couvert par des tests unitaires. Et les tests unitaires sont beaucoup moins chers - ils sont plus faciles à écrire et vous pouvez les exécuter littéralement après toute modification, et assurez-vous toujours que rien ne s'est cassé.


Et troisièmement, le plus important, à mon avis. Dessiner un morceau d'interface utilisateur avec la logique comme une seule pièce est extrêmement difficile de vaincre la paresse et de réfléchir plus profondément à son fonctionnement. Pour élaborer des scénarios, sauf idéalement positifs, lorsque l'utilisateur est entré exactement ce qui était attendu de lui, a fait exactement ce qui était nécessaire et a reçu exactement ce qu'il voulait. Ce même programmeur sacré "tout fonctionne pour moi".


La séparation de la partie visuelle et de la partie logique vous fait penser, tout d'abord, comment fonctionne la partie visuelle: ce qui y entre, ce qui en sort, ce qui se passe si quelque chose qui ne devait pas entrer ou sortir ne fonctionne pas. Et l'écriture de la logique séparément du contrôle vous oblige à l'écrire dans des cas, c'est-à-dire, selon des scénarios possibles pour utiliser une application particulière à un endroit particulier, y compris les erreurs de traitement qui surviennent ici, et aider l'utilisateur dans les difficultés qu'il éprouve ici. Eh bien, oui, pas toujours, ou plutôt pas en tout, une solution en général vaut mieux qu'une solution adaptée à un cas particulier.


Pour résumer. Vous pouvez écrire dans Delph, ou une application pour iOS, torturer le Web qui souffre depuis longtemps pour une sorte de là-bas, ou riveter un jeu de microcontrôleur en Python, si votre code a dépassé la formule «un moule, une requête, un résultat» - je vous dirai Je recommande fortement de séparer les widgets de manière décisive de toute logique de leur travail, et il y a alors une chance qu'il y ait moins de mouches dans vos côtelettes. Et malgré la parfaite non-évidence initiale des avantages d'une telle solution, plus vous travaillez avec elle, plus ces avantages vous apparaîtront.

Source: https://habr.com/ru/post/fr417885/


All Articles