Programación AHA

Rate this content
Bookmark

¿Eres el tipo de programador que prefiere no ver el mismo código en dos lugares, o haces uso liberal de copiar/pegar? Muchos desarrolladores juran por la filosofía de No Repetirte (DRY) mientras que otros prefieren Escribir Todo Dos Veces (WET). Pero, ¿cuál de estos produce bases de código más mantenibles? He visto cómo ambos enfoques arruinan las bases de código y tengo una nueva ideología que me gustaría proponerte: Evitar Abstracciones Precipitadas (AHA). En esta masterclass, hablaremos sobre la abstracción y cómo puedes mejorar una base de código aplicando y creando abstracciones de manera más reflexiva, así como cómo salir de un lío de sobre o sub-abstracción.

Kent C. Dodds
Kent C. Dodds
32 min
02 Aug, 2021

Video Summary and Transcription

La masterclass discute el concepto de programación AHA, que enfatiza las abstracciones reflexivas. Presenta un ejemplo codificado en vivo del ciclo de vida de una abstracción y demuestra cómo corregir errores y mejorar las abstracciones. Se destaca la importancia de evitar las abstracciones complejas y el valor de la duplicación sobre la abstracción incorrecta. La masterclass también proporciona ideas sobre cómo construir las abstracciones correctas y ofrece recursos para un aprendizaje más profundo.

Available in English

1. Introducción a la Programación AHA

Short description:

Hola a todos. Mi nombre es Kent C. Dodds y estoy súper emocionado de hablarles virtualmente. Estoy emocionado de hablarles sobre la programación AHA. Así que adelante y hablemos sobre evitar abstracciones apresuradas, programación AHA. Tengo algunos enlaces aquí que podrían ser interesantes para ustedes. Tengo un sitio web en la World Wide Web. Y, en particular, testingjavascript.com. Si aún no lo han probado o lo han visto, definitivamente échenle un vistazo. Y epicreact.dev va a ser aún más grande. Una gran cantidad de contenido estará disponible para ustedes en epicreact.dev en un futuro muy cercano.

Hola a todos. Mi nombre es Kent C. Dodds y estoy súper emocionado de hablarles virtualmente. Espero que todos estén sanos, felices y bien. Y estoy emocionado de hablarles sobre la programación AHA. Así que adelante, tomen sus principios de programación secos y húmedos, déjenlos a un lado por un momento y hablemos sobre evitar abstracciones apresuradas, programación AHA.

Así que tengo algunos enlaces aquí que podrían ser interesantes para ustedes. A diferencia de mis diapositivas. Y les hablo desde Utah. Tengo una esposa, cuatro hijos y un perro y son increíbles. Tengo un sitio web en la World Wide Web. Y, en particular, testingjavascript.com. Si aún no lo han probado o lo han visto, definitivamente échenle un vistazo. Les enseñará todo lo que sé sobre testing, que no es poco. Y epicreact.dev va a ser aún más grande. Una gran cantidad de contenido estará disponible para ustedes en epicreact.dev en un futuro muy cercano. Así que esperen eso. Echen un vistazo al resto de esto más tarde.

2. Introducción al Ciclo de Vida de la Abstracción

Short description:

Este es un ejemplo en vivo y forzado del ciclo de vida de una abstracción. Vamos a considerar qué es importante y por qué es importante ser reflexivo sobre una abstracción. Es como un ejemplo real de una historia contada por Sandy Metz en esta publicación de blog, The Wrong Abstraction.

Vamos a seguir adelante y entrar en esto. Esto es lo que vamos a cubrir hoy. Este es un ejemplo en vivo y forzado del ciclo de vida de una abstracción. Espero que puedas relacionarte con esto, aunque es un poco forzado. Pero creo que lo disfrutarás de todos modos.

Y vamos a considerar qué es importante y por qué es importante ser reflexivo sobre una abstracción. Y básicamente vamos a tomar esta historia... Es como un ejemplo real de una historia contada por Sandy Metz en esta publicación de blog, The Wrong Abstraction, que te recomiendo encarecidamente que leas.

No vamos a pasar por diapositivas. La mayor parte de esto está en mi editor de texto aquí, y no es consumible de forma pasiva. Así que necesitas decidir ahora mismo si vas a centrarte en Twitter o en mi charla. Porque no podrás hacer ambas cosas muy eficazmente. Así que elige. No me ofende.

3. Corrigiendo el Error del Nombre en Pantalla

Short description:

Así que aquí estamos en 02.js. Tenemos una aplicación con un objeto de usuario llamado Phil. Hay un error donde dice Philip undefined en lugar de Rodrigues. Se nos ha encomendado la tarea de solucionar este problema. En lugar de arreglar el error en varios lugares, vamos a crear una abstracción llamada GetDisplayName para solucionarlo automáticamente.

Así que aquí estamos en 02.js. Y voy a estar usando una herramienta llamada CuocaJS. Es una extensión para VS Code. Entre otras cosas, me permite hacer console log aquí y mostrará en azul cuál es el valor de esa declaración de log. Así que vamos a estar usándolo bastante.

