Arquitectura limpia para el front-end



La web moderna es complicada. La cantidad de marcos y el ritmo de su desarrollo hacen que el desarrollador galope. Alguien usa otros nuevos, alguien lee libros de moda. Pero a veces la lectura y la energía se gastan profundizando en arquitectura, OOP, TDD, DDD, etc. No cumpla con las expectativas. ¡Y a veces los libros son confusos! E incluso, lo peor, ¡aumentan increíblemente el FAC!

Me aventuraré a exponer de manera simple la idea principal de Pure Architecture en relación con la interfaz. Espero que esto sea útil para las personas que desean leer este libro, y para aquellos que ya lo han leído, pero no usan el conocimiento adquirido en la vida real. Y para aquellos que estén interesados ​​en cómo arrastré aquí al frente.

Motivación


La primera vez que leí las preguntas frecuentes es aproximadamente un año y medio antes de escribir un artículo con el asesoramiento de uno de los desarrolladores principales. Antes de eso, estaba muy impresionado con los extractos breves de Pure Code adaptados para JavaScript ( https://github.com/ryanmcdermott/clean-code-javascript ). Mantuve esta pestaña abierta durante seis meses para aplicar las mejores prácticas en mi trabajo. Además, mis primeros intentos de leer el Código limpio original fallaron. Tal vez porque está demasiado adherido a las características de los proyectos front-end, o porque la lectura debe ser reforzada por la práctica a largo plazo. Sin embargo, el Cheka es una guía práctica que puede tomar e inmediatamente aplicar a la función escrita (le recomiendo leerlo primero si no está familiarizado).

Pero con TA, es cada vez más complicado: aquí hay un conjunto de principios, leyes y consejos para construir el programa en su conjunto. No hay detalles que pueda tomar inmediatamente y zayuzat en el componente. Este libro está diseñado para cambiar la forma en que escribe el software y le brinda herramientas mentales y métricas. Es un error considerar que el ChA es útil solo para arquitectos, y trataré de transmitir esto usando un ejemplo adaptado al front-end.

Lógica de negocios y frontend




Cuando se trata de ChA, muchas personas dibujan círculos en su imaginación (vea la figura debajo del encabezado), proyectos de tamaño gigantesco, lógica de negocios increíblemente compleja y un montón de preguntas: ¿qué tipo de papi para poner a YuzKeysy? La idea de la aplicabilidad de los principios de ChA a la creación de un componente de acordeón es desconcertante. Pero los problemas que surgen al desarrollar interfaces modernas requieren una actitud seria. Las interfaces modernas son complejas y a menudo dolorosas. En primer lugar, descubramos qué es lo más importante en el front-end.

Todos saben desde hace tiempo que necesita separar la lógica de negocios de una presentación y observar los principios SOLID. El tío Bob en la CHA le informará sobre esto con gran detalle. Pero, ¿qué es la lógica empresarial? R. Martin ofrece varias definiciones y subcategorías; una de ellas suena aproximadamente Entonces:
La lógica empresarial (reglas comerciales) son reglas que aportan dinero a las organizaciones incluso sin automatización.
En general, la lógica de negocios es algo muy importante. (Escucho a los backenders reírse cuando escuchan sobre la lógica de negocios desde los frentes). Pero sugiero que los favoritos se relajen un poco y recuerden lo que puede ser muy importante en nuestro frente. Y no importa cuán extraño suene, lo más importante en el frente es la interfaz de usuario. ¡El primer paso para entender el AA para mí fue darme cuenta de que la lógica de la interfaz debería estar en el centro del círculo frontal! (fig. debajo del encabezado).

Entiendo que esta es una declaración infundada, y uno puede discutir fuertemente con ella. Pero recordemos que lo que está cambiando en el frente a menudo y dolorosamente? No sé sobre usted, pero a menudo se me pide que cambie el comportamiento de los elementos interactivos: acordeones, moldes, botones. Vale la pena señalar que el diseño (diseño) cambia con mucha menos frecuencia que el comportamiento de la interfaz. Los cambios y los actores ( iniciadores de los cambios ) se discuten especialmente en la AP , nota.

Moho desagradable


No nos molestemos mucho por la terminología. Damos un ejemplo y aclaramos un poco lo que yo llamo la lógica de la interfaz.

Hay un par de entradas con validación y mapeo condicional. Puede completar solo un campo, y el formulario es válido, pero aparecerán entradas opcionales. (Preste atención, no nos importa qué tipo de datos hay. Lo principal es la interactividad)





Espero que la lógica sea clara. Y al principio, la implementación no plantea dudas. Empuja esto en un componente de su marco y lo reutiliza audazmente en otras formas como parte integral e independiente. En algún lugar, debe pasar banderas para cambiar ligeramente la validación, en algún lugar un pequeño diseño, en algún lugar las características de conexión al formulario principal. En general, codifique sobre hielo fino. Y una vez, obtienes una tarea de esta forma (y la usas) y la congelas durante un par de días, aunque parece ser 15 minutos. Maldita sea el gerente, moldes y aburridas tareas aburridas.

¿Dónde está el error? Parece que has estado trabajando durante más de un día, pensaste muy bien en la composición de los componentes, probé diferentes trucos, transmitiste plantillas a través de accesorios, conjuraste con el marco para crear formularios, incluso trataste de seguir SOLID al escribir estos componentes.

Nota: componentes en ChA! == componentes en react / angular y co.

Pero el hecho es que olvidó resaltar la lógica. Cálmate un poco, vuelve a la tarea y juega a la simulación.

Tarea demasiado simple


La AN enfatiza que la arquitectura es crítica para grandes proyectos. Pero esto no niega la utilidad de los enfoques de ChA para tareas pequeñas. Nos parece que la tarea es demasiado simple para hablar de la arquitectura de alguna forma. ¿Y cómo designar una forma de hacer cambios, si no a través de la arquitectura? Si no define los límites y componentes de la interfaz interactiva, será aún más fácil confundirse. Recuerde con qué pensamientos toma la tarea de cambiar la forma en su trabajo.

Pero vayamos al grano. ¿Qué es esta forma? Estamos tratando de modelar, expresando pensamientos con un pseudocódigo.

ContactFormGroup
  +getValue()
  +isValid()

En mi opinión, toda nuestra tarea para el mundo exterior es crear un objeto con dos métodos. Suena fácil, tal como es. Continuamos describiendo lo que vemos y lo que nos interesa.

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

Probablemente, vale la pena indicar explícitamente la aparición de entradas menores. Cuando un gerente le pide que realice rápidamente la décima edición del formulario, todo parece simple en su cabeza, al igual que este pseudocódigo.

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

¿Podemos detectar un lugar para demandas extrañas ...

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

Una de las implementaciones de nuestro formulario en Angular podría verse así.

Implementación de ContactFormGroup (Angular)
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();
    }
}


