
Cuando mi amigo y yo fuimos a la escuela y solo soñábamos con convertirnos en desarrolladores, pensamos en cómo hacer algo juntos: un juego o un programa súper útil.
Empecé a aprender los pros y C #, es JavaScript. Nos graduamos de la escuela secundaria, estudiamos en la universidad, servimos en el ejército, conseguimos un trabajo. Estábamos plagados de desarrollo industrial aquí y allá, y cuando ambos nos cansamos, recordamos dónde comenzamos.
Habiendo reunido desarrolladores ya experimentados, finalmente decidimos hacer nuestro propio proyecto: un videojuego bidimensional. Como el amigo era un frente limpio, y yo era una pila completa, el navegador se convirtió en la plataforma obvia para nosotros. Solía desarrollar el frente solo en TypeScript, y pensamos que no había problema, TS es solo un superconjunto de JavaScript. Tómelo y todo saldrá bien. No importa como. Cuando comenzamos a hablar sobre el trabajo, nos enfrentamos a un increíble abismo de malentendidos.
Entonces vi la tarea de hacer un juego. Soy así, sí, tenemos un tipo de "juego", un tipo de "inventario", un tipo de "cosa", un tipo de "mapa", un tipo de "ubicación". Puedo imaginarme cómo trabajan juntos, describirlos, armar un proyecto y todo funciona. El compilador me revisó, hice todo bien. Luego, comienzo a escribir código que usa estos tipos. Debido al hecho de que lo son, es mucho más fácil para mí. El IDE me dice y comprueba si hay errores. Si el proyecto va a funcionar, lo más probable es que esté funcionando. Pasé mucho tiempo en descripciones de tipos, y fue bueno. Aquí está mi enfoque.
Mi amigo quería hacer lo contrario: escribir código inmediatamente y no describir ningún tipo. No estaba listo para definir el problema como una familia tipográfica. No quería desarrollarlo, no veía la tarea como un conjunto de clases, tipos, registros o algo así. Me pareció simplemente impensable. Ambos teníamos razón en muchos aspectos, solo la corrección de cada uno de nosotros excluía al otro.
En serio, hablamos durante horas, pero cada uno habló por su cuenta, como en diferentes idiomas. Y no puedes escribir que nuestros cerebros no son flexibles. Hace apenas un año, me mudé sin problemas al mundo funcional desde la orientación a objetos, y viceversa. Además, pasé mucho tiempo aprendiendo JS, y él estaba aprendiendo varios idiomas mecanografiados estáticamente.
Pero la tecnología, que se convirtió en la primera tecnología de "combate" para los desarrolladores, los define con tanta fuerza que dos personas adultas con experiencia simplemente no están listas para escucharse entre sí. A lo largo de los años de estudio del desarrollo, nuestra visión ha evolucionado de manera muy diferente y los enfoques para resolver problemas no funcionaron en absoluto.
Como resultado, abandonamos la idea de trabajar juntos. La idea inmediatamente me viene a la mente de que el problema está solo en nosotros dos. Tal vez, pero he visto esto con otras personas en la industria.
La escritura estática y dinámica tiene una diferencia fundamental irreconciliable
Mi código responde a la pregunta "Cómo trabajar con esto", y como un código para desarrolladores que están acostumbrados a la escritura dinámica: "Cómo funciona". Ambos enfoques tienen derecho a la vida, y hay herramientas para ambos, pero solo uno puede estar a la vanguardia.
Estático es bueno para grandes proyectos que han realizado cientos de años de desarrollo, y dinámico para pequeños equipos, para tareas donde a menudo se necesita código de solo escritura. Con Dynamic, ahorras tiempo y esfuerzo al comienzo del desarrollo, y con static al final.
La idea de poner los tipos a la vanguardia influyó seriamente en mi pensamiento del desarrollador.
Al elegir C # al comienzo del viaje, clavé la tipificación estática en mi visión del mundo, que ahora estoy sufriendo. Habiendo visto algún problema, trato de presentar su solución como un conjunto de tipos y principios de su interacción. Cuando desarrollo un módulo, primero determino en qué tipos funciona y qué interactúa con su entorno. Ni siquiera recuerdo cómo abordaba la resolución de problemas antes.
Toda la capacitación en programación Java es capacitación en el diseño y uso de tipos. .NET CLR - C # runtime - construido en tipos y para tipos. La escritura estática está en el centro del diseño de la programación orientada a objetos (hola, clases de JS, decidí que no eran necesarias). Las implementaciones canónicas de la mayoría de los patrones de OOP están repletas de interfaz, que no tiene ningún significado en un lenguaje de tipo dinámico.
Los patrones en sí mismos son un lenguaje cruzado, pero ¿alguien puede decirme por qué se necesita el patrón de "estado" en un lenguaje de tipo dinámico? ¿Qué pasa con el constructor? Estos patrones no son sobre desarrollo, son sobre tipos. Los tipos y POO están inextricablemente vinculados.
No puede construir su lógica de negocios basada en tipos, pero no sabe nada sobre ellos en el proceso de desarrollo. Es por eso que hay proveedores de front-end que cubren su código con un número inimaginable de pruebas unitarias, que solo comprueban la base del código por la ausencia de errores de tipo.
Todos sabemos muy bien que la seguridad a través de la cobertura es una ilusión. Las pruebas se escriben a mano; son, por definición, menos confiables que el sistema de verificación de tipos integrado en el lenguaje.
Esto no significa que no se necesiten lenguajes escritos dinámicamente (de hecho, realmente creo que no son necesarios). Esto significa que al usarlos, debe abandonar la POO como paradigma dominante. Toda esta unidad de datos y operaciones en ellos es para chicos que tienen una verificación estática.
Los desarrolladores con los que traté no creen que la presencia de tipeo estático cambie el enfoque del desarrollo, y escriben el mismo código que en lenguajes dinámicos, agregando verificación de tipos. Creo que esto es fundamentalmente incorrecto. Y esto es más notable precisamente en el caso de un front-end moderno.
Sé que criticar frentes es un tema tabú. Un día, mi amigo y yo comenzamos una IA, que controla a todos en Twitter, y Brendan Ike lo criticó. En serio, el creador del javascript luchó con nuestra red neuronal en los comentarios.
Por alguna razón desconocida, estos tipos simplemente no están listos para vivir en un mundo donde su visión contiene brechas serias. Por lo tanto, critico solo a aquellos de ellos que se apresuran a mi proyecto definitivamente escrito, y ponen sus propias órdenes allí.
Habríamos vivido en nuestros pequeños mundos, pero TypeScript nos empujó
Entonces estoy escribiendo un código que debido a los tipos no se puede usar incorrectamente. En el proyecto, espero que otros también usen tipos. Entonces mi código funcionará como pretendía. Y no cubro a sabiendas todos los casos de mal uso de este código (porque escribir excluye esto). Pero un apodo JS entra en el proyecto, toma este tipo de mina, la envuelve y comienza a usarla incorrectamente, lo que conduce a errores sutiles.
Los desarrolladores de JavaScript están convencidos de que Typecript sigue siendo el mismo JS, pero con la capacidad de agregar a veces la comprobación de tipo estático si lo necesitan. Esto no es asi. El script es cien veces más poderoso, y solo están interesados en el tres por ciento de sus capacidades.
El argumento más perjudicial es que TypeScript es solo un superconjunto de JS. Pero en la práctica, no puedes evitar considerar el mecanografiado como un idioma independiente, incluso si eres el maldito rey de los front-renders. Porque aquí necesitamos un enfoque diferente: estático, no dinámico.
La principal ventaja del tipeo estático es la garantía. Si lo usa en un módulo, pero no en otro, solo dedicó tiempo y esfuerzo a la descripción y desarrollo de tipos, pero no recibió ninguna garantía.
A muchos les parece que TypeScript es un compromiso entre los sistemas de tipos entre JS y Java. No es un compromiso, su sistema de tipos es simplemente especial.
Todo se complica por el hecho de que hoy cada segundo trabajo en el frente requiere conocimiento de TS. Esto lleva al hecho de que los desarrolladores de JS estudian superficialmente las capacidades de Typecript y comienzan a escribir código en él, creando una gran cantidad de prácticas dañinas. Surge una situación en la que realmente no necesitan una comprobación de escritura estática, pero se la impusieron y la arruinaron. Finalmente debe reconocerse que los enfoques de desarrollo con tipeo dinámico y estático se contradicen entre sí, estas no son cosas que se puedan mezclar.
JavaScript, como lo veo, es una muy buena herramienta para escribir código que resuelve el problema sin resaltar abstracciones innecesarias. El caso más atroz es el patrón de la fábrica de hielo. Puede alimentar esta instancia con sus instancias, y las cubre con inmunidad de tiempo de ejecución. Si proceso mi objeto con esta fábrica, me dará lo mismo, pero cuando trato de cambiar el valor de una de las propiedades, obtendré una excepción. ¿Solo WAT?
El patrón surgió porque los frentes leían en alguna parte sobre la inmutabilidad genial, y decidieron arrastrarlo a su propio idioma, que de ninguna manera estaba destinado a la inmunidad. En Typecript, puedo hacer la misma fábrica, pero con una prohibición de mutaciones en el tiempo de compilación, y sin ninguna excepción.
Por otro lado, esto no es necesario, porque existe una programación funcional pura. Tome F #, Haskell, OCaml, lo pondré, ReasonML: hay mutaciones prohibidas de fábrica. Pero me temo que si le das el front-end a un lenguaje funcional, inmediatamente comenzará a modernizarse y hará que el comportamiento se parezca a JS.
Porque la elección de escribir es un camino sin retorno. Todas las soluciones de compromiso solo dan la ilusión de compromiso. Pones los tipos a la vanguardia o no. No sé cómo resultaría todo, comience a aprender C # y JavaScript simultáneamente y paralelos entre sí. Pero ahora estoy tan clavado en mi pensamiento que no veo y no quiero ver las ventajas del tipeo dinámico. Lo son, pero están fuera de mi vista, y todo lo que me queda es hacer la vista gorda ante ellos, ante cualquier manifestación del mundo ajeno a mí con el que tenga que vivir. Entiendo que estoy equivocado, pero necesito trabajar aquí y ahora, y no hay presupuesto corriendo entre los polos.
Por lo tanto, no quiero buscar compromisos, pero hablo directamente. Si recién está comenzando a aprender el desarrollo, comience con la escritura estática.