Así que tenemos una aplicación y tenemos un objeto de usuario aquí. Este es Phil. Y Phil tiene un nombre y un nombre de usuario. Y en tres lugares diferentes de nuestra aplicación tenemos code para obtener el nombre de usuario de ese usuario para el primer y último nombre. Así que este es su nombre en pantalla que vamos a mostrar en toda la UI de nuestra aplicación. Ahora bien, es posible que te des cuenta de que en realidad tenemos un error aquí y esta es la primera parte de la abstracción. Aquí estamos diciendo Philip undefined. Pero el nombre de Philip es Rodrigues. Ese es su apellido. Y está un poco frustrado porque dice Philip undefined cuando se conecta a nuestra aplicación.

Y así se nos ha encomendado la tarea de solucionar este problema. Y cuando trabajaba en una empresa antes, recuerdo que decían, Oye, tenemos Así que voy a arreglarlo. Y luego el probador manual de QA allí diría, Oye, Kent, pensé que dijiste que lo arreglaste ¿no? Y yo decía, sí, lo hice. Dijo, bueno, está roto por aquí. Oh, vaya. Sí, supongo que eso fue copiado y pegado. Así que vamos a arreglarlo también por allí. Y fue un verdadero dolor. Así que construimos abstracciones para no tener que arreglar el mismo error en muchos lugares. Y tenemos tres lugares donde estamos haciendo exactamente lo mismo. Así que en lugar de arreglar el error aquí, ¿qué tal si simplemente hacemos una abstracción y lo colocamos en un lugar y entonces todos los demás lugares se arreglarán automáticamente. Así que vamos a hacer eso. Voy a hacer una función aquí llamada GetDisplayName. Tomaremos un usuario y luego devolveremos esto y lo generalizaremos. Así que tomaremos ese usuario, obtendremos el nombre y en lugar del primero y último, haremos primero y último.

4. Mejorando la Abstracción para el Honorífico

Short description:

Reemplazamos todas las ocurrencias de getDisplayName con la nueva función para Phil, solucionando el error en un solo lugar. Sin embargo, ahora necesitamos agregar soporte para el honorífico en la página de perfil. Como ya tenemos una abstracción en su lugar, es natural mejorarla para soportar el nuevo caso de uso. Añadiremos una opción 'includeHonorific' a la función, por defecto será false para evitar romper los usuarios existentes. Esto es solo una refactorización regular sin ningún cambio aún.

Así que vamos a reemplazar todas estas con getDisplayName para Phil y luego lo arreglaremos en este último lugar. Ta-da, y todos los lugares fueron arreglados. Estamos muy contentos con esto porque significa que no tenemos que arreglarlo en todos los otros lugares. Solo lo arreglamos en este lugar y si alguna vez queremos hacer cambios, podemos simplemente hacer cambios a esta única función, lo cual es genial.

Bueno, resulta que realmente necesitamos hacer algunos cambios y eso es si en la página de perfil decidimos que queremos incluir el honorífico. Digamos que el Dr. Philip Rodriguez dice, oye, sería realmente genial si mi página de perfil dice que soy un doctor. Como fui a mucha escuela, quiero que la gente sepa que soy un doctor. El gerente de producto viene a ti y dice, oye, queremos agregar el honorífico a la página de perfil allí, el nombre en pantalla, y tú dices, está bien, genial. Así que vienes al code y dices, oh, sí, escribí esta abstracción para esto. Entonces, porque la abstracción existe, nuestra inclinación natural es ir a la abstracción para mejorar la abstracción para soportar el nuevo caso de uso y también para ver si ya soporta el nuevo caso de uso. Así que estamos naturalmente inclinados a ir a la abstracción primero. Y vemos esto y vemos, oh, no hay soporte para honorífico, así que podría eliminar la abstracción aquí o agregar ese caso de uso a esta abstracción existente. Es realmente natural para nosotros preferir usar la abstracción existente por varias razones. Tal vez pensamos que otras personas podrían beneficiarse de este caso de uso extra, o tal vez simplemente sentimos que, ya que ya estamos usando la abstracción, no quiero, ya sabes, alejarme de todos los beneficios que me da la abstracción. Y en un escenario del mundo real, eso podría ser bastante. Y entonces, sí, no necesariamente querrías simplemente eliminar la abstracción solo para agregar una característica. Parece mucho más fácil simplemente mejorar la abstracción para soportar el caso de uso. Así que eso es lo que vamos a hacer. Y lo que haremos es que tomaremos opciones. Pero no todos van a pasar opciones, ¿verdad? Así que vamos a poner eso por defecto a un objeto. Y no quiero simplemente llamar a esto opciones. Vamos a desestructurar esto. Y simplemente tomaremos e incluiremos honorífico. Y lo pondremos por defecto en falso. No queremos romper a los usuarios existentes de esta abstracción. Así que diremos incluir honorífico aquí. Tomaremos un nombre en pantalla y devolveremos el nombre en pantalla. Así que eso es solo una refactorización regular. Aún no hemos cambiado nada.

5. Mejorando la Abstracción con Nombre de Usuario

Short description:

Ahora tomaremos ese nombre para mostrar y, si hay include honorific, incluiremos el honorífico. Lo tenemos. Reutilizamos la abstracción. Vamos a escribir algunas pruebas unitarias para asegurarnos de no romper esta característica. En el futuro, necesitamos soportar un nombre de usuario para la tarjeta de usuario. Añadiremos esta característica a la abstracción incluyendo el nombre de usuario.

Ahora tomaremos ese nombre para mostrar. Y si hay include honorific, entonces diremos que el nombre para mostrar es lo que es. Lo pondremos en un literal de plantilla allí. Pero incluiremos el honorífico. Así que diremos user.name.honorific. Genial.

