Le presentamos una traducción de un artículo de Scott Domes, que se publicó en blog.bitsrc.io. Descubra en kat por qué los componentes deben ser lo más pequeños posible y cómo el principio de responsabilidad exclusiva afecta la calidad de las aplicaciones.

Foto
Austin Kirk con
UnsplashLa ventaja del sistema de componentes React (y bibliotecas similares) es que su IU está dividida en partes pequeñas que son fáciles de leer y reutilizables.
Estos componentes son compactos (100-200 líneas), lo que permite a otros desarrolladores comprenderlos y modificarlos fácilmente.
Aunque los componentes, por regla general, intentan ser más cortos, no existe una restricción clara y estricta sobre su longitud. A React no le importará si decide adaptar su aplicación a un componente terriblemente enorme, que consta de 3.000 líneas.
... pero no vale la pena. La mayoría de sus componentes, muy probablemente, ya son demasiado voluminosos, o más bien, realizan demasiadas funciones.
En este artículo demostraré que la mayoría de los componentes (incluso con la longitud habitual de 200 líneas) deberían ser más específicos. Deben realizar solo una función y realizarla bien. Esto es lo que Eddie Osmani dice genial
aquí .
Consejo : cuando trabaje en JS,
use Bit para organizar, ensamblar y reutilizar componentes como piezas de lego. Bit es una herramienta extremadamente efectiva para este negocio, lo ayudará a usted y a su equipo a ahorrar tiempo y acelerar el ensamblaje. Solo inténtalo.
Demostremos cómo, al crear componentes
, algo puede salir mal .
Nuestra aplicación
Imagine que tenemos una aplicación estándar para bloggers. Y esto es lo que hay en la pantalla principal:
class Main extends React.Component { render() { return ( <div> <header> // Header JSX </header> <aside id="header"> // Sidebar JSX </aside> <div id="post-container"> {this.state.posts.map(post => { return ( <div className="post"> // Post JSX </div> ); })} </div> </div> ); } }
(Este ejemplo, como muchos posteriores, debe considerarse como un pseudocódigo).Muestra el panel superior, la barra lateral y la lista de publicaciones. Todo es simple
Como también necesitamos descargar publicaciones, podemos hacer esto mientras se está montando el componente:
class Main extends React.Component { state = { posts: [] }; componentDidMount() { this.loadPosts(); } loadPosts() {
También tenemos cierta lógica por la cual se llama a la barra lateral. Si el usuario hace clic en el botón en el panel superior, el lado saldrá. Puede cerrarlo tanto desde la parte superior como desde el panel lateral.
class Main extends React.Component { state = { posts: [], isSidebarOpen: false }; componentDidMount() { this.loadPosts(); } loadPosts() {
Nuestro componente se ha vuelto un poco más complicado, pero aún así fácil de leer.
Se puede argumentar que todas sus partes tienen un propósito: mostrar la página principal de la aplicación. Entonces seguimos el principio de responsabilidad exclusiva.
El principio de responsabilidad exclusiva establece que un componente debe cumplir solo una función. Si reformulamos la definición tomada de
wikipedia.org , resulta que cada componente debe ser responsable de solo una parte de la funcionalidad [aplicación].
Nuestro componente principal cumple con este requisito. Cual es el problema
Aquí hay una formulación diferente del principio:
cualquier [componente] debe tener una sola razón para el cambio .
Esta definición está tomada del
libro de Robert Martin
, Desarrollo rápido de software. Principios, ejemplos, práctica ", y es de gran importancia.
Al centrarnos en
una razón para cambiar nuestros componentes, podemos crear mejores aplicaciones que, además, serán fáciles de configurar.
Para mayor claridad, vamos a complicar nuestro componente.
Complicacion
Supongamos que un mes después de la implementación del componente Principal, nuestro equipo asignó una nueva característica al desarrollador. Ahora el usuario podrá ocultar una publicación (por ejemplo, si contiene contenido inapropiado).
¡Esto no es difícil de hacer!
class Main extends React.Component { state = { posts: [], isSidebarOpen: false, postsToHide: [] };
Nuestro colega se ocupó fácilmente de esto. Ella solo agregó un nuevo método y una nueva propiedad. Ninguno de los que revisaron la breve lista de cambios tuvo objeciones.
Un par de semanas después, se anuncia otra característica: una barra lateral mejorada para la versión móvil. En lugar de jugar con CSS, el desarrollador decide crear varios componentes JSX que solo se ejecutarán en dispositivos móviles.
class Main extends React.Component { state = { posts: [], isSidebarOpen: false, postsToHide: [], isMobileSidebarOpen: false };
Otro pequeño cambio. Un par de nuevos métodos bien nombrados y una nueva propiedad.
Y aquí tenemos un problema.
Main
todavía realiza solo una función (renderizar la pantalla principal), pero observa todos estos métodos con los que estamos tratando ahora:
class Main extends React.Component { state = { posts: [], isSidebarOpen: false, postsToHide: [], isMobileSidebarOpen: false }; componentDidMount() { this.loadPosts(); } loadPosts() {
Nuestro componente se vuelve grande y voluminoso, es difícil de entender. Y con la expansión de la funcionalidad, la situación solo empeorará.
¿Qué salió mal?
Única razón
Volvamos a la definición del principio de responsabilidad exclusiva:
cualquier componente debe tener una sola razón para el cambio .
Anteriormente, cambiamos la forma en que se muestran las publicaciones, por lo que tuvimos que cambiar nuestro componente Principal. Luego, cambiamos la forma en que se abre la barra lateral, y nuevamente cambiamos el componente Principal.
Este componente tiene muchas razones no relacionadas para el cambio.
Esto significa que realiza demasiadas funciones .
En otras palabras, si puede cambiar significativamente una parte de su componente y esto no conduce a cambios en otra parte, entonces su componente tiene demasiada responsabilidad.
Separación más eficiente
La solución es simple: debe dividir el componente Principal en varias partes. Como hacerlo
Comencemos de nuevo. La representación de la pantalla principal sigue siendo responsabilidad del componente Principal, pero la reducimos solo para mostrar los componentes relacionados:
class Main extends React.Component { render() { return ( <Layout> <PostList /> </Layout> ); } }
Genial
Si de repente cambiamos el diseño de la pantalla principal (por ejemplo, agregamos secciones adicionales), Main también cambiará. En otros casos, no tendremos ninguna razón para tocarlo. Genial
Pasemos al
Layout
:
class Layout extends React.Component { render() { return ( <SidebarDisplay> {(isSidebarOpen, toggleSidebar) => ( <div> <Header openSidebar={toggleSidebar} /> <Sidebar isOpen={isSidebarOpen} close={toggleSidebar} /> </div> )} </SidebarDisplay> ); } }
Esto es un poco más complicado.
Layout
es responsable de representar los componentes del diseño (panel lateral / panel superior). Pero no sucumbiremos a la tentación y le daremos al
Layout
responsabilidad de determinar si la barra lateral está abierta o no.
SidebarDisplay
esta función al componente
SidebarDisplay
, que pasa los métodos o estados necesarios a los componentes
Header
y
Sidebar
.
(El ejemplo anterior es un ejemplo del patrón Render Props via Children en React. Si no está familiarizado con él, no se preocupe. Es importante que haya un componente separado que controle el estado abierto / cerrado de la barra lateral).Y luego, la
Sidebar
sí misma puede ser bastante simple si solo es responsable de representar la barra lateral a la derecha.
class Sidebar extends React.Component { isMobile() {
Nuevamente, resistimos la tentación de insertar JSX para computadoras / dispositivos móviles directamente en este componente, porque en este caso tendrá dos razones para el cambio.
Veamos otro componente:
class PostList extends React.Component { state = { postsToHide: [] } filterPosts(posts) {
PostList
solo cambia si cambiamos la forma en que se representa la lista de publicaciones. Parece obvio, ¿verdad? Esto es exactamente lo que necesitamos.
PostLoader
solo cambia si cambiamos la forma en que se cargan las publicaciones. Y finalmente, la
Post
solo cambia si cambiamos la forma en que se representa la publicación.
Conclusión
Todos estos componentes son pequeños y realizan una pequeña función. Los motivos de los cambios en ellos son fáciles de identificar y los componentes en sí mismos se prueban y corrigen.
Ahora nuestra aplicación es mucho más fácil de modificar: reorganice los componentes, agregue nuevas funciones y amplíe las existentes. Solo necesita mirar un archivo componente para determinar para
qué sirve.
Sabemos que nuestros componentes cambiarán y crecerán con el tiempo, pero la aplicación de esta regla universal lo ayudará a evitar deudas técnicas y a aumentar la velocidad del equipo. La distribución de los componentes depende de usted, pero recuerde:
debe haber una sola razón para cambiar el componente .
¡Gracias por su atención y esperamos sus comentarios!