Por lo tanto, obtenemos tres interfaces (o clases, no importantes). Debe colocar estas clases en un archivo separado en un lugar destacado para que pueda comprender las partes móviles de la interfaz con solo mirarla. Hemos identificado, extraído y enfatizado la lógica problemática, y ahora controlamos el comportamiento del formulario, combinando la implementación de partes individuales de ContactFormGroup. Y los requisitos para diferentes casos de uso se pueden representar fácilmente como objetos separados.

Esto parece ser una implementación estándar del patrón MVC, y nada más. Pero no descartaría cosas elementales que en la práctica no se respetan en absoluto. El punto no es que extrajimos un fragmento de código de la vista. El punto es que hemos resaltado la parte importante que está sujeta a cambios y describimos su comportamiento para que se vuelva simple.

Total


ChA nos cuenta sobre las leyes de escritura de software. Proporciona métricas mediante las cuales podemos distinguir partes importantes de las menores y dependencias directamente correctas entre estas partes. Describe los beneficios de la POO y los enfoques para resolver problemas a través del modelado.

Si desea mejorar la calidad de sus programas, flexibilizarlos, usar OOP en su trabajo, aprender a administrar las dependencias en su proyecto, hablar en el código sobre la solución del problema y no sobre los detalles de su biblioteca, le recomiendo leer Clean Architecture. Los consejos y principios de este libro son relevantes para cualquier pila y paradigma. No tengas miedo de los experimentos en tus tareas. Buena suerte

PD Sobre la gestión del estado


Un obstáculo muy grande para comprender NA puede ser un compromiso con una biblioteca de gestión estatal. De hecho, las bibliotecas como redux / mobx resuelven simultáneamente la tarea de notificar a los componentes sobre los cambios. Y para algunos desarrolladores, un frente sin un administrador estatal es algo impensable. Creo que los principios de ChA pueden aplicarse con y sin el uso de un administrador estatal. Pero al enfocarse en la biblioteca de administración del estado, inevitablemente perderá algo de flexibilidad. Si piensa en términos de ChA y OOP, el concepto de gestión estatal generalmente desaparece. La implementación más simple sin administración del estado está aquí habr.com/en/post/491684

PPS


Honestamente, le mostré la solución a una tarea de interfaz similar a mi amigo: no lo apreciaba y reescribió todo para ganchos de reacción. Me parece que, en mayor medida, el rechazo se debe al hecho de que OOP prácticamente no se usa en proyectos reales, y la mayoría de los desarrolladores front-end jóvenes no tienen la más mínima experiencia con soluciones OOP. En las entrevistas, a veces preguntan sobre SOLID, pero a menudo solo para descartar candidatos. Además, las rachas de desarrollo en el campo de la OLP en algunos equipos pueden ser suprimidas por una revisión. Y a menudo es más fácil para las personas clasificar una nueva biblioteca que leer un libro aburrido o defender su derecho a eliminar la lógica de un componente. Por favor, apoye a los activistas de OOP :)

All Articles