Y luego aquí en la página de perfil, podemos decir include honorific. Sí. Y boom. Lo tenemos. Estamos muy contentos con esto. Hacemos commit de eso. Lo hacemos revisar. Y la gente dice, wow, genial. Reutilizamos la abstracción. Así que aprovechemos todo el poder que tenemos con esta abstracción.

Vamos a escribir un par de unit tests para asegurarnos de no romper esta característica que hemos añadido. Y seguimos adelante. Y en el futuro, alguien viene y dice, hey, necesitamos soportar un nombre de usuario para la tarjeta de usuario. Así que queremos que diga su nombre, y luego entre paréntesis, su nombre de usuario. Y entonces dices, está bien, eso debería ser bastante sencillo. Vamos a la abstracción de nuevo. Vemos que no está soportado. Y en lugar de eliminar la abstracción de nuestro code, vamos a añadir esta característica a la abstracción. Pero no queremos romper lo existente, así que vamos a tocar lo menos posible. Y simplemente añadiremos otra opción aquí para include user name. Y lo pondremos por defecto en falso porque no queremos romper a los usuarios existentes de esta abstracción. Y diremos si include user name, excepto que tienes que deletrearlo correctamente, de lo contrario no funcionará. Y diremos que el nombre para mostrar es el nombre para mostrar tal como es actualmente, y luego entre paréntesis, y luego cualquiera que sea el nombre de usuario, así que user dot user name. Genial, y luego aquí abajo podemos decir include user name true.

6. Evolución de la Abstracción y Complejidad de las Pruebas

Short description:

Añadimos pruebas para soportar diferentes combinaciones de opciones. Más tarde, recibimos una solicitud de característica para mostrar la inicial en lugar del primer nombre. Modificamos la abstracción para soportar este nuevo caso de uso sin romper el código existente. Sin embargo, los casos de uso soportados por la abstracción han divergido significativamente. Escribir pruebas para casos de uso inexistentes puede complicar la refactorización futura.

Perfecto, esto es exactamente lo que querían. Fuimos capaces de codificar eso en la abstracción y añadimos un par de pruebas para asegurarnos de que esto está soportado. Y en realidad, en el proceso de añadir pruebas, nos damos cuenta de que hay algunas combinaciones de estas opciones que no soportamos o que no necesitamos en nuestra code base pero nuestra abstracción soporta y tal vez nos damos cuenta de eso, tal vez no, pero sabemos que esos casos de uso están soportados donde podrías proporcionar ambos como verdaderos.

Y entonces añadimos pruebas para eso sólo para asegurarnos de que nadie rompe esa característica existente. En caso de que alguien quiera usar esa característica en el futuro. Y así no es demasiado complicado. Es una función pura, es realmente fácil de probar y así que vamos adelante y añadimos una prueba para eso. Y luego, más tarde, recibimos otra solicitud de característica para este code y dicen, hey, nuestra navegación, queremos que ese primer nombre no sea un primer nombre, sino una primera inicial. Y entonces vuelves a la abstracción, dices, está bien, eso no está soportado hoy. No quiero perder los beneficios de tener la abstracción, está bien probada. Así que voy a añadir mis cosas aquí, pero no quiero romper nada que ya esté ahí. No quiero romper el code existente. Así que voy a tomar una primera inicial, la pondré por defecto en falso, así los usuarios existentes de esta abstracción no se rompen, y tomaremos esa primera inicial como una opción. Y diremos, si la primera inicial, entonces queremos que el primer nombre sea sólo la primera inicial. Así que lo que voy a hacer, es que sacaremos esto, lo llamaremos primero. Y en realidad lo asignaremos a un let aquí para primero igual nombre de usuario primero. Y entonces si la primera inicial es verdadera, entonces diremos, primero en realidad va a ser igual a la primera, y cortaremos el primer carácter y añadiremos un punto. Vale, genial. Y entonces podemos bajar aquí y decir, incluir o en realidad es una primera inicial es verdadera. Y boom, tenemos todos estos casos de uso soportados por nuestra abstracción, añadimos un par más de pruebas aquí, y estamos realmente contentos con esto.

Ahora hay dos cosas que quiero señalar sobre esto. En primer lugar, ahora tenemos tres usos de esta abstracción, y tal vez hay más a lo largo de la code base, pero estos tres no se parecen en nada. No tienen nada en común entre sí. Aparte del hecho de que algunos de ellos muestran el primer y el último nombre, pero cada uno de ellos tiene diferencias muy distintas de los demás. Y así como esto es en realidad bastante común que ocurra a las abstracciones es que eventualmente La abstracción evoluciona más allá del caso de uso inicial, y eso no es necesariamente malo cosa, pero todos los casos de uso han divergido entre sí bastante significativamente. Y así, aunque nuestra abstracción soporta tantas cosas, en realidad están soportando casos de uso que no están totalmente relacionados entre sí. El otro problema con esto es que mientras estamos escribiendo pruebas para esto, vamos a estar escribiendo pruebas para soportar casos de uso que en realidad no tenemos. Y aunque eso tal vez no sea una cosa terrible, aquí está el problema con eso. A medida que escribimos todas estas pruebas para probar casos de uso, cuando entramos a refactorizar esto si queremos hacer mejoras a ello, entonces tenemos que asegurarnos de que nuestras refactorizaciones soportan todo lo que nuestras pruebas dicen que nuestra abstracción soporta.

7. Evitando y Corrigiendo la Complejidad de la Abstracción

