Uno de los problemas más comunes en los proyectos de código JavaScript es que nuestro código es demasiado complejo. A medida que los proyectos y sus requisitos evolucionan, la complejidad se va introduciendo. El exceso de complejidad ralentiza el progreso, frustrándonos mientras intentamos mantener grandes fragmentos de un programa en nuestra cabeza solo para entender qué está sucediendo.
¡Para conquistar la complejidad, debemos refactorizar! En esta charla, investigaremos cómo identificar la complejidad innecesaria en nuestra base de código utilizando la complejidad cognitiva como medida, cómo abordar la refactorización de código complejo y qué herramientas están disponibles para ayudarnos a refactorizar. Lo pondremos todo en práctica a través de un ejemplo en vivo. Al final de la charla, estarás emocionado por abordar esa monstruosidad de una función de 1000 líneas en tu propia base de código (ya sabes cuál).
This talk has been presented at JSNation 2024, check out the latest edition of this JavaScript Conference.
FAQ
AstroDB es una base de datos vectorial sin servidor desarrollada por Datastacks, diseñada para ser utilizada en la construcción de aplicaciones generativas de AI.
Phil Nash es un ingeniero de relaciones con desarrolladores en Datastacks, la empresa detrás de AstroDB.
Puedes encontrar a Phil Nash en redes sociales como Twitter y Mastodon, así como en LinkedIn.
La complejidad ciclomática es una métrica de software que mide el número de caminos a través de una función. Se asigna una puntuación basada en la cantidad de bucles y condicionales dentro de la función.
La complejidad cognitiva mide cómo los humanos perciben la complejidad del código. Se calcula aumentando la puntuación cada vez que hay una interrupción en el flujo de una función, añadiendo puntos extra por anidamiento.
La complejidad ciclomática mide el número de caminos a través de una función, útil para determinar el número de pruebas necesarias. La complejidad cognitiva, por otro lado, se enfoca en cómo los humanos entienden el código, considerando la anidación y la interrupción del flujo.
Para manejar la complejidad, se recomienda entender dónde se localiza la complejidad, aplicar métricas como la complejidad cognitiva, y si es necesario modificar el código, realizar una refactorización que simplifique la estructura antes de hacer cambios sustanciales.
Las pruebas son cruciales en la refactorización, ya que permiten verificar que el comportamiento del código no cambie a pesar de las modificaciones en su estructura interna. Las pruebas deben cubrir el comportamiento existente del código para asegurar la integridad del mismo.
La charla de hoy explora la complejidad en el código y su impacto. Se discuten diferentes métodos para medir la complejidad, como la complejidad ciclomática y la complejidad cognitiva. Se enfatiza la importancia de comprender y conquistar la complejidad, con una demostración que muestra la complejidad en una base de código. La charla también profundiza en la necesidad de cambio y el papel de la refactorización en el manejo de la complejidad. Se comparten consejos y técnicas para la refactorización, incluido el uso de características y herramientas del lenguaje para simplificar el código. En general, la charla brinda información sobre cómo gestionar y reducir la complejidad en el desarrollo de software.
Hoy quiero hablar sobre la complejidad en nuestro código. Nuestros trabajos son complejos ya que tenemos que modelar cosas de la vida real en lenguajes de programación. Vamos a explorar qué significa la complejidad y cómo afecta a nuestro código.
¿Qué tal, todos? Mi nombre es Phil Nash y soy un ingeniero de relaciones con desarrolladores en Datastacks. Datastacks es la empresa detrás de AstroDB, que es una base de datos vectorial sin servidor que puedes usar para construir tus aplicaciones generativas de AI. Nuevamente, mi nombre es Phil Nash. Si necesitas encontrarme en cualquier lugar de internet, estaré como Phil Nash, en Twitter, Mastodon, cualquier red social que estés usando en este momento, incluso LinkedIn, ¡Dios mío! De todos modos, lo que quiero hablarles hoy es la complejidad, la complejidad en nuestro código. Así que empecemos hablando de lo que quiero decir con complejidad. Verás, nuestros trabajos son complejos. A menudo tenemos que modelar cosas de la vida real en el medio de JavaScript o TypeScript u otro tipo de lenguaje. Y el mundo en sí mismo es inherentemente complejo, y luego nosotros simplemente agregamos a eso al intentar convertirlo en código. Y el código, por lo tanto, es inherentemente complejo.
2. Medición de la Complejidad y Complejidad Ciclomática
Short description:
Nuestro trabajo es gestionar la complejidad y necesitamos un método para medirla en nuestro código. Veamos la complejidad de las funciones a través de ejemplos. La complejidad ciclomática, inventada en 1976, asigna una puntuación a una función basada en sus puntos de ruptura de flujo, como bucles y condicionales.
Lo que queremos evitar es agregar más complejidad a nuestras aplicaciones de la que el problema que estamos tratando de resolver demanda en sí mismo. Y en última instancia, esto significa que nuestro trabajo se convierte en gestionar la complejidad. Si podemos mantenernos al tanto de esta complejidad, entonces nuestras bases de código se mantienen sanas, fáciles de entender y fáciles de trabajar a lo largo del tiempo y de los cambios de equipo y cosas así. Así que nuestro trabajo es gestionar la complejidad. Sin embargo, el año pasado en otras conferencias, di una charla en la que investigué los cinco principales problemas en proyectos de JavaScript que podrían descubrirse mediante análisis estático, y en el número dos estaba el hecho de que la complejidad de las funciones en nuestros proyectos era demasiado alta. Y eso es un problema. Por eso quería dar esta charla, para superar eso. Y entonces realmente la pregunta es, ¿qué es demasiado alto? Necesitamos un método para medir nuestra complejidad en nuestro código. ¿Y cómo podríamos hacer eso? ¿Cómo medimos la complejidad?
Bueno, en primer lugar, permítanme, si les mostrara un fragmento de código, si les mostrara una función como esta, una suma de números primos, y les preguntara qué tan compleja es, piensen en qué responderían y qué tan útil sería eso. Obviamente hay cierta complejidad aquí. Tenemos algunos bucles. Tenemos algunas condicionales. Estamos tratando con números primos. Eso será complejo. Y luego tenemos esta otra función. Esta es una función get words. Pasamos un número y devuelve palabras como uno, un par, unos pocos, muchos o muchos. Es una gran declaración switch. ¿Qué tan compleja es esta? Bueno, ha habido formas de medir la complejidad que se han inventado a lo largo de los años. En 1976 se inventó la complejidad ciclomática. La complejidad ciclomática asigna una puntuación a una función basada en un par de cosas. Principalmente suma puntuaciones cuando una función tiene una interrupción en el flujo. Es decir, cuando hay un bucle o un condicional en su mayoría. Y así, si observamos nuestra función de suma de números primos, la complejidad ciclomática realmente asigna una puntuación de uno por ser una función. Todo comienza como uno. Así que comienza allí arriba. Y luego asignamos uno por este primer bucle for. Hay un segundo bucle for que suma uno. Hay un condicional.
3. Complejidad Cognitiva y Puntuación Anidada
Short description:
En última instancia, la complejidad ciclomática y la complejidad cognitiva tienen resultados diferentes. Mientras que la complejidad ciclomática mide el número de caminos a través de una función, la complejidad cognitiva considera la comprensibilidad y lectura del código. Incrementa la puntuación por cada interrupción en el flujo y también realiza un seguimiento de la anidación. La función de suma de números primos se utiliza como ejemplo para ilustrar estos conceptos.
Y luego hay otra condicional en la parte inferior. Por lo tanto, en última instancia, esta función obtiene una puntuación de cinco. ¿Compleja? Bastante compleja. Lo descubriremos. Sin embargo, la función get words también obtiene una puntuación de uno por ser una función. Y luego, debido a que es una declaración switch, obtiene una puntuación de uno por cada caso en el switch. Y hay cuatro de esos casos. Por lo tanto, en última instancia, get words también obtiene una puntuación de cinco. Y no estoy seguro de estar de acuerdo en que get words y sum of primes sean necesariamente equivalentes en complejidad. Entonces tal vez haya algo que podamos hacer con nuestra complejidad ciclomática. Sobre nuestra complejidad ciclomática que podría ser mejor. La complejidad ciclomática es útil. Mide el número de caminos a través de una función. Y eso es realmente útil si quieres saber cuántas pruebas necesitas para cubrir esa función y todas las funcionalidades o ramas potenciales. Pero no cubre realmente cómo medimos la comprensibilidad, cómo nosotros, como humanos, al leer code realmente lo entendemos. Y así, la gente de Sona en 2016 creó una puntuación llamada complejidad cognitiva. Esta es una puntuación que estaba más destinada a enfocarse en cómo pensamos acerca del code y cómo lo leemos y lo puntuamos de esa manera. Y así, la complejidad cognitiva se puntúa de manera similar a la complejidad ciclomática. Aún así, al final del día, obtendrá un número, pero esta vez incrementa la puntuación cada vez que se produce una interrupción en el flujo. Pero también mantiene la idea de una puntuación de anidación en su mente. Y cada vez que se incrementa, se suma uno más la puntuación de anidación actual. Y eso genera un resultado diferente. Y es bastante interesante. Y así, si volvemos a nuestra función de suma de números primos, lo que vemos es que ya no tenemos que puntuar por ser una función. La puntuación mínima aquí es cero, pero puntuamos uno por este primer bucle. Y luego incrementamos la puntuación de anidación en uno. Entonces, cuando llegamos al segundo bucle obtiene una puntuación de dos y la puntuación de anidación se incrementa nuevamente cuando llegamos a la condicional. Y esa puntuación es tres porque está anidada dos veces y luego hay una interrupción. Luego, agregaríamos uno más a la anidación, pero luego no tenemos más interrupciones dentro de ella. Entonces, restamos uno por salir de la condicional, restamos uno por salir del bucle.
4. Conquistando la Complejidad y Demostración
Short description:
La complejidad cognitiva de la función suma de primos es ocho, mientras que la función obtener palabras obtiene una puntuación de uno. Comprender la complejidad es crucial. Evitar dar vueltas y construir una pila compleja de consideraciones es algo que queremos evitar. Para conquistar esta complejidad, necesitamos identificar dónde se encuentra. Lo demostraré con una demostración rápida utilizando el cliente AstraDB escrito en TypeScript. Agregué complejidad a la función insertar muchos, superando el umbral establecido por Sonalint.
Llegamos a la siguiente condicional. Por lo tanto, obtiene una puntuación de dos porque está anidada una vez. Y luego, eventualmente, salimos completamente hasta que la puntuación final sea ocho. Por lo tanto, la complejidad cognitiva de la función suma de primos es ocho, pero nuestra función obtener palabras, que creo que acordamos que es menos compleja anteriormente, ahora solo obtiene una puntuación de uno. Es una gran declaración switch. Tenemos que considerar un valor y un número de cosas que hacer con él, pero solo estamos mirando un valor en cualquier momento. Y por eso obtiene una puntuación de uno. Y creo que eso tiene más sentido para la forma en que pensamos acerca de las cosas, la forma en que entendemos code. Para mí, el modelo de esto era como una pila de cosas en tu cerebro que tienes que considerar mientras lees partes de code. Y a medida que avanzas en algo como la suma de primos, terminas agregando cosas a la pila a medida que avanzas. Y terminamos teniendo que saber y entender en todo momento que tenemos dos variables de bucle y estamos dentro de una condicional, y eso es bastante complejo. Como es obvio, puede ser peor que esto. Y luego también hay un poco de dar vueltas mientras salimos de la pila y luego agregamos cosas nuevamente. Y tenemos que seguir trabajando para saber qué está en nuestra pila cerebral, qué realmente tenemos que considerar en este punto durante la parte de comprensión del code. Y una vez que finalmente todo se despeja, vamos a respirar aliviados porque llegamos al final de la función. Pero evitar dar vueltas y construir cosas en una pila cerebral como esa es el tipo de cosas que queremos evitar. Entonces, ¿cómo conquistamos esta complejidad? Eso es lo que el resto de esta charla va a ser como vencer eso. Y el primer paso para conquistar esa complejidad es comprender dónde está la complejidad. Les he dado esta puntuación de complejidad cognitiva, pero ahora tenemos que poder aplicar eso a nuestro code. Y así, aquí hay una demostración rápida para mostrar eso. Entonces, lo que hice fue ingresar a esto es el cliente AstraDB de código abierto escrito en TypeScript para lidiar con instancias de AstraDB. Resultó que en realidad no había nada tan complejo aquí. Entonces, tuve que agregar algunas cosas. Entonces, elegí la función más compleja y luego agregué más cosas para empeorarlo. Así que, por favor, no culpen a las otras personas que escribieron esta maravillosa biblioteca. Entonces, lo que hice fue mirar la función insertar muchos. Y aquí tengo en VS code ejecutando Sonalint, que es lo que estaba usando para ver la complejidad cognitiva antes. Y esto me dice que esta función tiene una complejidad de 34 sobre los 15 permitidos. Y así, ese es el tipo de umbral en el que Sonalint se enfoca en la complejidad cognitiva. Y tiene 13 ubicaciones en las que
5. Analizando la Complejidad y la Necesidad de Cambio
Short description:
Agregamos cosas a la pila y analizamos la complejidad. Comprender la necesidad de cambio es crucial. Solo es necesario cambiar el código complejo si necesita ser modificado.
agregamos complejidad. Agregamos cosas a la pila. Y puedes ver, de hecho, si vas a, si nos desplazamos hasta abajo y presionamos solución rápida, puedes presionar mostrar todas las ubicaciones para esto. Y muestra estos números junto al code donde se agrega complejidad. Entonces, hay esta gran condicional alrededor del exterior. Si hay documentos con los que estamos tratando, entonces continuaremos. Y eso suma uno. Pero luego todo lo demás se anida dentro de él. Entonces, esta condicional suma dos. Esta condicional suma tres porque está anidada dos veces. Esta suma cuatro porque se anidó dentro de este bucle también. Y poder ver esta complejidad es súper útil. El segundo paso, entonces, es no hacer nada. Lo cual me gusta. Soy un desarrollador perezoso. Y si no tengo que hacer nada, eso es genial. Pero el punto aquí es que no tiene sentido cambiar algo.
6. Lidiando con la Complejidad y la Refactorización
Short description:
La complejidad solo es un problema si necesitas cambiar el código. En una base de código antigua, deja el código complejo que no necesita cambiar. La refactorización facilita el cambio de código complejo. Divide el cambio en dos etapas: refactorización y luego hacer la corrección o agregar la funcionalidad. Las pruebas son cruciales para garantizar que la funcionalidad del código siga siendo la misma después de la refactorización.
si es complejo si no necesitas cambiarlo realmente. Esa complejidad solo es difícil para nosotros lidiar con ella cuando tenemos que entender y cambiar ese code. La complejidad solo es un problema si necesitas cambiar el code. Y por lo tanto, si hay diferencias en la base de code, hay diferentes partes que cambian más a menudo que otras. Algunas de ellas se están trabajando activamente. Y eso es lo que debemos prestar atención. Pero en una base de code antigua, probablemente haya fragmentos de code que nunca cambiarán. Y si son complejos, pero no necesitan cambiar, podemos dejarlos así. En realidad, es un riesgo cambiar el code que no necesita ser cambiado solo por la idea de que lo vamos a mejorar de alguna manera. Si ya hace el trabajo que se supone que debe hacer, entonces podemos dejarlo hasta que necesite cambiar. Y luego, si necesita cambiar, recomiendo que limpiemos ese code a medida que avanzamos. ¿Y qué quiero decir con eso? Bueno, creo que esto cuando encontramos que tenemos que cambiar algún code y descubrimos que es demasiado complejo, esa es una buena oportunidad para refactorizar ese code primero y hacer que sea más fácil realizar ese cambio en el futuro. Entonces, podemos dividir esto en dos cosas. Tenemos que cambiar el code. Tenemos que corregir un error o agregar una funcionalidad. Pero es demasiado complejo. Si lo refactorizamos primero, será más fácil cambiarlo para corregir ese error o agregar esa funcionalidad una vez que esté refactorizado. Entonces, la refactorización, les recuerdo, es mejorar cómo funciona una pieza de code sin cambiar lo que esa pieza de code hace. Eso significa que obtenemos el mismo resultado después de una refactorización que antes. Y eso es importante. También es importante que estemos dividiendo este tipo de cambio en dos etapas. Primero la refactorización, donde lo que hace la función no cambia. Y luego más tarde, hacemos la corrección o más tarde, agregamos la funcionalidad. Ahí es cuando realmente cambia su comportamiento. Entonces, ¿cómo sabemos que no cambiamos el resultado de una pieza de code? Bueno, espero que ya estés gritando a la pantalla, pruebas. Definitivamente necesitamos alguna cobertura de prueba aquí para tener confianza en que una vez que hayamos refactorizado algo, siga haciendo lo mismo que estábamos haciendo antes. Y también es importante tener en cuenta que las pruebas en este caso deben asegurarse de que prueben lo que hace una función y no cómo lo hace. Si una prueba depende de la estructura interna de una función o de un fragmento de code, y cambias la estructura interna, entonces esas pruebas se romperán incluso si no rompiste lo que hace la función. Y por lo tanto, las pruebas deben asegurarse de que solo prueben lo que hace la función y no cómo lo hace. Y por lo tanto, si aún no tienes pruebas para un fragmento de code que necesitas refactorizar y cambiar, entonces tu paso 0 en este proceso es escribir esas pruebas, obtener la cobertura de prueba.
7. Consejos y Técnicas de Refactorización
Short description:
Las pruebas deben cubrir el comportamiento existente. Consejos para refactorizar el código: reducir anidamiento, invertir condiciones y salir temprano, colapsar estructura, extraer funciones auxiliares. Ejemplos de características de JavaScript que ayudan con la refactorización.
Y es importante destacar nuevamente, esas pruebas deben cubrir el comportamiento existente. Si estamos corrigiendo un error en un fragmento de code, pero decidimos refactorizarlo primero, entonces esas pruebas deben cubrir todo el comportamiento existente, incluso si es incorrecto. Porque si estamos cambiando la prueba y el code al mismo tiempo, entonces no podemos saber si la refactorización funcionó. Necesitamos escribir las pruebas que aseguren que el code haga lo mismo que la función hacía una vez que lo hayamos refactorizado. Y solo entonces cambiamos la prueba y cambiamos el code para corregir el error. Y luego en ese punto podemos refactorizar. Y así, para la última parte de la charla, quería repasar algunos pequeños tips que nos ayudarán a refactorizar el code frente a esta idea de complejidad y comprensibilidad. Y así, la complejidad cognitiva, obviamente, como puntaje, castiga el code anidado. Cuantas más cosas pongamos en la pila cerebral, empujemos a la pila cerebral, supongo, más complejas se vuelven las cosas. Y por lo tanto, reducir el anidamiento te ayudará a lidiar con eso y simplemente quitar algunas de esas cosas de la pila cerebral y dejarte con menos cosas que considerar mientras lees una función. Y por lo tanto, las cosas que vamos a cubrir en esto son invertir condiciones y salir temprano, colapso estructural, extraer funciones auxiliares y solo un par de pequeñas características de JavaScript que nos van a ayudar con esto también y que son un poco más modernas. Y por lo tanto, invertir condiciones y salir temprano. Esto se refiere a lo primero que te mostré en esa función de inserción múltiple en la que dije que había esta gran condición en el exterior que verifica que la longitud del array de documentos sea mayor que cero. De lo contrario, simplemente devuelve un objeto vacío, en realidad, un recuento de inserción de cero. Esta gran condición alrededor de la función que luego tiene todo lo demás dentro de ella, obviamente, aumenta ese anidamiento. Y si invertimos la condición, es decir, si la longitud del documento es cero o menor que cero, supongo, no va a suceder realmente con un array. Pero si la longitud del documento es cero, entonces podemos devolver inmediatamente nuestro objeto cero y descartar la idea de que esto es un problema. La función luego puede continuar con la seguridad de que estamos tratando con una lista de documentos y eso está bien. Invertir y salir temprano, simplemente, sí, quita cosas de la pila cerebral y significa que no tenemos que considerarlo más adelante en la función. Simplemente quítalo de la pila cerebral. Eso es lo que estoy haciendo. El colapso estructural es algo similar. Estamos tratando de reducir el número de condicionales, especialmente los condicionales anidados, si podemos juntarlos. Y así, en este caso, insert many realmente puede manejar un objeto de opciones que puede tener un array de vectores, y luego intentará combinar esos vectores y documentos. Pero si la longitud de los vectores y la longitud de los documentos no es la misma, entonces eso es un error, porque no van a ir juntos. Pero esto es como condicionales anidados aquí. Y lo que podríamos hacer es juntar ese tipo de cosa para verificar que si tenemos vectores y si los vectores no son iguales a la misma longitud que los documentos, entonces podemos lanzar un error. Y así, esto nos permite, en este caso, salir temprano a través de un error en lugar de seguir anidando y luego podemos dejar que el resto del code continúe. Comprimir ese tipo de cosas en un condicional nos permite, sí, considerar que se ha resuelto mucho más rápido y simplemente quitarlo de la pila cerebral. Extraer métodos auxiliares, creo,
8. Extracción de Métodos Auxiliares y Nomenclatura de Comportamiento
Short description:
La extracción de un método auxiliar es excelente para reducir la repetición y nombrar el comportamiento en el código. Al crear una función separada para manejar una tarea específica, podemos simplificar el código y mejorar su legibilidad. Esto también reduce el anidamiento y nos permite comprender la función sin necesidad de adentrarnos en los detalles de su implementación.
Lo más útil aquí es, de hecho, la extracción de un método auxiliar. Es excelente si tienes repetición en tu código durante una función y no quieres repetir el código, puedes convertirlo en una sola función. Pero también creo que es muy útil para nombrar el comportamiento. En este pequeño extracto, estamos revisando y diciendo: 'ok, si tenemos el array de vectores en nuestro objeto de opciones, entonces vamos a iterar sobre los documentos. Y para cada documento, si hay un vector para él, entonces vamos a convertir ese documento en un documento más un vector'. Pero tenemos que deducir todo eso leyendo el código. Y en realidad, si sacáramos la parte interna, es decir, estamos convirtiendo este documento en un documento y un vector, y lo extrajéramos en una función que simplemente diga 'agregar vector al documento', entonces esta función auxiliar sería bastante simple. Solo estamos tratando con un documento y tal vez un vector, y devolvemos el documento y el vector o solo el documento. Y eso es una cantidad muy pequeña de contexto con la que lidiar. Y luego, si volvemos a la función original, hemos nombrado ese comportamiento. El documento se convierte en un vector y un documento juntos. Y no necesitamos adentrarnos en esa función para entender qué está haciendo. Entonces, lo que hemos hecho es reducir un montón de anidamiento, pero también hemos nombrado el comportamiento para que podamos entenderlo sin leerlo. Y luego, en la función auxiliar real, el contexto es mucho más pequeño, por lo que es más fácil entender la función en sí misma cuando está independiente. Podemos probarla de forma independiente. Y también es menos compleja en sí misma. Nos permite eliminar una gran cantidad de cosas de la pila cerebral en ese caso.
9. Características del Lenguaje y Herramientas
Short description:
Los objetos anidados y el operador de encadenamiento opcional simplifican el código al evitar comprobaciones de indefinido. El operador de fusión de conocimiento reduce los operadores condicionales y ternarios. Exploramos la complejidad cognitiva, reducción de anidamiento, refactorización y el uso de herramientas como Sona Cloud, Sona Cube y Sona Lint. Para mejorar ESLint, instale el complemento Sona JS. Gracias por su atención.
Y finalmente, algunas características del lenguaje que creo que son realmente buenas para esto. Si alguna vez has lidiado con objetos anidados y has tenido que buscar una propiedad en un objeto que está profundamente anidado, probablemente hayas escrito una de estas cadenas de object.first y object.first.second para evitar golpear un indefinido accidentalmente en algún lugar intermedio. Y un operador de encadenamiento opcional es muy útil para eso. Simplifica toda la línea de code y elimina todas esas condiciones booleanas. Realmente útil. Y en segundo lugar, si estás tratando con, digamos, en este caso estamos tratando de asignar a chunk size algo que está en options.chunk size o un valor predeterminado en este caso. Y así estamos comprobando que options.chunk size no sea nulo o indefinido. Y si es alguno de esos dos, obtenemos el valor predeterminado. Y si no, podemos asignarlo a la cosa. Y eso es un lío completo de operadores condicionales y ternarios cuando realmente podríamos usar el operador de fusión de conocimiento que es efectivamente lo mismo que decir no nulo y no indefinido. Y la línea superior aquí establecerá chunk size en el valor predeterminado solo si options.chunk size es nulo o indefinido. Y si lo estuviéramos haciendo dentro del objeto en sí, es aún más fácil con el operador de asignación nula que dice que solo asignaremos esto a un valor predeterminado si chunk size en el objeto original es nulo o indefinido. Muy útil. Aprieta las piezas de code en esos momentos y en este contexto. Y simplemente te ayuda a sacarlo de la pila cerebral. Entonces, para resumir, echamos un vistazo a qué es la complejidad. Básicamente nuestro trabajo es básicamente code. Analizamos la complejidad cognitiva como una forma de medir la complejidad. Y luego analizamos cómo conquistar la complejidad reduciendo el anidamiento, refactorizando primero, asegurándonos de tener cobertura de pruebas, refactorizando y luego realizando el cambio que necesitamos hacer. Hay algunas herramientas que te ayudarán con esto. Entonces, Sona cloud o Sona Cube pueden escanear tu code como parte de tu canalización de CI/CD y detectar problemas como este de complejidad cognitiva. Lo mismo ocurre con Sona Lint. Es gratis instalarlo en tu IDE y mostrará cosas como lo estaba demostrando antes. Y si estás usando ESLint, que no tiene la complejidad cognitiva como puntaje. Pero puedes instalar el complemento de ESLint, Sona JS, que sí lo tiene, y lo agregará a tu ESLint también. Realmente útil. Y eso es todo lo que tengo tiempo para aquí. Nuevamente, mi nombre es Phil Nash. Soy un ingeniero de relaciones con desarrolladores en Datastacks. Y muchas gracias por su atención.
Today's Talk discusses the future of performance tooling, focusing on user-centric, actionable, and contextual approaches. The introduction highlights Adi Osmani's expertise in performance tools and his passion for DevTools features. The Talk explores the integration of user flows into DevTools and Lighthouse, enabling performance measurement and optimization. It also showcases the import/export feature for user flows and the collaboration potential with Lighthouse. The Talk further delves into the use of flows with other tools like web page test and Cypress, offering cross-browser testing capabilities. The actionable aspect emphasizes the importance of metrics like Interaction to Next Paint and Total Blocking Time, as well as the improvements in Lighthouse and performance debugging tools. Lastly, the Talk emphasizes the iterative nature of performance improvement and the user-centric, actionable, and contextual future of performance tooling.
Rome is a toolchain built in Rust that aims to replace multiple tools and provide high-quality diagnostics for code maintenance. It simplifies tool interactions by performing all operations once, generating a shared structure for all tools. Rome offers a customizable format experience with a stable formatter and a linter with over 150 rules. It integrates with VCS and VLSP, supports error-resilient parsing, and has exciting plans for the future, including the ability to create JavaScript plugins. Rome aims to be a top-notch toolchain and welcomes community input to improve its work.
GitHub Copilot is an auto-completion tool that provides suggestions based on context. Research has shown that developers using Copilot feel less frustrated, spend less time searching externally, and experience less mental effort on repetitive tasks. Copilot can generate code for various tasks, including adding modals, testing, and refactoring. It is a useful tool for improving productivity and saving time, especially for junior developers and those working in unfamiliar domains. Security concerns have been addressed with optional data sharing and different versions for individuals and businesses.
Static analysis in JavaScript involves analyzing source code without executing it, producing metrics, problems, or warnings. Data flow analysis aims to determine the values of data in a program. Rule implementation in JavaScript can be straightforward or require extensive consideration of various cases and parameters. JavaScript's dynamic nature and uncertainty make static analysis challenging, but it can greatly improve code quality.
The Talk discusses browser automation using the Worker's Browser Rendering API, which allows tasks like navigating websites, taking screenshots, and creating PDFs. Cloudflare integrated Puppeteer with their workers to automate browser tasks, and their browser rendering API combines remote browser isolation with Puppeteer. Use cases for the API include taking screenshots, generating PDFs, automating web applications, and gathering performance metrics. The Talk also covers extending sessions and performance metrics using Durable Objects. Thank you for attending!
This Talk discusses automating code changes for Android repositories, utilizing tools like JSCodeShift and Abstract Syntax Tree. The speaker shares a real use case example of maintaining a design system library and making changes to a component. The talk emphasizes the importance of automating repetitive tasks and using the power of abstract syntax tree for code changes. The Q&A session covers topics like source code formatting, TypeScript support, and cultural embedding of code mods. The talk concludes with insights on when automation is worth it and the limitations of code mods for monorepo changes.
¿Conoces ese molesto error? ¿El que no aparece localmente? Y no importa cuántas veces intentes recrear el entorno, no puedes reproducirlo. Has revisado las migas de pan, leído la traza de pila y ahora estás jugando al detective para unir los tickets de soporte y asegurarte de que sea real. Únete al desarrollador de Sentry, Ryan Albrecht, en esta charla para aprender cómo los desarrolladores pueden utilizar la Reproducción de Sesiones, una herramienta que proporciona reproducciones de video de las interacciones de los usuarios, para identificar, reproducir y resolver errores y problemas de rendimiento más rápido (sin golpear tu cabeza contra el teclado).
Comments