{"id":36721,"date":"2019-10-31T22:13:20","date_gmt":"2019-10-31T19:13:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-dark-razvertyvaet-kod-za-50-ms\/"},"modified":"2019-10-31T22:13:20","modified_gmt":"2019-10-31T19:13:20","slug":"kak-dark-razvertyvaet-kod-za-50-ms","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","title":{"rendered":"C\u00f3mo Dark despliega c\u00f3digo en 50 ms","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"C\u00f3mo Dark despliega c\u00f3digo en 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/c159a36eb52bf488f3a70ea511690366.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cuanto m\u00e1s r\u00e1pido es el proceso de desarrollo, m\u00e1s r\u00e1pido se desarrolla la empresa tecnol\u00f3gica.<\/p>\n<p><\/p>\n<p>Desafortunadamente, las aplicaciones modernas trabajan en nuestra contra: nuestros sistemas deben actualizarse en tiempo real sin interrumpir a nadie ni provocar tiempos de inactividad. Implementar en estos sistemas se convierte en una tarea complicada y requiere pipelines de entrega continua incluso en equipos peque\u00f1os.<\/p>\n<p><\/p>\n<p>Estos pipelines suelen tener un uso limitado, funcionan lentamente y no son fiables. Los desarrolladores deben crearlos manualmente primero y luego gestionarlos, y las empresas a menudo contratan equipos enteros de DevOps para esto.<\/p>\n<p><\/p>\n<p>La velocidad de estos pipelines afecta la velocidad de desarrollo. En los mejores equipos, la implementaci\u00f3n toma de 5 a 10 minutos, pero normalmente todo tarda mucho m\u00e1s, y una sola implementaci\u00f3n puede requerir varias horas.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>En Dark, esto toma 50 ms. <em>Cincuenta. Milisegundos.<\/em>. Dark \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">es una soluci\u00f3n integral con un lenguaje de programaci\u00f3n, editor e infraestructura<\/a><\/noindex>, creado espec\u00edficamente para entrega continua, y todos los aspectos de Dark, incluido el propio lenguaje, est\u00e1n dise\u00f1ados para un despliegue instant\u00e1neo y seguro.<\/p>\n<p><\/p>\n<h3 id=\"pochemu-konveyery-nepreryvnoy-postavki-takie-medlennye\">\u00bfPor qu\u00e9 los pipelines de entrega continua son tan lentos?<\/h3>\n<p><\/p>\n<p>Supongamos que tenemos una aplicaci\u00f3n web en Python y ya hemos creado un grandioso y moderno pipeline de entrega continua. Para un desarrollador que trabaja en este proyecto todos los d\u00edas, implementar un peque\u00f1o cambio se ver\u00e1 aproximadamente as\u00ed:<\/p>\n<p><\/p>\n<h3 id=\"vnesenie-izmeneniy\">Realizando cambios.<\/h3>\n<p><\/p>\n<ul>\n<li>Creando una nueva rama en git.<\/li>\n<li>Realizando cambios tras el interruptor de funciones.<\/li>\n<li>Pruebas unitarias para verificar los cambios con y sin el interruptor de funciones.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pul-rekvest\">Pull request.<\/h3>\n<p><\/p>\n<ul>\n<li>Confirmar cambios.<\/li>\n<li>Enviar cambios al repositorio remoto en GitHub.<\/li>\n<li>Pull request.<\/li>\n<li>La construcci\u00f3n de CI se ejecuta autom\u00e1ticamente en segundo plano.<\/li>\n<li>Revisi\u00f3n del c\u00f3digo.<\/li>\n<li>Algunas revisiones m\u00e1s, si es necesario.<\/li>\n<li>Fusionando cambios con el maestro de git.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"ci-vypolnyaetsya-na-mastere\">CI se ejecuta en el maestro.<\/h3>\n<p><\/p>\n<ul>\n<li>Instalando dependencias del frontend a trav\u00e9s de npm.<\/li>\n<li>Construyendo y optimizando recursos HTML+CSS+JS.<\/li>\n<li>Ejecutando pruebas unitarias y funcionales en el frontend.<\/li>\n<li>Instalando dependencias de Python desde PyPI.<\/li>\n<li>Ejecutando pruebas unitarias y funcionales en el backend.<\/li>\n<li>Pruebas de integraci\u00f3n en ambos extremos.<\/li>\n<li>Enviando recursos del frontend al CDN.<\/li>\n<li>Construyendo el contenedor para la aplicaci\u00f3n Python.<\/li>\n<li>Env\u00edo del contenedor al registro<\/li>\n<li>Actualizaci\u00f3n del manifiesto de Kubernetes<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zamena-starogo-koda-novym\">Reemplazo del c\u00f3digo antiguo por el nuevo<\/h3>\n<p><\/p>\n<ul>\n<li>Kubernetes inicia varias instancias del nuevo contenedor<\/li>\n<li>Kubernetes espera a que las instancias est\u00e9n operativas<\/li>\n<li>Kubernetes a\u00f1ade instancias al equilibrador de carga HTTP<\/li>\n<li>Kubernetes espera a que las antiguas instancias dejen de ser utilizadas<\/li>\n<li>Kubernetes detiene las antiguas instancias<\/li>\n<li>Kubernetes repite estas operaciones hasta que todas las nuevas instancias reemplacen a las antiguas<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"vklyuchenie-novogo-pereklyuchatelya-funkcii\">Activaci\u00f3n de un nuevo interruptor de funciones<\/h3>\n<p><\/p>\n<ul>\n<li>El nuevo c\u00f3digo se activa solo para s\u00ed mismo, asegur\u00e1ndose de que todo est\u00e9 correcto<\/li>\n<li>El nuevo c\u00f3digo se activa para el 10% de los usuarios, se supervisan m\u00e9tricas operativas y comerciales<\/li>\n<li>El nuevo c\u00f3digo se activa para el 50% de los usuarios, se supervisan m\u00e9tricas operativas y comerciales<\/li>\n<li>El nuevo c\u00f3digo se activa para el 100% de los usuarios, se supervisan m\u00e9tricas operativas y comerciales<\/li>\n<li>Finalmente, repites todo el proceso para eliminar el c\u00f3digo antiguo y el interruptor<\/li>\n<\/ul>\n<p><\/p>\n<p>El proceso depende de las herramientas, el lenguaje y el uso de arquitecturas orientadas a servicios, pero en general se ve as\u00ed. No mencion\u00e9 los despliegues con migraci\u00f3n de bases de datos, porque eso requiere una planificaci\u00f3n cuidadosa, pero a continuaci\u00f3n, explicar\u00e9 c\u00f3mo lo maneja Dark.<\/p>\n<p><\/p>\n<p>Aqu\u00ed hay muchos componentes y muchos de ellos pueden f\u00e1cilmente causar retrasos, fallos, competencia temporal o colapsar el sistema en funcionamiento.<\/p>\n<p><\/p>\n<p>Y dado que estos pipelines casi siempre est\u00e1n dise\u00f1ados para un caso particular, es dif\u00edcil confiar en ellos. Muchos tienen d\u00edas en los que no se puede desplegar el c\u00f3digo porque hay problemas en el Dockerfile, uno de los decenas de servicios ha fallado o el especialista necesario est\u00e1 de vacaciones.<\/p>\n<p><\/p>\n<p>Peor a\u00fan, muchos de estos pasos no hacen nada \u00fatil en absoluto. Fueron necesarios en el pasado, cuando despleg\u00e1bamos c\u00f3digo directamente para los usuarios, pero ahora tenemos interruptores para el nuevo c\u00f3digo y estos procesos se han separado. Como resultado, el paso en el que se despliega el c\u00f3digo (el antiguo es reemplazado por el nuevo) se ha convertido en un riesgo innecesario.<\/p>\n<p><\/p>\n<p>Por supuesto, este es un pipeline muy bien pensado. El equipo que lo cre\u00f3 no escatim\u00f3 tiempo ni dinero en un despliegue r\u00e1pido. Por lo general, los pipelines de despliegue son mucho m\u00e1s lentos y menos fiables.<\/p>\n<p><\/p>\n<h3 id=\"realizaciya-nepreryvnoy-postavki-v-dark\">Implementaci\u00f3n de entrega continua en Dark<\/h3>\n<p><\/p>\n<p>La entrega continua es tan importante para Dark que desde el principio nos propusimos un tiempo de menos de un segundo. Revisamos todos los pasos del pipeline para eliminar lo innecesario y perfeccionamos el resto. As\u00ed es como eliminamos pasos.<\/p>\n<p><\/p>\n<blockquote><p>Jessie Frazelle (<noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex>) cre\u00f3 la nueva palabra deployless (sin despliegue) en la conferencia Future of Software Development en Reikiavik.<\/p><\/blockquote>\n<p>Decidimos de inmediato que Dark se basar\u00eda en la \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u00abdeployless\u00bb (gracias a <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex> por el neologismo). Deployless significa que cualquier c\u00f3digo se despliega instant\u00e1neamente y est\u00e1 listo para usar en producci\u00f3n. Por supuesto, no dejaremos pasar c\u00f3digo defectuoso o incompleto (los principios de seguridad los describir\u00e9 a continuaci\u00f3n).<\/p>\n<p><\/p>\n<p>Durante la demostraci\u00f3n de Dark, a menudo nos preguntaban c\u00f3mo logramos acelerar el despliegue de esa manera. Una pregunta extra\u00f1a. La gente debe pensar que hemos inventado alguna supertecnolog\u00eda que compara c\u00f3digo, lo compila, lo empaqueta en un contenedor, lanza una m\u00e1quina virtual, inicia un contenedor en fr\u00edo y todo eso, en 50 ms. Es poco probable que eso sea posible. Pero hemos creado un motor de despliegue especial que no necesita hacer todo eso.<\/p>\n<p><\/p>\n<p>Dark lanza int\u00e9rpretes en la nube. Supongamos que est\u00e1s escribiendo c\u00f3digo en una funci\u00f3n o manejador HTTP o de eventos. Enviamos un diff al \u00e1rbol de sintaxis abstracta (la implementaci\u00f3n del c\u00f3digo que utiliza internamente nuestro editor y servidores) a nuestros servidores, y luego ejecutamos ese c\u00f3digo cuando llegan las solicitudes. As\u00ed que el despliegue parece simplemente una modesta entrada en una base de datos: instant\u00e1neo y elemental. El despliegue es tan r\u00e1pido porque incluye lo m\u00ednimo.<\/p>\n<p><\/p>\n<p>En el futuro, planeamos convertir a Dark en un compilador de infraestructura que crear\u00e1 y ejecutar\u00e1 la infraestructura ideal para alto rendimiento y fiabilidad de aplicaciones. El despliegue instant\u00e1neo, por supuesto, no ir\u00e1 a ninguna parte.<\/p>\n<p><\/p>\n<h2 id=\"bezopasnoe-razvertyvanie\">Despliegue seguro<\/h2>\n<p><\/p>\n<h3 id=\"strukturirovannyy-redaktor\">Editor estructurado<\/h3>\n<p><\/p>\n<p>El c\u00f3digo en Dark se escribe en el editor de Dark. El editor estructurado no permite errores de sintaxis. De hecho, en Dark no hay ni siquiera un analizador. Mientras introduzcas texto, trabajamos directamente con el \u00e1rbol de sintaxis abstracta (AST), como <noindex><a rel=\"nofollow\" href=\"http:\/\/danmidwood.com\/content\/2014\/11\/21\/animated-paredit.html\">Paredit<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ravichugh.github.io\/sketch-n-sketch\/\">Sketch-n-Sketch<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/gregoor.github.io\/tofu\/\">Tofu<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/notes\/kent-beck\/prune-a-code-editor-that-is-not-a-text-editor\/1012061842160013\/\">Prune<\/a><\/noindex> y <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/mps\/\">MPS<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Cualquier c\u00f3digo incompleto en Dark tiene una sem\u00e1ntica de ejecuci\u00f3n v\u00e1lida, similar a <noindex><a rel=\"nofollow\" href=\"https:\/\/hazel.org\/\">typed holes en Hazel<\/a><\/noindex>. Por ejemplo, si cambias la llamada a una funci\u00f3n, guardamos la antigua hasta que la nueva sea adecuada.<\/p>\n<p><\/p>\n<p>Cada programa en Dark tiene su propio prop\u00f3sito, por lo que el c\u00f3digo incompleto no interfiere con el funcionamiento del c\u00f3digo completo.<\/p>\n<p><\/p>\n<h3 id=\"rezhimy-redaktirovaniya\">Modos de edici\u00f3n<\/h3>\n<p><\/p>\n<p>Escribes c\u00f3digo en Dark en dos situaciones. Primero: escribes nuevo c\u00f3digo y eres el \u00fanico usuario. Por ejemplo, est\u00e1 en REPL, y otros usuarios nunca tendr\u00e1n acceso a \u00e9l, o es una nueva ruta HTTP a la que no te refieres en ninguna parte. Aqu\u00ed puedes trabajar sin ninguna medida de precauci\u00f3n, y ahora est\u00e1s trabajando as\u00ed en el entorno de desarrollo.<\/p>\n<p><\/p>\n<p>La segunda situaci\u00f3n: el c\u00f3digo ya est\u00e1 en uso. Si hay tr\u00e1fico pasando a trav\u00e9s del c\u00f3digo (funciones, manejadores de eventos, bases de datos, etc.), se debe tener cuidado. Para ello, bloqueamos todo el c\u00f3digo en uso y requerimos utilizar herramientas m\u00e1s estructuradas para su edici\u00f3n. A continuaci\u00f3n hablar\u00e9 sobre las herramientas estructurales: los interruptores de funciones para manejadores HTTP y eventos, una potente plataforma de migraci\u00f3n para bases de datos y un nuevo m\u00e9todo de gesti\u00f3n de versiones para funciones y tipos.<\/p>\n<p><\/p>\n<h3 id=\"pereklyuchateli-funkciy\">Interruptores de funciones<\/h3>\n<p><\/p>\n<p>Una de las maneras <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">de eliminar la complejidad innecesaria<\/a><\/noindex> en Dark es resolver varios problemas con una soluci\u00f3n. Los interruptores de funciones realizan muchas tareas diferentes: reemplazo del entorno de desarrollo local, ramas de git, despliegue de c\u00f3digo y, por supuesto, el tradicional lanzamiento lento y controlado de nuevo c\u00f3digo.<\/p>\n<p><\/p>\n<p>La creaci\u00f3n y despliegue de un interruptor de funci\u00f3n se realiza en nuestro editor en una sola operaci\u00f3n. Crea un espacio vac\u00edo para el nuevo c\u00f3digo y proporciona controles de acceso al c\u00f3digo antiguo y nuevo, as\u00ed como botones y comandos para cambiar gradualmente al nuevo c\u00f3digo o excluirlo.<\/p>\n<p><\/p>\n<p>Los interruptores de funciones est\u00e1n integrados en el lenguaje Dark, y incluso los interruptores incompletos cumplen su funci\u00f3n: si la condici\u00f3n en el interruptor no se cumple, se ejecutar\u00e1 el antiguo c\u00f3digo bloqueado.<\/p>\n<p><\/p>\n<h3 id=\"sreda-razrabotki\">Entorno de desarrollo<\/h3>\n<p><\/p>\n<p>Los interruptores de funciones reemplazan el entorno de desarrollo local. Hoy en d\u00eda, es dif\u00edcil para los equipos asegurarse de que todos utilicen las mismas versiones de herramientas y bibliotecas (herramientas de formateo de c\u00f3digo, linters, gestores de paquetes, compiladores, preprocesadores, herramientas de prueba, etc.). Con Dark, no es necesario instalar dependencias localmente, gestionar una instalaci\u00f3n local de Docker o tomar otras medidas para garantizar al menos una semblanza de igualdad entre el entorno de desarrollo y la producci\u00f3n. <noindex><a rel=\"nofollow\" href=\"https:\/\/thenewstack.io\/honeycombs-charity-majors-go-ahead-test-in-production\/\">Dado que tal igualdad sigue siendo imposible<\/a><\/noindex>, ni siquiera vamos a pretender que estamos tratando de lograrla.<\/p>\n<p><\/p>\n<p>En lugar de crear un entorno local clonado, los interruptores en Dark crean una nueva caja de arena en producci\u00f3n que reemplaza el entorno de desarrollo. En el futuro, tambi\u00e9n planeamos crear una caja de arena para otras partes de la aplicaci\u00f3n (por ejemplo, clones instant\u00e1neos de bases de datos), aunque por ahora esto no parece tan importante.<\/p>\n<p><\/p>\n<h3 id=\"vetki-i-razvertyvaniya\">Ramas y despliegues<\/h3>\n<p><\/p>\n<p>Actualmente, hay varias formas de introducir nuevo c\u00f3digo en los sistemas: ramas de git, etapa de despliegue e interruptores de funciones. Resuelven un mismo problema en diferentes partes del flujo de trabajo: git \u2014 en las etapas previas al despliegue, el despliegue \u2014 en el momento de la transici\u00f3n del c\u00f3digo viejo al nuevo, y los interruptores de funciones \u2014 para un lanzamiento controlado del nuevo c\u00f3digo.<\/p>\n<p><\/p>\n<p>La forma m\u00e1s efectiva son los interruptores de funciones (adem\u00e1s de ser la m\u00e1s f\u00e1cil de entender y usar). Con ellos se puede prescindir por completo de los otros dos m\u00e9todos. Es especialmente \u00fatil eliminar el despliegue \u2014 si ya estamos usando interruptores de funciones para activar el c\u00f3digo, el paso de trasladar servidores al nuevo c\u00f3digo solo crea riesgos innecesarios.<\/p>\n<p><\/p>\n<p>Git es dif\u00edcil de usar, especialmente para los principiantes, y eso lo limita enormemente, pero por otro lado tiene ramas convenientes. Hemos suavizado muchas de las desventajas de git. Dark se edita en tiempo real y proporciona la posibilidad de colaboraci\u00f3n al estilo de Google Docs, de modo que no es necesario enviar c\u00f3digo y se puede realizar el rebase y la fusi\u00f3n con menos frecuencia.<\/p>\n<p><\/p>\n<p>Los interruptores de funciones son la base de un despliegue seguro. Junto con los despliegues instant\u00e1neos, permiten probar r\u00e1pidamente conceptos en peque\u00f1os fragmentos con bajo riesgo, en lugar de aplicar un gran cambio que podr\u00eda colapsar el sistema.<\/p>\n<p><\/p>\n<h3 id=\"versionirovanie\">Versionado<\/h3>\n<p><\/p>\n<p>Para cambiar funciones y tipos, usamos el versionado. Si deseas cambiar una funci\u00f3n, Dark crea una nueva versi\u00f3n de esa funci\u00f3n. Luego puedes llamar a esa versi\u00f3n con un interruptor en el manejador HTTP o de eventos. (Si es una funci\u00f3n profundamente anidada en el \u00e1rbol de llamadas, se crear\u00e1 una nueva versi\u00f3n de cada funci\u00f3n en el camino. Puede parecer excesivo, pero las funciones no interfieren entre s\u00ed si no las utilizas, as\u00ed que ni siquiera lo notar\u00e1s.)<\/p>\n<p><\/p>\n<p>Por las mismas razones, versionamos los tipos. Hablamos en detalle sobre nuestro sistema de tipos <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">en la publicaci\u00f3n anterior.<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Gracias al versionado de funciones y tipos, puedes realizar cambios en la aplicaci\u00f3n de forma gradual. Puedes verificar que cada manejador individual trabaja con la nueva versi\u00f3n, sin la necesidad de implementar todos los cambios en la aplicaci\u00f3n de inmediato (aunque tenemos herramientas para hacerlo r\u00e1pidamente si lo deseas).<\/p>\n<p><\/p>\n<p>Esto es mucho m\u00e1s seguro que el despliegue completo de todo a la vez, como se hace actualmente.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-paketov-i-standartnaya-biblioteka\">Nuevas versiones de paquetes y la biblioteca est\u00e1ndar<\/h3>\n<p><\/p>\n<p>Cuando actualizas un paquete en Dark, no reemplazamos inmediatamente el uso de cada funci\u00f3n o tipo en toda la base de c\u00f3digo. Eso no es seguro. El c\u00f3digo sigue utilizando la misma versi\u00f3n que estaba usando, mientras que actualizas el uso de funciones y tipos a la nueva versi\u00f3n para cada caso individual mediante interruptores.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/rh\/t3\/4w\/rht34wyibolrgracbz88tnqqhg0.png\"><img decoding=\"async\" alt=\"C\u00f3mo Dark despliega c\u00f3digo en 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/54fdb566b4bcbc10e06e51c47a3820f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Captura de pantalla de parte del proceso autom\u00e1tico en Dark, mostrando dos versiones de la funci\u00f3n Dict::get. Dict::get_v0 devolv\u00eda el tipo Any (del que estamos renunciando), mientras que Dict::get_v1 devuelve el tipo Option.<\/em><\/p>\n<p><\/p>\n<p>A menudo proporcionamos una nueva funci\u00f3n en la biblioteca est\u00e1ndar y eliminamos las versiones antiguas. Los usuarios con versiones antiguas en su c\u00f3digo mantendr\u00e1n acceso a ellas, pero los nuevos usuarios no podr\u00e1n obtenerlas. Planeamos proporcionar herramientas para migrar a los usuarios de versiones antiguas a nuevas en un solo paso, nuevamente utilizando interruptores de funciones.<\/p>\n<p><\/p>\n<p>Dark tambi\u00e9n ofrece una oportunidad \u00fanica: dado que ejecutamos tu c\u00f3digo de trabajo, podemos probar nuevas versiones comparando la salida de las nuevas y viejas solicitudes para informarte sobre los cambios. Como resultado, la actualizaci\u00f3n de paquetes, que a menudo se realiza a ciegas (o requiere pruebas exhaustivas por motivos de seguridad), representa mucho menos riesgo y puede ocurrir autom\u00e1ticamente.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-dark\">Nuevas versiones de Dark<\/h3>\n<p><\/p>\n<p>La transici\u00f3n de Python 2 a Python 3 se extendi\u00f3 por una d\u00e9cada y sigue siendo un problema. Dado que estamos creando Dark para la entrega continua, debemos tener en cuenta estos cambios en el lenguaje.<\/p>\n<p><\/p>\n<p>Cuando hacemos peque\u00f1os cambios en el lenguaje, creamos una nueva versi\u00f3n de Dark. El c\u00f3digo antiguo permanece en la versi\u00f3n anterior de Dark, y el c\u00f3digo nuevo se utiliza en la nueva versi\u00f3n. Se pueden utilizar interruptores o versiones de funciones para actualizar a la nueva versi\u00f3n de Dark.<\/p>\n<p><\/p>\n<p>Esto es especialmente \u00fatil, considerando que Dark ha surgido recientemente. Muchos cambios en el lenguaje o en la biblioteca pueden resultar desafortunados. La versionado gradual del lenguaje nos permite realizar actualizaciones menores, lo que significa que podemos tomarnos nuestro tiempo y posponer muchas decisiones sobre el lenguaje hasta que tengamos m\u00e1s usuarios, lo que significa m\u00e1s informaci\u00f3n.<\/p>\n<p><\/p>\n<h3 id=\"migracii-baz-dannyh\">Migraciones de bases de datos<\/h3>\n<p><\/p>\n<p>Para migrar bases de datos de manera segura, existe una <noindex><a rel=\"nofollow\" href=\"http:\/\/www.brunton-spall.co.uk\/post\/2014\/05\/06\/database-migrations-done-right\/\">f\u00f3rmula est\u00e1ndar<\/a><\/noindex>:<\/p>\n<p><\/p>\n<ul>\n<li>Reescribir el c\u00f3digo para soportar los nuevos y antiguos formatos<\/li>\n<li>Transformar todos los datos al nuevo formato<\/li>\n<li>Eliminar el acceso antiguo a los datos<\/li>\n<\/ul>\n<p><\/p>\n<p>Como resultado, la migraci\u00f3n de bases de datos se alarga y requiere muchos recursos. Y acumulamos esquemas obsoletos, ya que incluso tareas simples, como corregir el nombre de una tabla o columna, no justifican el esfuerzo.<\/p>\n<p><\/p>\n<p>Dark tiene una plataforma de migraci\u00f3n de bases de datos eficaz que (esperamos) simplificar\u00e1 el proceso tanto que dejar\u00e1s de tenerle miedo. Todos los almacenes de datos en Dark (almacenes de pares de \"clave-valor\" o tablas hash persistentes) tienen un tipo. Para transferir un almac\u00e9n de datos, simplemente le asignas un nuevo tipo y una funci\u00f3n de reversi\u00f3n y avance para transformar los valores entre los dos tipos.<\/p>\n<p><\/p>\n<p>El acceso a los almacenes de datos en Dark se realiza a trav\u00e9s de nombres de variables versionados. Por ejemplo, el almac\u00e9n de datos Users inicialmente se llamar\u00e1 Users-v0. Cuando se crea una nueva versi\u00f3n con un tipo diferente, el nombre cambia a Users-v1. Si los datos se guardan a trav\u00e9s de Users-v0 y se accede a ellos mediante Users-v1, se aplica la funci\u00f3n de retroceso. Si los datos se guardan a trav\u00e9s de Users-v1 y se accede a ellos mediante Users-v0, se aplica la funci\u00f3n de restauraci\u00f3n.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/ui\/sl\/wd\/uislwdrfrvact0d1ts5icnk-4ka.png\"><img decoding=\"async\" alt=\"C\u00f3mo Dark despliega c\u00f3digo en 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/35743ba246f327ca9e8b71f0069a3800.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Pantalla de migraci\u00f3n de base de datos con los nombres de los campos de la antigua base de datos, expresiones de retroceso y restauraci\u00f3n e instrucciones para habilitar la migraci\u00f3n.<\/em><\/p>\n<p><\/p>\n<p>Utilice los interruptores de funciones para dirigir las llamadas a Users-v0 en la versi\u00f3n Users-v1. Esto se puede hacer un controlador HTTP a la vez, para reducir los riesgos, y los interruptores tambi\u00e9n funcionan para usuarios individuales, para que pueda verificar que todo est\u00e9 funcionando como se esperaba. Cuando no queden usuarios en Users-v0, Dark convertir\u00e1 todos los datos restantes en segundo plano del antiguo formato al nuevo. No se dar\u00e1 cuenta de esto.<\/p>\n<p><\/p>\n<h3 id=\"testirovanie\">Pruebas<\/h3>\n<p><\/p>\n<p>Dark es un <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">lenguaje de programaci\u00f3n funcional con tipado est\u00e1tico<\/a><\/noindex> y valores inmutables, por lo que su superficie de prueba es significativamente menor en comparaci\u00f3n con lenguajes orientados a objetos con tipado din\u00e1mico. Pero a\u00fan as\u00ed, es necesario hacer pruebas.<br \/>\nEn Dark, el editor ejecuta autom\u00e1ticamente pruebas modulares en segundo plano para el c\u00f3digo editado y, por defecto, ejecuta estas pruebas para todos los interruptores de funciones. En el futuro, queremos usar tipos est\u00e1ticos para ejecutar autom\u00e1ticamente fuzzing del c\u00f3digo, para encontrar errores.<\/p>\n<p><\/p>\n<p>Adem\u00e1s, Dark ejecuta su infraestructura en producci\u00f3n, lo que abre nuevas posibilidades. Guardamos autom\u00e1ticamente las solicitudes HTTP en la infraestructura de Dark (por ahora, guardamos todas las solicitudes, pero luego queremos pasar a la selecci\u00f3n). Probamos nuevo c\u00f3digo contra ellas y realizamos pruebas modulares, y si lo desea, puede convertir f\u00e1cilmente solicitudes interesantes en pruebas modulares.<\/p>\n<p><\/p>\n<h3 id=\"ot-chego-my-izbavilis\">De lo que nos deshicimos<\/h3>\n<p><\/p>\n<p>Como no tenemos despliegue, pero s\u00ed interruptores de funciones, alrededor del 60% del pipeline de despliegue queda fuera. No necesitamos ramas de git o pull requests, construcci\u00f3n de recursos backend y contenedores, env\u00edo de recursos y contenedores a registros o pasos de despliegue en Kubernetes.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/gc\/9e\/g-\/gc9eg-szouq0dtrxxr8jd6c6dyo.jpeg\"><img decoding=\"async\" alt=\"C\u00f3mo Dark despliega c\u00f3digo en 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/d584b13a1f91e9eef1e2e40c25e90052.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Comparaci\u00f3n del pipeline est\u00e1ndar de entrega continua (izquierda) y la entrega continua de Dark (derecha). En Dark, la entrega consta de 6 pasos y un ciclo, mientras que la versi\u00f3n tradicional incluye 35 pasos y 3 ciclos.<\/em><\/p>\n<p><\/p>\n<p>En Dark, hay solo 6 pasos y 1 ciclo en el despliegue (pasos que se repiten varias veces), mientras que el pipeline moderno de entrega continua consta de 35 pasos y 3 ciclos. En Dark, las pruebas se ejecutan autom\u00e1ticamente, y ni siquiera lo ves; las dependencias se instalan autom\u00e1ticamente; ya no es necesario trabajar con git o Github; no es necesario compilar, probar y enviar contenedores Docker; el despliegue en Kubernetes ya no es necesario.<\/p>\n<p><\/p>\n<p>Incluso los pasos restantes en Dark se han simplificado. Dado que los interruptores de funciones se pueden controlar con una sola acci\u00f3n, no es necesario recorrer todo el pipeline de despliegue nuevamente para eliminar el c\u00f3digo antiguo.<\/p>\n<p><\/p>\n<p>Hemos simplificado la entrega de c\u00f3digo tanto como hemos podido, reduciendo el tiempo y los riesgos de la entrega continua. Adem\u00e1s, hemos simplificado enormemente la actualizaci\u00f3n de paquetes, las migraciones de bases de datos, las pruebas, la gesti\u00f3n de versiones, la instalaci\u00f3n de dependencias, la paridad entre el entorno de desarrollo y producci\u00f3n, y las actualizaciones r\u00e1pidas y seguras de versiones de lenguajes.<\/p>\n<p><\/p>\n<p>Estoy respondiendo preguntas sobre esto en <noindex><a rel=\"nofollow\" href=\"https:\/\/news.ycombinator.com\/item?id=20394166\">HackerNews<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Para saber m\u00e1s sobre el dispositivo Dark, lee <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">el art\u00edculo sobre Dark<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/darklang?source=post_page---------------------------\">s\u00edguenos en Twitter<\/a><\/noindex> (o en <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/paulbiggar?source=post_page---------------------------\">m\u00ed<\/a><\/noindex>) o <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/subscribe?source=post_page---------------------------\">reg\u00edstrate para la versi\u00f3n beta y recibe notificaciones sobre las pr\u00f3ximas publicaciones<\/a><\/noindex>. Si vas a StrangeLoop en septiembre, <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/launch\">ven a nuestro lanzamiento<\/a><\/noindex>.<\/p>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/462027\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u0441 \u2014 \u043d\u0430\u0448\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0442\u044c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u0440\u043e\u0441\u0442\u043e\u044f\u043c \u0438 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430\u043c. \u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430\u0436\u0435 \u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27506,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47C\u00f3mo Dark despliega c\u00f3digo en 50 ms | ProHoster","description":"Cuanto m\u00e1s r\u00e1pido es el proceso de desarrollo, m\u00e1s r\u00e1pido es.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster","og:description":"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:20+00:00","article:modified_time":"2019-10-31T19:13:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36721","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:34:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:40:22","updated":"2026-01-22 04:34:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/36721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=36721"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/36721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/27506"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=36721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=36721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=36721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}