Short description:

La prueba tiene como objetivo asegurar que los casos de uso que necesitas soportar se mantengan continuamente soportados. Al agregar características sin pensar, terminamos en una situación complicada. A menudo mantenemos código y características innecesarias debido al bajo costo y al alto riesgo de eliminarlas. Dejar código no utilizado en su lugar requiere mantenimiento. Terminamos con una abstracción complicada con la que es difícil trabajar. Sandy Metz sugiere reintroducir la duplicación y eliminar selectivamente el código innecesario como una forma de evitar o solucionar este problema.

Pero la única cosa que se preocupa por ese caso de uso es la prueba, por lo que existe por sí misma. Y eso es súper inútil. La prueba tiene como objetivo asegurar que los casos de uso que necesitas soportar se mantengan continuamente soportados y si el único que se preocupa por ello no son los usuarios sino las pruebas, entonces simplemente elimina la prueba y ahora a nadie le importa.

Y así, al agregar características a esta abstracción sin pensar, terminamos en una situación realmente complicada y no se detiene aquí. No, tenemos más por hacer. ¿Qué pasa si la página de perfil ya no quiere el honorífico? Entonces decimos, está bien, sí, eso está bien. Podemos simplemente eliminar el honorífico, boom, se ha ido, estamos contentos, guardamos esto, lo confirmamos, lo empujamos, se fusiona, estamos contentos con esto porque todo lo que se necesitó fue eliminar esa opción. Y esto es lo que normalmente sucede y en realidad no pensamos en sacar la opción honorífica y deshacernos del code que es específico para el honorífico o tal vez sí pensamos en eso y hay un par de otras razones por las que podríamos no querer eliminarlo. Por un lado, el costo de mantenerlo en su lugar es bastante bajo, ¿verdad?, o se siente bajo y el riesgo de eliminarlo y romper accidentalmente algo, eso en realidad se siente alto y entonces con ese análisis de costo versus riesgo allí simplemente decidimos, vamos a mantenerlo allí, no quiero romper nada.

Hacemos esto mucho con CSS en particular, como CSS global. Prefiero añadir algo nuevo que modificar algo existente o, Dios no lo quiera, eliminar algo existente porque es muy difícil identificar si realmente se está utilizando. Y luego siempre está la cosa persistente en la parte de atrás de tu mente como, tal vez algún día querremos incluir el honorífico en el futuro así que simplemente dejaremos esa característica y entonces nadie tendrá que hacer ningún cambio para soportar ese caso de uso en el futuro. Y eso también es problemático porque tenemos Git y podemos volver atrás y mirar lo que el code era en ese momento. Así que no es una cosa sin costo dejar este code en su lugar porque tenemos que mantenerlo a medida que hacemos refactorizaciones si lo dejamos en su lugar. Y el único que se preocupa de que este code exista es el code y la prueba en sí misma así que si los eliminamos entonces a nadie le importa y eso está bien.

Pero aún no hemos terminado. ¿Qué pasa si nuestra tarjeta de usuario aquí en lugar del primer y último nombre deciden, hey, en realidad solo quiero mostrar el último nombre. Ahora hacer eso con lo que tenemos aquí es realmente fácil. Simplemente eliminamos la abstracción y luego decimos fill.username() pero porque la abstracción existe simplemente nos atrae y pensamos, ¿sabes qué? En lugar de incluir el nombre de usuario tendré un solo nombre de usuario y luego aquí arriba aceptaré eso solo nombre de usuario. Lo pondremos por defecto en falso para que no rompamos a otras personas y no quiero tocar ninguna de estas cosas. Simplemente vamos a añadir esto aquí al final y diremos solo nombre de usuario display name equals user.username() y ahí vamos, tenemos soporte para esta nueva característica y ahora tenemos dos opciones que a nadie le importan excepto al code en sí y a las pruebas que se escribieron para asegurarnos de que no rompemos esos casos de uso. Así que hemos terminado con una abstracción que es en realidad bastante más complicada de lo que necesita ser y podemos refactorizarla pero ahora tenemos todas estas pruebas que están asegurando que no rompemos estos casos de uso que en realidad no nos importan y así es simplemente se convierte en un lío enredado y esta es una función bastante simple, solo está concatenando cadenas juntas. Piensa en tus complicados componentes de React o tus componentes de Angular o lo que sea que estás escribiendo y todas estas diferentes abstracciones que has construido alrededor de esto y es bastante fácil construirte una abstracción que da miedo trabajar con ella. Y entonces, ¿cómo evitamos este problema o cómo salimos de este problema cuando estamos en él? Y esto es algo de lo que Sandy Metz habla en su post de blog, La Abstracción Equivocada. Realmente te aconsejo que le eches un vistazo porque es realmente genial y tiene una masterclass aquí que puedes ir y ver y darle un vistazo, pero aquí lo que dice es que la forma más rápida de avanzar es retroceder. Así que la idea es primero reintroduces la duplicación al poner en línea y luego con cada color usas los parámetros que se pasan para determinar el subconjunto del code en línea que es específico para los colores, lo que ejecuta el color y luego borras los bits que no son necesarios para ese color en particular. Y así, en este caso, eso básicamente significa que haremos tres copias de getDisplayName y lo pondremos en línea en cada uno de estos y luego eliminaremos las piezas de cada uno de esos que ya no son necesarios. Así que vamos a repasar eso muy rápido. Lo que voy a hacer es console.log aquí mismo y solo necesito tener un console.log aquí mismo que es el mismo que este. Y el nuestro es bastante simple así que realmente no necesito hacer una función separada.

