Architecture propre pour le front-end



Le web moderne est compliqué. Le nombre de frameworks et le rythme de leur développement font galoper le développeur. Quelqu'un en utilise de nouveaux, quelqu'un lit des livres de mode. Mais parfois, la lecture et l'énergie consacrées à l'approfondissement de l'architecture, OOP, TDD, DDD, etc. ne répondent pas aux attentes. Et parfois, les livres prêtent à confusion! Et même, le pire, ils soulèvent incroyablement le FAC!

J'oserai exposer de manière simple l' idée principale de l'architecture pure par rapport au frontend. J'espère que cela sera utile pour les personnes qui veulent lire ce livre et pour ceux qui l'ont déjà lu, mais n'utilisent pas les connaissances acquises dans la vie réelle. Et pour ceux qui sont intéressés par la façon dont j'ai traîné le front end ici.

Motivation


La première fois que j'ai lu la FAQ, c'est environ un an et demi avant d'écrire un article sur les conseils d'un des développeurs seniors. Avant cela, j'ai été très impressionné par les courts extraits de Pure Code adaptés pour JavaScript ( https://github.com/ryanmcdermott/clean-code-javascript ). J'ai gardé cet onglet ouvert pendant six mois pour appliquer les meilleures pratiques dans mon travail. De plus, mes premières tentatives de lecture du Clean Code d'origine ont échoué. Peut-être parce qu'il adhère trop aux caractéristiques des projets front-end, ou parce que la lecture devrait être renforcée par une pratique à long terme. Néanmoins, le Cheka est un guide pratique que vous pouvez prendre et appliquer immédiatement à la fonction écrite (je vous recommande fortement de le lire d'abord si vous n'êtes pas familier).

Mais avec TA, c'est de plus en plus compliqué - voici des ensembles de principes, de lois et de conseils pour construire le programme dans son ensemble. Il n'y a pas de détails que vous pouvez prendre immédiatement et zayuzat dans le composant. Ce livre est conçu pour changer la façon dont vous écrivez des logiciels et vous donner des outils et des mesures mentaux. C'est une erreur de considérer que le ChA n'est utile qu'aux architectes, et je vais essayer de le transmettre à l'aide d'un exemple adapté au front-end.

Logique métier et frontend




En ce qui concerne ChA, de nombreuses personnes dessinent des cercles dans leur imagination (voir la figure sous le titre), des projets de taille gigantesque, une logique métier incroyablement complexe et un tas de questions - quel genre de papa mettre YuzKeysy? L'idée de l'applicabilité des principes de ChA à la création d'une composante accordéon laisse perplexe. Mais les problèmes qui se posent lors du développement d'interfaces modernes nécessitent une attitude sérieuse. Les interfaces modernes sont complexes et souvent douloureuses. Tout d'abord, découvrons ce qui est le plus important sur le front-end.

