Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Fearless refactors con AST

Sanguino
December 10, 2019

Fearless refactors con AST

Enfréntate a breaking changes y refactors sin miedo. AST (Abstract Syntax Trees) es utilizado por muchos compiladores para parsear el código antes del análisis léxico.

En este meetup queremos mostrar cómo podemos usar el potencial de AST para parsear nuestro código para hacer cambios masivos en nuestro código fuente, sin tener que tratar con las lineas de codigo directamente.

Constará de una parte de explicación de que es AST, donde se usa, codemods, jscodeshift, ejemplos de uso real y una demo de cómo refactorizamos miles de ficheros de un proyecto en pocos minutos.

Comienza a codificar tus refactors!

Sanguino

December 10, 2019
Tweet

Transcript

  1. 1. Find-and-replace (en un directorio completo) para modificar ficheros de

    código. 2. Script con expresiones regulares usando grupos de captura. Técnicas de refactor
  2. 1. Find-and-replace (en un directorio completo) para modificar ficheros de

    código. 2. Script con expresiones regulares usando grupos de captura. Técnicas de refactor
  3. 1. Find-and-replace (en un directorio completo) para modificar ficheros de

    código. 2. Script con expresiones regulares usando grupos de captura. Aquí es donde entran los “codemods” y AST Técnicas de refactor
  4. “Código que modifica código” Se suelen usar para: • Actualizar

    código Fuente manteniendo el “coding style” y convenciones. • Hacer cambios en nuestro código cuando se modifica un API. • Auto-fix del código fuente cuando un paquete público introduce breaking changes. Codemods
  5. Abstract syntax tree An abstract syntax tree is a tree

    representation of the abstract syntactic structure of source code written in a programming language. The syntax is "abstract" in the sense that it does not represent every detail appearing in the real syntax, but rather just the structural or content- related details. - Wikipedia “ “
  6. • Abstract Syntax Trees son estructuras de datos muy utilizadas

    en compiladores, generalmente como resultado de la fase de análisis de sintaxis. • AST se usa intensamente durante el análisis semántico, donde el compilador verifica el uso correcto de los elementos del programa y el lenguaje. • Frente al código fuente, AST no incluye signos de puntuación y delimitadores no esenciales (llaves, punto y coma, paréntesis, etc.). Abstract syntax tree
  7. Cada nodo del árbol representa una parte del código fuente.

    Cómo AST parsea el código Lo que escribes Nodos AST Const var name ‘=‘ value ‘;’ Identifier Literal VariableDeclaration
  8. Qué pinta tiene un arbol AST Const var name ‘=‘

    value ‘;’ Identifier Literal VariableDeclaration
  9. Consideremos estos 4 ejemplos: Por qué AST y no Regex

    Todos generan el mismo árbol AST
  10. AST

  11. AST

  12. AST

  13. AST

  14. AST

  15. AST

  16. AST

  17. AST

  18. AST

  19. AST

  20. AST

  21. AST

  22. AST

  23. AST

  24. AST

  25. AST

  26. AST

  27. AST

  28. AST

  29. AST

  30. AST

  31. AST

  32. AST

  33. AST

  34. V8 usa Ignition para parsear javascript en AST y compilarlo

    en bytecode AST en JavaScript https://v8.dev/blog/background-compilation
  35. Babel parsea tu código a AST, hace transformaciones al árbol

    e imprime el código de vuelta. AST en JavaScript
  36. AST codemods Vamos a usar codemods para parsear nuestro código

    a AST, hacer transformaciones en el árbol sintáctico y volver a imprimir nuestro código al fichero original sin perder el “code style”
  37. Python: https://pybowler.io/ Java: https://www.vogella.com/tutorials/EclipseJDT/article.html#using-jdt-to-modify-existing-source-code CSS: https://postcss.org/ C++ & C#: https://www.jetbrains.com/resharper-cpp/

    SQL: https://www.red-gate.com/products/sql-development/sql-prompt/ Javascript: https://github.com/facebook/jscodeshift AST codemod libraries
  38. We have tens of thousands of JavaScript modules at Facebook.

    When an engineer makes breaking API changes we transform all of our JavaScript to new code. To deprecate and remove legacy APIs Felix Kling and I developed a tool called jscodeshift for doing AST-to-AST transforms for JavaScript. - Christoph Nakazawa jscodeshift “ “
  39. jscodeshift es un Toolbox. • Utiliza el parser de babel

    (babylon), ast-types (libreria de Ben Newman) para crear nodos y recast para el “pretty-printing”. • Es un wrapper de éstas 3 herramientas que nos prove de un API para poder hacer find, filter, map y replace de los nodos de AST. • También nos proporciona un runner/worker para poder transformer miles de ficheros en paralelo. Si no habeis trabajado nunca con AST podeis usar AST Explorer desarrollado por Felix para inspeccionar los nodos AST. jscodeshift
  40. Vocabulario: Nodes: Son la unidad minima del AST, Tambien llamados

    “AST nodes.” Son objetos simples y no nos proven de ningún método. Node-paths: Wrappers al rededor de los nodos AST que nos da la libreria “ast-types” para poder recorrer el AST. Los nodos por si solos no tienen información del parent o su scope, los node-paths nos dan esa información. Collections: Grupos de cero o más node-paths que nos devuelve el API de jscodeshift cuando hacemos queries soble el AST. Collections contienen Node-paths, Node-paths contienen Nodes, Y los Nodes son de lo que está hecho AST jscodeshift
  41. Usamos Babel y Eslint en el día a día así

    que tenia sentido elegir uno de estos para nuestros codemods. Eslint lo descartamos antes de empezar, esta pensado para otro tipo de tareas, no imprime de vuelta del AST a código. Pusimos a Babel y jscodeshift a trabajar para saber cual era mejor para lo que queríamos: • Babel transforma código que va a ser ejecutado en un navegador, le da igual el código que genera. Añadimos recast para parsear el código y mantener el “code style”. • Las colecciones de jscodeshift nos permitían recorrer el árbol con más facilidad y con menos código. • Los codemods con Babel se veían más imperativos, con jscodeshift eran más declarativos. Jscodeshift trae todo lo que necesitabamos “out of the box”, nos da herramientas que hacen que nuestros codemods sean más pequeños, más legibles, más reutilizables y eramos más rápidos desarrollandolos. Porqué elegimos jscodeshift sobre Babel o Eslint
  42. js-codemod/template-literals: Casos de uso simples El repo de js-codemod contiene

    una colección de scripts que podemos utilizar. js-codemod script
  43. js-codemod/object-shorthand : Casos de uso simples El repo de js-codemod

    contiene una colección de scripts que podemos utilizar. js-codemod script
  44. En ING tenemos proyecto con lit-element. Tenemos un catalogo de

    componentes compartido llamado ing-web Hace unos meses, ing-icon introdujo un breaking change para evitar posibles ataques xss: Enfrentandose a breaking changes
  45. Imaginemos que tenemos un proyecto con multiples usos de ing-icon.

    Quieres actualizar la versión de ing-web, pero para eso hay que actualizar todos los atributos .svg antes. Enfrentandose a breaking changes
  46. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes
  47. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Executamos jscodeshift sobre el código fuente y nos devuelve una colección de nodos Importamos el fichero de código y el api de jscodeshift
  48. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Devuelve una colección con todos los tag templates cuyo tag es html y tiene un template literal como argumento
  49. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Buscamos los literals
  50. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Filtramos la colección y nos quedamos solo con los que sean tags <svg>
  51. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Con esto hemos identificado todos los nodos que queremos reemplazar
  52. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Creamos un template literal con el contenido del string con <svg> original
  53. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Creamos un tag template con el tag ‘tag’ y le pasamos el template literal como argumento
  54. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes Creamos un arrow function con el parámetro ‘tag’ y el tag template recién creado como body de la función
  55. Hemos escrito este codemod para que haga todo el trabajo

    por nosotros Enfrentandose a breaking changes 65 Ejecutamos replaceWith sobre todos los nodos que encontramos pasándole el arrow function recién creado
  56. Enfrentandose a breaking changes Por útimo convertimos AST en código

    de nuevo Hemos escrito este codemod para que haga todo el trabajo por nosotros
  57. Enfrentandose a breaking changes Y eso es todo, hemos adaptado

    todos nuestros ficheros a un breaking change. Todo lo que hay que hacer es escribir un pequeño script!!
  58. Y eso es todo, hemos adaptado todos nuestros ficheros a

    un breaking change. Todo lo que hay que hacer es escribir un pequeño script!! Enfrentandose a breaking changes
  59. Manteniendo código legacy 2.048 Paquetes Frontend { } 1.947.006 Líneas

    de código {*.js} 1.436.705 Líneas de javascript Estado actual de las aplicaciones frontend en ING España *node_modules excluido.
  60. Manteniendo código legacy 2.048 Paquetes Frontend { } 1.947.006 Líneas

    de código {*.js} 1.436.705 Líneas de javascript 100 Paquetes Libraries Estado actual de las aplicaciones frontend en ING España { } 199.964 Líneas de código {*.js} 197.146 Líneas de javascript *node_modules excluido.
  61. Manteniendo código legacy 2.048 Paquetes Frontend { } 1.947.006 Líneas

    de código {*.js} 1.436.705 Líneas de javascript 100 Paquetes Libraries Estado actual de las aplicaciones frontend en ING España Node y Build tasks 91 Paquetes { } 199.964 Líneas de código { } 340.982 Líneas de código {*.js} 197.146 Líneas de javascript {*.js} 126.923 Líneas de javascript *node_modules excluido.
  62. Manteniendo código legacy Estado actual de las aplicaciones frontend en

    ING España Core V1 V1 V1 V1 App dependencies V1
  63. Manteniendo código legacy Estado actual de las aplicaciones frontend en

    ING España Core V2 V1 V2 V1 V2 V1 V1 V1 V1 Legacy App dependencies V1 V2
  64. Manteniendo código legacy Estado actual de las aplicaciones frontend en

    ING España Core App dependencies V3 V2 V1 V3 V2 V1 V2 V1 V1 V1 V1 Legacy V1 V2 V3 V2 V1 V2 V1 V2 Legacy V3 V3
  65. Manteniendo código legacy Estado actual de las aplicaciones frontend en

    ING España Core V1 V1 V1 V1 App dependencies V1 V2 V3 V4 V2 V1 V2 V1 V2 Legacy V3 V2 V1 V3 V2 V1 V2 Legacy V3 V3
  66. Manteniendo código legacy Estado actual de las aplicaciones frontend en

    ING España Core V1 V1 V1 V1 codemod codemod codemod App dependencies V1 V2 V3 V4 V2 V1 V2 V1 V2 Legacy V3 V2 V1 V3 V2 V1 V2 Legacy V3 V3
  67. Manteniendo código legacy V1 Estado actual de las aplicaciones frontend

    en ING España V2 V3 V4 V4 V4 V4 V4 Core V4 V4 V4 V4 V4 V4 V1 V1 V1 V1 codemod codemod codemod No more legacy App dependencies V2 V1 V2 V1 V2 Legacy V3 V2 V1 V3 V2 V1 V2 Legacy V3 V3
  68. Links útiles Articles • https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb • https://nec.is/writing/transform-your-codebase-using-codemods/ • https://www.toptal.com/javascript/write-code-to-rewrite-your-code/ •

    https://itnext.io/ast-for-javascript-developers-3e79aeb08343/ Tools • https://astexplorer.net/ • https://resources.jointjs.com/demos/rappid/apps/Ast/index.html