8. Incorporando la Abstracción

Short description:

Simplemente miraré la función y tomaré las piezas que necesito. Así que aquí solo necesitamos la primera inicial y luego el apellido. Así que eso es prácticamente todo este code es todo lo que necesito para esto. Así que lo que haré es tomar esto aquí. Y vamos a obtener el primero de fill.name.first. Y luego el resto de esto está aquí. Así que tomemos eso. Y en lugar de usuario eso va a ser fill. Ahora esta situación o este archivo de navegación ya no está utilizando la abstracción. Incorporaremos la abstracción en todos los lugares donde se utiliza y luego podemos eliminarla. Para el siguiente, añadiremos un console.log y obtendremos el nombre y apellido de fill.name.first y fill.name.last. Para el último, solo necesitamos el nombre de usuario de fill.username. Ahora que has identificado las similitudes entre diferentes abstracciones y las diferencias, eres más reflexivo sobre la abstracción que estás haciendo. Recuerda, la duplicación es mucho más barata que la abstracción equivocada.

Simplemente miraré la función y tomaré las piezas que necesito. Así que aquí solo necesitamos la primera inicial y luego el apellido. Así que eso es prácticamente todo este code es todo lo que necesito para esto. Así que lo que haré es tomar esto aquí. Lo pondremos justo allí. Y vamos a obtener el primero de fill.name.first. Vale, eso nos da nuestro p punto. Y luego el resto de esto está aquí. Así que tomemos eso. Y en lugar de usuario eso va a ser fill. Vale, esas dos cosas son las mismas, así que podemos tomar esto ahora y ponerlo en lugar de la abstracción. Ahora esta situación o este archivo de navegación ya no está utilizando la abstracción y podríamos entrar aquí y eliminar las cosas que ya no se están utilizando, pero sigamos incorporando la abstracción en todos los lugares donde se utiliza y luego podemos eliminarla.

Así que el siguiente es solo el nombre y el apellido y eso está aquí o no es esta parte aquí. Así que tomemos eso, añadiremos un console.log aquí y el primero vendrá de fill.name.first y esto será fill.name.last y vamos a necesitar poner eso en una plantilla literal. Ahí vamos. Genial y eso es exactamente lo que necesitamos, así que simplemente reemplazaremos eso, nos desharemos de eso y ahora hemos eliminado la abstracción de ese y luego para nuestro último solo es el nombre de usuario y todo lo que estamos utilizando de la abstracción para esto es solo user.username. Así que bajaremos aquí y eso es tan fácil que solo voy a decir fill.username. ¡Tada! Ahí está. Tenemos exactamente lo mismo que teníamos antes y resulta que podemos eliminar todo esto Se ha ido de nuestro código, esa cosa realmente grande y aterradora de la que estabas preocupado se ha ido y tal vez lo tienes todo en línea como esto o tal vez era un gran componente y tienes como cuatro copias diferentes del mismo componente que son solo ligeramente diferentes para cada caso de uso. Ahora que tienes esas cuatro copias diferentes, puedes ver las similitudes entre algunas de ellas y tal vez son dos categorías diferentes de esa misma abstracción. Está la que muestra el desplegable y luego está la categoría que no lo hace y así que simplemente mantendremos esas cosas como separadas. Sea cual sea el caso, pero porque has hecho esto, eres capaz de identificar las similitudes entre las diferentes abstracciones y las diferencias y en tu estado actual de construcción esto hoy, estás mucho más capacitado para crear una abstracción que funcione para lo que tenemos hoy. has experimentado, tienes algunas cicatrices de batalla en malas abstracciones, eres más reflexivo sobre la abstracción que estás haciendo.

Así que con todo esto, solo quiero terminar con un par de conclusiones, en primer lugar, no te repitas o DRY no es necesariamente algo malo, no te repitas en teoría es una buena idea porque nos permite deshacernos de algunos errores de lógica de negocio en un lugar o incluso algunos errores tipográficos si no estás usando TypeScript pero realmente puede ayudarte a evitar alguna duplicación. Como la duplicación no es inherentemente mala, pero puede ser un problema y puede propagar un montón de errores por todas partes. Así que no te repitas por sí mismo no es necesariamente malo. Pero la clave aquí es que no puedes prever el futuro. Así que lo único para lo que realmente deberías estar optimizando es el cambio. Así que una cosa de la que habla Sandy Mintz es que la duplicación es mucho más barata que la abstracción equivocada. Así que prefiere la duplicación sobre la abstracción equivocada.

9. Construyendo las Abstracciones Correctas

Short description:

A medida que duplicas el código y esperas que surjan las similitudes, las abstracciones correctas se vuelven más obvias. Continúa duplicando el código y luego identifica las similitudes. Si hay ramas de código compartidas, refactoriza en lugar de agregar más condicionales. Aprende sobre los usuarios y divide la abstracción en piezas manejables.