Tout le monde sait depuis longtemps que vous devez séparer la logique métier d'une présentation et respecter les principes SOLID. L'oncle Bob de la SHC vous en parlera en détail. Mais qu'est-ce que la logique métier? R. Martin propose plusieurs définitions et sous-catégories; l'une d'elles sonne approximativement Donc:
La logique métier (règles métier) sont des règles qui rapportent de l'argent aux organisations même sans automatisation.
En général, la logique métier est quelque chose de très important. (J'entends des backenders glousser quand ils entendent parler de la logique métier par le devant). Mais je suggère que les avant-gardistes se détendent un peu et se souviennent de ce qui peut être très important chez nous? Et aussi étrange que cela puisse paraître, la chose la plus importante à l'avant est l'interface utilisateur. La première étape pour comprendre l'AA pour moi a été de réaliser que la logique d'interface devrait être au centre du cercle avant! (fig. sous le titre).

Je comprends qu'il s'agit d'une déclaration non fondée, et on peut fortement y contester. Mais rappelons-nous que ce qui change souvent et douloureusement à l'avant? Je ne sais pas pour vous, mais on me demande le plus souvent de changer le comportement des éléments interactifs - accordéons, moules, boutons. Il convient de noter que la disposition (conception) change beaucoup moins fréquemment que le comportement de l'interface. Les changements et les acteurs ( initiateurs des changements ) sont particulièrement discutés dans l'AP , note.

Moule méchant


Ne nous embêtons pas beaucoup pour la terminologie. Nous donnons un exemple et clarifions un peu ce que j'appelle la logique d'interface.

Il existe quelques entrées avec validation et mappage conditionnel. Vous ne pouvez remplir qu'un seul champ et le formulaire est valide, mais des entrées facultatives apparaîtront. (Faites attention, peu nous importe le type de données. L'essentiel est l'interactivité)





J'espère que la logique est claire. Et au début, la mise en œuvre ne soulève pas de questions. Vous insérez cette chose dans un composant de votre framework et la réutilisez audacieusement sous d'autres formes en tant que partie intégrante et indépendante. Quelque part, vous devez passer des drapeaux afin de modifier légèrement la validation, quelque part une petite mise en page, quelque part les fonctionnalités de connexion au formulaire parent. En général, codez sur de la glace mince. Et une fois, vous obtenez une tâche sous cette forme (et vous l'utilisez) et la gelez pendant quelques jours, même si cela semble être de 15 minutes. Merde le gestionnaire, les moules et les tâches ennuyeuses ennuyeuses.

Où est l'erreur? Il semblerait que vous ayez travaillé pendant plus d'une journée, réfléchi très bien à la composition des composants, essayé différents hockeys, transmis des modèles via des accessoires, conjuré avec le cadre de construction des formes, même essayé de suivre SOLID lors de l'écriture de ces composants.

Remarque: composants en ChA! == composants en react / angular et co.

Mais le fait est que vous avez oublié de mettre en évidence la logique. Calmez-vous un peu, revenez à la tâche et jouez à la simulation.

Tâche trop simple


L'AN souligne que l'architecture est essentielle pour les grands projets. Mais cela ne nie pas l'utilité des approches ChA pour les petites tâches. Il nous semble que la tâche est trop simple pour parler de l'architecture d'une certaine forme. Et comment désigner un moyen d'apporter des changements, sinon par l'architecture? Si vous ne définissez pas les limites et les composants de l'interface interactive, il sera encore plus facile de vous embrouiller. Rappelez-vous avec quelles pensées vous prenez la tâche de changer la forme à votre travail.

Mais passons aux choses sérieuses. Quelle est cette forme? Nous essayons de modéliser, d'exprimer des pensées avec un pseudo-code.

ContactFormGroup
  +getValue()
  +isValid()

À mon avis, toute notre tâche pour le monde extérieur est de créer un objet avec deux méthodes. Cela semble facile - comme ça. Nous continuons à décrire ce que nous voyons et ce qui nous intéresse.

ContactFormGroup
  emailFormGroup
  phoneFormGroup
  getValue()
    => [emailFormGroup.getValue(), phoneFormGroup.getValue()]
  isValid()
    => emailFormGroup.isValid() || phoneFormGroup.isValid()

Probablement, cela vaut la peine d'indiquer explicitement l'apparition d'entrées mineures. Lorsqu'un gestionnaire vous demande de faire rapidement la 10e modification du formulaire, tout semble simple dans sa tête - tout comme ce pseudo-code.

EmailFormGroup
  getValue()
  isValid()
  isSecondaryEmailVisible()
    => isValid() && !!getValue()

Pouvons-nous repérer un endroit pour des demandes étranges ...

PhoneFormGroup
  getValue()
  isValid()
  isSecondaryPhoneVisible()
    => isValid() && today !== ‘sunday’

Une des implémentations de notre formulaire sur Angular pourrait ressembler à ceci.

Implémentation de ContactFormGroup (angulaire)
export class ContactFormGroup {
    emailFormGroup = new EmailFormGroup();
    phoneFormGroup = new PhoneFormGroup();

    changes: Observable<unknown> = merge(this.emailFormGroup.changes, this.phoneFormGroup.changes);

    constructor() {}

    isValid(): boolean {
        return this.emailFormGroup.isValid() || this.phoneFormGroup.isValid();
    }

    getValue() {
        return {
            emails: this.emailFormGroup.getValue(),
            phones: this.phoneFormGroup.getValue(),
        };
    }
}

export class EmailFormGroup {
    emailControl = new FormControl();
    secondaryEmailControl = new FormControl();

    changes: Observable<unknown> = merge(
        this.emailControl.valueChanges,
        this.secondaryEmailControl.valueChanges,
    );

    isValid(): boolean {
        return this.emailControl.valid && !!this.emailControl.value;
    }

    getValue() {
        return {
            primary: this.emailControl.value,
            secondary: this.secondaryEmailControl.value,
        };
    }

    isSecondaryEmailVisible(): boolean {
        return this.isValid();
    }
}


Ainsi, nous obtenons trois interfaces (ou classes, pas importantes). Vous devez placer ces classes dans un fichier séparé à un endroit bien en vue afin de pouvoir comprendre les parties mobiles de l'interface simplement en y regardant. Nous avons identifié, tiré et souligné la logique problématique, et maintenant nous contrôlons le comportement du formulaire, combinant la mise en œuvre de parties individuelles de ContactFormGroup. Et les exigences pour différents cas d'utilisation peuvent être facilement représentées comme des objets séparés.

Cela semble être une implémentation standard du modèle MVC, et rien de plus. Mais je ne rejetterais pas les choses élémentaires qui, dans la pratique, ne sont pas du tout respectées. Le fait n'est pas que nous avons extrait un morceau de code de la vue. Le fait est que nous avons mis en évidence la partie importante qui est sujette à changement et décrit son comportement afin qu'il devienne simple.

Total


ChA nous parle des lois de l'écriture de logiciels. Il donne des métriques par lesquelles nous pouvons distinguer les parties importantes des parties mineures et diriger correctement les dépendances entre ces parties. Décrit les avantages de la POO et des approches pour résoudre les problèmes par le biais de la modélisation.

Si vous souhaitez améliorer la qualité de vos programmes, les rendre flexibles, utiliser la POO dans votre travail, apprendre à gérer les dépendances dans votre projet, parler dans le code de la solution au problème et non des détails de votre bibliothèque, alors je vous recommande fortement de lire Clean Architecture. Les conseils et les principes de ce livre sont pertinents pour n'importe quelle pile et paradigme. N'ayez pas peur des expériences sur vos tâches. Bonne chance

PS À propos de la gestion de l'État


Un très gros obstacle à la compréhension de NA peut être un engagement envers une bibliothèque de gestion de l'État. En fait, des bibliothèques telles que redux / mobx résolvent simultanément la tâche d'aviser les composants des changements. Et pour certains développeurs, un front sans gestionnaire d'état est quelque chose d'impensable. Je crois que les principes de la ChA peuvent être appliqués avec et sans l'utilisation d'un gestionnaire d'État. Mais en vous concentrant sur la bibliothèque de gestion de l'État, vous perdrez inévitablement une partie de la flexibilité. Si vous pensez en termes de ChA et OOP, le concept de gestion de l'État disparaît généralement. La mise en œuvre la plus simple sans gestion d' état est ici habr.com/en/post/491684

PPS


Honnêtement, j'ai montré la solution à une tâche d'interface similaire à mon ami - il ne l'a pas appréciée et a tout réécrit pour les hooks de réaction. Il me semble que, dans une plus large mesure, le rejet est dû au fait que la POO n'est pratiquement pas utilisée dans les projets réels, et la plupart des jeunes développeurs frontaux n'ont pas la moindre expérience des solutions de POO. Lors des entretiens, ils posent parfois des questions sur SOLID, mais souvent uniquement pour éliminer les candidats. De plus, les rafales de développement dans le domaine de l'OLP dans certaines équipes peuvent être supprimées par une revue. Et il est souvent plus facile pour les gens de trier une nouvelle bibliothèque que de lire un livre ennuyeux ou de défendre leur droit de retirer la logique d'un composant. Veuillez soutenir les activistes de la POO :)

All Articles