Estoy completamente de acuerdo con eso y creo que a medida que duplicas cosas y simplemente esperas que las similitudes en ese code duplicado te griten para la abstracción, entonces esas abstracciones se vuelven mucho más obvias para ti y puedes construir la abstracción correcta para los casos de uso que tienes presentes en ese momento. Entonces, mientras estás construyendo cosas y tienes todas estas ideas como, oh genial abstracción aquí, genial abstracción allí, simplemente sigue duplicando cosas. Copia y pega, muévelo y luego, una vez que hayas terminado, puedes ver lo que tienes y ves las similitudes y dices, oh en realidad estas dos cosas no son tan comunes como pensé cuando quise abstraerlas por primera vez. Así que me alegro de no haberlo hecho. Simplemente los dejaremos como cosas separadas o, estas dos cosas son realmente comunes, hay solo tres cosas que podría parametrizar y luego puedes hacer una abstracción para ello. Si tienes code compartido con muchas ramas, entonces te recomiendo que resistas el impulso de agregar más condicionales y en su lugar refactorízalo primero. Y ve y aprende todo lo que puedas sobre los usuarios de esa abstracción y tal vez hay algo que puedes aprender sobre la abstracción en su conjunto para que puedas dividir la abstracción en múltiples piezas que serán más fáciles de manejar por sí mismas.

QnA

Recursos y Preguntas y Respuestas sobre la Programación Aha

Short description:

Así que tengo un par de recursos para ti. Sandy Metz dio una charla llamada All the all the little things. Tengo una entrada de blog sobre la Programación Aha y una variante de pruebas. Sígueme en Twitter. Gracias. La charla de Kent sobre la Programación Aha siempre es maravillosa. Hagamos algunas preguntas y respuestas. Kent comparte el origen de Aha y las frustraciones con la programación seca y la creación de abstracciones.

Así que tengo un par de recursos para ti. Sandy Metz dio una charla que es realmente buena en torno a esta misma idea llamada All the all the little things. Definitivamente échale un vistazo. Y luego, por supuesto, la entrada del blog también es genial. Y luego tengo una entrada de blog sobre este concepto de Programación Aha que puedes consultar en mi blog. Y tengo una variante de testing de eso también. Y sí, sígueme en Twitter porque tuiteo cosas. Muchas gracias. Espero que tengas un tiempo maravilloso en la conferencia. Mantente feliz, mantente saludable y sí, suscríbete. Gracias.

Muy bien. Eso fue excelente. Kent, como siempre, fue una charla maravillosa. Si eres nuevo en el concepto de Programación Aha, creo que es algo genial. Siempre me encanta ver lo que hace Kent. Y ahora traigamos a Kent de vuelta al escenario y haremos algunas preguntas y respuestas. Tenemos algunas preguntas geniales en el Slack. Kent, bienvenido de nuevo. Gracias. Gracias. Estoy muy emocionado de estar aquí. Siempre disfruto pasando tiempo contigo, Jason y nuestros 4,000 amigos o cuantas personas estén viendo ahora mismo. Sí, creo que estamos por encima de 4,000 ahora mismo en la transmisión en vivo. Así que santo cielo. Tenía una pregunta porque te he seguido durante mucho tiempo y recuerdo el origen de Aha, así que te voy a poner un poco en el apuro. Pero Aha no siempre se llamó Aha. ¿Puedes hablar un poco sobre los orígenes de cómo llegaste hasta ahora? Sí, así que Aha fue algo así como mis frustraciones con la programación seca como practicante al principio. Aprendí sobre no repetirte a ti mismo y lo importante que es que crees abstracciones para las cosas. Y luego descubrí lo que creo que la mayoría de la gente descubre con eso es que eventualmente las abstracciones que creas son realmente malas.

Introducción a la Programación AHA Continuada

Short description:

Y luego escuché sobre la programación húmeda, que es escribir todo dos veces. Y también me frustró eso porque entonces tienes que arreglar errores en varios lugares. Y así pensé que ambos eran demasiado dogmáticos. Y entonces decidí ser más consciente de las abstracciones que hacemos y entonces todo será mejor, esperemos. Eso es genial. Mencionaste esto brevemente, pero quiero hablar, bueno, en realidad, sabes qué respondiste. No voy a decirte, hablaste sobre la diferencia entre seco y AHA. Así que vamos al Slack y alguien pregunta, hay una gran pregunta aquí. ¿Cómo implementas esto como proyecto? Como si fueras a implementar esto en un proyecto dado, ¿cómo lo incorporas a tu proceso? Esa es una gran pregunta. Creo que es tan tentador cuando estamos como, si estás comenzando un proyecto completamente nuevo o estás entrando en un proyecto y estás como, vaya, mira el lío de abstracciones que tenemos aquí o lo que sea. Es tan tentador para ti querer arquitectar todo desde el principio. Y eso es un error enorme que cometer. Automáticamente, tienes una base de código de 3000 líneas de código hasta ahora, y la estás arquitectando para una base de código de tres millones de líneas.

Y luego escuché sobre la programación húmeda, que es escribir todo dos veces. Y también me frustró eso porque entonces tienes que arreglar errores en varios lugares. Y así pensé que ambos eran demasiado dogmáticos. Y entonces decidí ser más consciente de las abstracciones que hacemos y entonces todo será mejor, esperemos.

Y así, en el proceso de escribir una entrada de blog sobre esto, porque tengo que escribir un blog que pienso, decidí, bueno, no es seco. No es húmedo. ¿Qué no son esas cosas? Supongo que es húmedo. Y así es como lo llamé al principio, era húmedo. Y realmente no me gusta el sonido de esa palabra. Y sé que a mucha gente le parece realmente desagradable. Pero estaba como, está bien. Y realmente no podía pensar en lo que eso podría significar. Así que ni siquiera hice un acrónimo de eso. Y tuiteé sobre ello y conseguí que mucha gente dijera que es tan asqueroso. Estaban riendo histéricamente por ello. Así que estaba como, está bien, está bien, necesito pensar en un nombre diferente. Y Cher Scarlet me dio un nombre perfecto. Y AHA, Evita las Abstracciones Precipitadas, era perfecto. Y fue como un momento de bombilla. Me encanta por cada, ya sabes, es simplemente el acrónimo perfecto. Así que de ahí es de donde vino.

Eso es genial. Mencionaste esto brevemente, pero quiero hablar, bueno, en realidad, sabes qué respondiste. No voy a decirte, hablaste sobre la diferencia entre seco y AHA. Así que vamos al Slack y alguien pregunta, hay una gran pregunta aquí. ¿Cómo implementas esto como proyecto? Como si fueras a implementar esto en un proyecto dado, ¿cómo lo incorporas a tu proceso? Esa es una gran pregunta. Creo que es tan tentador cuando estamos como, si estás comenzando un proyecto completamente nuevo o estás entrando en un proyecto y estás como, vaya, mira el lío de abstracciones que tenemos aquí o lo que sea. Es tan tentador para ti querer arquitectar todo desde el principio. Y eso es un error enorme que cometer. Automáticamente, tienes una base de code de 3000 líneas de code hasta ahora, y la estás arquitectando para una base de code de tres millones de líneas.

Enfoque Iterativo y Evitando Malas Abstracciones

Short description:

Adopta un enfoque iterativo y no te preocupes por la duplicación. Si te encuentras con malas abstracciones en una base de código, intégralas y finge que siempre han sido así. Sé reflexivo y evita intentar arquitecturar toda la aplicación para lo que no es hoy.

Vas a terminar en malas abstracciones y nunca llegarás a esas tres millones de líneas en la base de code. Al menos no una en la que quieras trabajar. Así que recomiendo simplemente tomar un enfoque realmente iterativo. No te preocupes por la duplicación y sabes, si entras en una base de code y tiene malas abstracciones, entonces lo que hablo en la masterclass y haciendo referencia a Sandy Metz allí, integra esas abstracciones y luego, como puedes fingir que siempre ha sido así y estás como, oh wow, hay una abstracción justo aquí para mí. Pero será totalmente diferente de la mala que integraste antes. Así que al menos espero que lo sea. Pero eso es lo que recomendaría es simplemente ser realmente reflexivo sobre todo el proceso. No intentes arquitecturar toda tu aplicación, para algo que no es hoy.

Considerando la Abstracción y la Duplicación de Código

Short description:

En el contexto de la abstracción, es importante considerar si extenderla o crear múltiples funciones. Copiar el código inicialmente ayuda a determinar si la abstracción es necesaria o si el código no es tan similar como se pensaba. Un ejemplo es tener botones de inicio de sesión y registro similares con diferentes atributos. Crear un componente con muchas propiedades puede no ser más simple que la duplicación. La implementación puede diferir incluso si el código visualmente parece el mismo. Agregar más propiedades para ligeras diferencias crea más trabajo. El costo de una mala abstracción puede ser peor que duplicar el código y los errores. Sin embargo, es un tema matizado y no debe interpretarse como un disgusto por la abstracción.

Entonces, una pregunta aquí que es, creo, en el contexto de una abstracción, ¿sientes que la abstracción no debería extenderse o sería mejor simplemente extenderla y ver qué sucede hasta que termines con tres o cuatro funciones y luego cambies? Entonces, tal vez no estoy entendiendo completamente la pregunta pero mi proceso de pensamiento normalmente, esto es algo por lo que realmente tuve que luchar, pero mientras trabajo en algo de code antes de haber comprometido algo solo estoy jugando con cosas, estoy pensando constantemente, oh, esto se parece mucho a esto y entonces, simplemente pongamos eso en una función. Y realmente tuve que luchar contra mí mismo y decir, no, no, no, no, no hagas eso todavía. Solo copia, incluso si son como cinco líneas de code, parece tan duplicado, solo copia y pega eso porque eventualmente descubrirás una de dos cosas. Descubrirás que no lo necesitabas en absoluto en primer lugar y entonces, como tomar el tiempo para hacer la abstracción y crear los nombres de las variables y la generalización de esa función fue una pérdida de tiempo de todos modos o descubres que no eran tan similares como pensabas que eran. Entonces sí, no sé si eso responde a la pregunta porque tal vez la entendí mal, pero eso es, sí.

Me gustaría hacer un seguimiento de eso en realidad. Entonces, cuando dices que te das cuenta de que no son tan similares como pensabas que eran, ¿tienes como un ejemplo? Porque siento que eso es una de esas cosas que es fácil de decir en abstracto y difícil de poner en términos concretos. Entonces, si alguien está pensando en esto, ¿cuándo es el caso en que el mismo code, code que has copiado y pegado no es tan similar como pensamos que es.

Sí, esa es una gran pregunta. Entonces, un ejemplo de esto que acabo de experimentar recientemente y especialmente es una conferencia de React, entonces, un ejemplo de React, tenía un botón de inicio de sesión y un botón de registro, muy similares, solo palabras diferentes y diferentes etiquetas ARIA para el modal, aparecen colores diferentes y cosas así. Y pensé, ¿sabes qué? Estos son realmente similares. Podría hacer un componente de React, solo toma un par de propiedades, pero me he abstenido. Y descubrí que si fuera a hacer un componente para esto, habría tantas pequeñas propiedades que son como, esto es lo que debería ser la etiqueta ARIA, este es el título del modal, este es el tipo de botón que debería ser. Y simplemente no veo que este tipo de abstracción sea más simple que la duplicación que tengo en su lugar. Es como si cada uno fuera seis o siete líneas de code. Ahora hay una pequeña pieza allí que el modal que aparece tiene un pequeño botón de cierre que está diseñado específicamente para los modales de inicio de sesión y registro. Y entonces todo lo que hice para eso fue que extraje el CSS para eso porque no hay como variables o nada, no el CSS, sino el JSX para eso. Entonces, simplemente creé un elemento JSX y luego enlacé ese elemento como una variable. Y entonces, como puedo tomar esa pequeña pieza de similitud sin hacerlo un componente de función completo que tiene como 12 propiedades en él. Y sabes, esa es una distinción realmente interesante también porque en ambos casos, estás hablando de code que visualmente se vería igual. Como lo que aparece en el navegador, visualmente se ve igual. Es un botón de cierre o es un formulario de registro, pero la implementación es donde la diferencia comienza a aparecer. Si tienes que cambiar cada parte de esos atributos, no estás realmente escribiendo una abstracción, solo te estás dando tareas.

Sí, exactamente. Y luego, cada vez que quieres hacer algo que los hace ligeramente diferentes, tienes que agregar otro argumento, otra propiedad, y es solo más tarea para ti. Y al final del día, lo que terminas teniendo es JSX copiado y pegado que son solo dos copias de casi lo mismo o un componente de función que estás llamando que es casi la misma cantidad de líneas de propiedades. Entonces, ¿qué te estás comprando allí? No mucho, solo tareas. Totalmente, totalmente. Bueno, entonces otra pregunta siguiendo eso. ¿Es el costo de una mala abstracción generalmente mucho peor que el de duplicar el code en las pruebas y posiblemente duplicar los errores? ¿Cuál ha sido tu experiencia con eso? Esa es una gran pregunta, y es bastante matizada porque no quiero que nadie se vaya de mi charla diciendo, oh, a Kent le gusta la duplicación, odia la abstracción.

El Valor de la Abstracción y la Duplicación

Short description:

Como autor de bibliotecas, veo el valor de la abstracción, pero llega un punto en el que la duplicación se convierte en un problema. Si te encuentras duplicando en muchos archivos, puede haber un buen caso para una abstracción. No hay una regla estricta para esto, ya que es matizado.

Eso absolutamente no es el caso. Como autor de bibliotecas, claramente, hago muchas bibliotecas y veo el valor de la abstracción. Solo veo que, llega un punto en el que la duplicación se convierte en un problema real. Para este ejemplo de inicio de sesión y registro que acabamos de compartir, como esa duplicación, está justo allí, y si hay un error en uno, es realmente fácil simplemente corregir el error en el otro, no es demasiado problema, pero si te encuentras duplicando en muchos, muchos archivos, entonces quizás haya un buen caso para una abstracción allí. Así que no puedo darte una regla, porque realmente no hay una regla sobre esto, todo es solo un poco matizado, y sí. Lo siento, eso no es muy útil, pero espero que la masterclass lo haya sido. No, creo que eso es genial. Y con eso, vamos a empezar a avanzar, eso es todo el tiempo que tenemos. Kent, muchas gracias, siempre es un placer, y nos vemos en el Slack. Muy bien, nos vemos. Muy bien, adiós. Gracias. Muy bien, adiós. Adiós. Adiós.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Don't Solve Problems, Eliminate Them
React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Top Content
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
Using useEffect Effectively
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
Design Systems: Walking the Line Between Flexibility and Consistency
React Advanced Conference 2021React Advanced Conference 2021
47 min
Design Systems: Walking the Line Between Flexibility and Consistency
Top Content
Design systems aim to bring consistency to a brand's design and make the UI development productive. Component libraries with well-thought API can make this a breeze. But, sometimes an API choice can accidentally overstep and slow the team down! There's a balance there... somewhere. Let's explore some of the problems and possible creative solutions.
React Concurrency, Explained
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
TypeScript and React: Secrets of a Happy Marriage
React Advanced Conference 2022React Advanced Conference 2022
21 min
TypeScript and React: Secrets of a Happy Marriage
Top Content
TypeScript and React are inseparable. What's the secret to their successful union? Quite a lot of surprisingly strange code. Learn why useRef always feels weird, how to wrangle generics in custom hooks, and how union types can transform your components.
Jotai Atoms Are Just Functions
React Day Berlin 2022React Day Berlin 2022
22 min
Jotai Atoms Are Just Functions
Top Content
Jotai is a state management library. We have been developing it primarily for React, but it's conceptually not tied to React. It this talk, we will see how Jotai atoms work and learn about the mental model we should have. Atoms are framework-agnostic abstraction to represent states, and they are basically just functions. Understanding the atom abstraction will help designing and implementing states in your applications with Jotai

Workshops on related topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Hooks Tips Only the Pros Know
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React, TypeScript, and TDD
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Web3 Workshop - Building Your First Dapp
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
Nader Dabit
Nader Dabit
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
Remix Fundamentals
React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Top Content
Featured WorkshopFree
Kent C. Dodds
Kent C. Dodds
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:- Create Remix Routes- Style Remix applications- Load data in Remix loaders- Mutate data with forms and actions