El curso "Lenguajes de programación web" (basado en Ruby) de MSTU. N.E. Bauman en el canal Technostream



En este artículo hablaremos sobre el curso "Lenguajes de programación web" , que se imparte en el Departamento de "Sistemas informáticos y redes" (IU-6) MSTU. N.E. Bauman Se dan ejemplos en Ruby, y el curso en sí es de 16 video conferencias disponibles de forma gratuita en el canal Technostream . En Baumanka, el curso se imparte a estudiantes de segundo año que ya están familiarizados con lenguajes de programación de alto nivel como Pascal, C ++ o Java. El énfasis principal está en una comprensión sistemática de las tecnologías utilizadas en la programación web, y no en la profundidad del desarrollo de las tecnologías Ruby. Por lo tanto, el curso también será útil para los estudiantes que tienen un conocimiento incompleto de las tecnologías web en cualquier idioma.

Contenido


  1. Sobre el curso "Lenguajes de programación web"

  2. Contenido de la conferencia

  3. Cómo crear un curso para una universidad
  4. ¿Por qué rubí?
  5. ¿Por qué Ruby no es popular?
  6. Resumen

Lenguajes de programación web


¿Por qué el curso se llama Lenguajes de programación web? La respuesta es muy simple. Como hace 30 años, cuando Internet estaba emergiendo, ahora no hay forma de usar un lenguaje de programación.

  • Los lenguajes de marcado son HTML y CSS.
  • Lenguajes de configuración e intercambio de datos: JSON, XML, YAML.
  • Programación del navegador - Javascript (Typecript, Coffeescript ...).
  • Programación del servidor - Ruby, PHP, Perl, Java, Javascript ...

Para comprender la programación web incluso en una cantidad mínima, necesita conocer 4-5 lenguajes de marcado y programación (aunque los límites entre ellos ahora están borrosos).

Propósito del curso


El objetivo principal del curso es comprender las tecnologías necesarias para el desarrollo web, ya que la mayoría de los proyectos modernos están relacionados de alguna manera con el desarrollo web. El curso está organizado de tal manera que los estudiantes puedan obtener de manera concisa los conceptos básicos que pueden usarse como marco para un estudio en profundidad.

Los estudiantes desarrollan habilidades específicas de forma independiente durante la capacitación, y el grado de desarrollo depende de si pretendes sumergirte en el desarrollo web en el futuro.

Autor del curso


El desarrollador principal del curso es un candidato de ciencias técnicas, profesor asociado de la cátedra "Sistemas y redes de computadoras" de MSTU que lleva el nombre N.E. Bauman Samarev Roman Stanislavovich. Un programador con más de 20 años de experiencia (C ++, C, Java, Perl, PHP, Ruby y otros para Windows, Linux, Embedded Linux, MacOS), jefe de desarrollo de software, investigador en el campo de DBMS, procesamiento de datos y big data, trabajó en Rusia, en Alemania y en los Estados Unidos.

Duración y formato


El curso completo incluye 192 horas académicas: 16 conferencias por 2 horas, 8 seminarios por 2 horas, 48 ​​horas por 12 trabajos de laboratorio. El resto del tiempo se asigna para el autoestudio. Los materiales de video incluyen solo la parte de la clase. Aquellos que deseen profundizar en el tema del curso, los materiales de trabajo de laboratorio y seminarios tendrán que aprender de forma independiente. Todas las preguntas pueden hacerse al profesor: samarev@acm.org .

Resultados


Como parte del curso de capacitación, formamos la comprensión de los estudiantes de no solo tecnologías web específicas implementadas en el lenguaje de programación Ruby, sino, más bien, una percepción holística de los problemas que surgen al crear aplicaciones web y todo lo que las acompaña, usando Ruby como una muy buena ilustración. El lenguaje Ruby en sí mismo es una adición útil para los estudiantes, que puede usarse ampliamente fuera del curso.

Contenido del curso


Conferencias 1-2. Introduccion

  • Una introducción a la programación web en términos de arquitectura básica.
  • Información mínima sobre lenguajes de marcado y hojas de estilo.
  • Introducción mínima a Javascript.



Quizás Javascript debería haber asignado mucho más tiempo, pero dado que la programación web basada en navegador no es el objetivo principal del curso, y las tecnologías de programación del lado del servidor en Javascript aún no se han establecido, el material disponible es suficiente para una comprensión inicial.

Conferencias 3-5. Rubí

Las siguientes tres conferencias están dedicadas a Ruby, ya que son las tecnologías en este lenguaje Ruby las que subyacen en el curso. Las conferencias incluyen:

  • Los fundamentos del lenguaje Ruby.
  • Información requerida sobre la estructura de tipo y el modelo de objeto.
  • Estilo funcional.




Lección 6. Principios de creación de aplicaciones web.

  • Interfaz de puerta de enlace común.


Alguien dirá que este estándar no es relevante, pero subyace a toda la programación web moderna. Por lo tanto, cualquier programador web simplemente está obligado a saber de qué se trata, y debe comprender que la aplicación web más simple es simplemente "Hola mundo".

Lección 7. Bastidor

  • Rack es una capa intermedia para la mayoría de los frameworks web de Ruby.
  • Sinatra es un marco común para crear aplicaciones simples.
  • Un ejemplo de creación de una aplicación.


Lección 8. Introducción a los rieles

  • Aspectos clave de una aplicación Rails.


Ruby on Rails es el marco que hizo famoso a Ruby y casi se convirtió en su sinónimo. Este es un ejemplo de un marco profundamente desarrollado con el concepto Modelo-Vista-Controlador, que sirvió como prototipo para la creación de muchos otros marcos web, incluidos Grails y Django. Tenga en cuenta que el concepto de Rails es generar la mayor cantidad de código posible con generadores automáticos y escribir menos a mano.

Lección 9. Interacción asincrónica

La mayoría de las aplicaciones web modernas utilizan el método asincrónico, es decir, las solicitudes del servidor desaparecen en segundo plano para el usuario. Las respuestas se resuelven en algún lugar profundo del navegador. ¿Qué necesitas saber aquí?

  • Formatos de intercambio: XML y JSON.
  • Ejecutando una solicitud asincrónica de Javascript.
  • El concepto de Javascript discreto aplicado a Rails.


Lección 10. Pruebas

Cualquier programa moderno debe estar cubierto por pruebas automáticas. Ruby implica el uso de pruebas unitarias. Y, por supuesto, Rails sugiere que cualquier acción debe ser cubierta en pruebas. La conferencia incluye los siguientes temas:

  • Probar varios aspectos de las aplicaciones web.
  • Introducción a los lenguajes de dominio (dado que RSpec y Cucumber son los mismos ejemplos de "humanidad" en las pruebas: un programa de prueba debe ser comprensible no solo para un programador que está "adaptado" para el idioma utilizado, sino también para una persona normal). Tenga en cuenta que el enfoque utilizado tanto en RSpec como en Cucumber ahora se replica ampliamente en las herramientas de prueba para muchos otros lenguajes de programación.
  • Herramientas como SikuliX y Selenium, que se pueden usar para probar programas con una interfaz gráfica y navegadores, respectivamente.


Lección 11. Tecnologías XML

  • Consultar idiomas como Xpath, Xquery.
  • XSL y XSLT.


Parece, ¿qué tiene que ver todo esto con la programación web? Pero XML es el núcleo de la tecnología web. El hecho de que no estemos utilizando XML como formato de intercambio ahora no garantiza que después de 5 años no volveremos a hacerlo. Todavía no existe un enfoque unificado para verificar los datos en formato JSON. Y en el caso de XML, el esquema de marcado lo establece el lenguaje mismo.

El lenguaje de consulta Xpath es, de hecho, un lenguaje de consulta de waypoint universal que se puede utilizar para buscar cualquier elemento de las estructuras de datos en forma de árbol, que incluyen JSON.

Las transformaciones XSLT también son otra forma de transformar documentos XML, cuyo conocimiento permitirá a los estudiantes no reinventar la rueda en el futuro cuando se encuentren con ETL.

Lección 12. ORM (mapeo relacional de objetos)

Casi cualquier marco de programación web moderno proporciona algún medio para la transformación relacional de objetos. Los estudiantes necesitan entender:

  • por qué se necesita tal mecanismo;
  • ¿Cuáles son sus limitaciones?
  • cómo usarlo en la práctica.

En este caso, todo se considera en el contexto de Ruby on Rails.


Lección 13. Sesiones, seguridad y todo lo relacionado.

  • Un método de almacenamiento de estado basado en cookies.
  • Métodos de autenticación típicos.
  • Un ejemplo de agregar autorización en Rails.
  • Consideraciones de seguridad para aplicaciones web per se.


Conferencia 14. Servicios

  • Aspectos históricos
  • Recomendaciones específicas sobre el desarrollo y despliegue de sus propios servicios para la Web.


Lección 15. CMS (Sistemas de gestión de contenidos)
En la programación web, es importante no solo poder escribir una aplicación, sino también comprender si necesita escribirla. Esta conferencia es una demostración de los principales tipos de aplicaciones web ya creadas que se pueden personalizar según los requisitos de un cliente en particular y, si es necesario, finalizar.

  • Énfasis en herramientas Ruby.
  • El CMS más común escrito en PHP.


Lección 16. Hospedaje de aplicaciones web de Ruby en Internet

Se considera la ideología general de los servicios web. Se explican los orígenes de esta arquitectura con el formato XML de intercambio y su posterior modificación en la API web con JSON y REST o GraphQL.

  • Servidores web
  • Métodos de virtualización.
  • Formas de alojar la aplicación en Internet.


Cómo crear un curso para una universidad


Es difícil crear cursos de capacitación sobre temas relacionados con la programación, donde la tecnología cambia cada 5-10 años. Al crear un curso para una universidad, es necesario equilibrar entre la formación de habilidades prácticas en lenguajes de programación específicos y la presentación de los fundamentos teóricos necesarios para comprender las tecnologías como tales. Además, la diferencia entre la educación universitaria y los cursos de capacitación radica en la presentación sistemática del material, que también impone restricciones sobre cuándo y en qué volumen se puede enviar cierto material.

En los últimos años, ha habido una tendencia a grabar conferencias universitarias en video y crear cursos de video. El curso "Lenguajes de programación web" es el primer intento formal de nuestra universidad. Y en función de los comentarios, decidiremos cómo y en qué formato realizar nuevas entradas.

Hace 10 años era necesario actualizar radicalmente el plan de estudios, introduciendo, entre otras cosas, la programación web. En el Departamento de Sistemas y Redes de Computadoras, aproximadamente las mismas horas de capacitación se asignan tradicionalmente para cursos relacionados con la electrónica y el diseño de computadoras que para la programación. Además, los cursos de programación incluyen capacitación algorítmica en lenguajes de alto nivel Pascal, C, C ++ / Qt, capacitación en varios ensambladores, así como la teoría de lenguajes de programación y compiladores. E incluso lenguajes de programación para FPGA y hardware específico. Es decir, el departamento prepara especialistas universales que en el futuro eligen su propia especialización.

Necesitábamos identificar tecnologías web prometedoras que se puedan dominar en un semestre, y es deseable que estas tecnologías se puedan proyectar en otros lenguajes de programación.

¿Por qué rubí?


¿Por qué se selecciona Ruby? La elección de los lenguajes para la programación web es bastante rica. Además de Ruby, estos son PHP, Perl, Javascript, Java, Go y otros. Si nos acercamos desde la perspectiva de aplicaciones web altamente cargadas, enviando Benchmarks que dudan del Web Framework , vemos en primer plano C ++, Java, Rust, Ur, Go, etc. Ruby no es el más popular para el desarrollo web, ni el más rápido para Soluciones altamente cargadas. Sin embargo, Ruby tiene una serie de otras virtudes que lo convierten en un lenguaje de programación, del que cualquier programador educado debe tener en cuenta.

Ruby recientemente celebró su 25 aniversario, lo que significa que es un idioma bastante maduro. A pesar del hecho de que la mayoría de los idiomas mencionados también han pasado o están cerca de esta edad (Rust, Dart, Go todavía son "verdes" en comparación con él), Ruby es uno de los pocos idiomas que ha mantenido la compatibilidad con versiones anteriores a lo largo de los años.

En el mundo de Ruby, podemos decir que no hubo revoluciones ni cambios radicales. Se refiere a lenguajes inicialmente bien diseñados, cuyos conceptos básicos han sobrevivido hasta nuestros días sin cambios. Afirmaciones de rendimiento relacionadas con versiones anteriores a 1.8.7, que se suspendieron hace 10 años. Las versiones modernas cada año muestran un aumento múltiple en la productividad. Las afirmaciones de que este idioma no es muy popular son ciertas solo para nuestro país. Desafortunadamente, en nuestro país, las grandes empresas realmente lo están evitando inmerecidamente.

¿Por qué es Ruby bueno para la educación universitaria? Este es un lenguaje de objetos puro. Y dado que es dinámico, casi todo se puede redefinir. No hay tipos simples en su modelo (no pensaremos en la implementación de un sistema aquí, solo estamos hablando de un modelo). Cualquier dato es un objeto. El código es un objeto. Es decir, Ruby facilita el aprendizaje de los principios de la programación orientada a objetos. Además, la sintaxis del lenguaje es bastante simple y casi no tiene excepciones. Cualquier código escrito en el programa debe ejecutarse una vez, y no importa dónde esté escrito este código, dentro o fuera de la declaración de clase. Lo que sea que esté escrito, se cumplirá. La sintaxis de Ruby es muy flexible, lo que la hace muy conveniente para escribir lenguajes específicos de dominio (DSL / DSEL). Además, el concepto básico de Ruby, el bloque, es una función anónima. El dominio de estos principios permite a los estudiantes dominar fácilmente la programación funcional en lenguajes de programación puramente funcionales.

Y, más bien, el mérito decorativo de Ruby: no es necesario perder el tiempo explicando el formato obligatorio del código con sangría. El programa está claramente marcado de todos modos. El formateo proporcionará automáticamente rubocop, y los estudiantes aprenderán a escribir correctamente con el tiempo.

¿Por qué Ruby no es popular?


¿Por qué Ruby, con tales ventajas, todavía no es popular y se refiere a idiomas con un alto umbral de entrada?

Lo primero que debe entender: Ruby no es solo otro lenguaje de programación imperativo que puede comenzar a programar por la noche, sino que comprende completamente en una semana. Este es un idioma diferente con una filosofía diferente.

El primer principio de Ruby: el texto del programa debe ser percibido como texto en lenguaje natural. Es decir, Ruby es un lenguaje para un programador que es una persona, y no un lenguaje para el que necesita encontrar el programador adecuado. Desafortunadamente, la mayoría de los lenguajes de programación modernos siguen el principio de "el programador resistirá", y la retirada ya se percibe con dificultad.

Ruby a menudo es criticado por hacer lo mismo de docenas de maneras. Pero en el lenguaje natural tenemos una gran cantidad de sinónimos, y es la elección del sinónimo correcto lo que enriquece nuestro discurso. Así es en Ruby. Además del hecho de que las mismas acciones se pueden realizar de diferentes maneras, hay muchos sinónimos asociados con los mismos métodos asociados con los métodos especiales alias y alias_method .

Un ejemplo simple de las limitaciones de la mayoría de los otros lenguajes de programación. Suponga que hay una variedad de productos y desea determinar que no está vacío. En la mayoría de los idiomas, escribiremos algo como if (products.size() > 0 ) .... Pero, al haber venido a la tienda, no le preguntamos al vendedor: "¿Si tiene más de cero de tal o cual producto?" Hacemos una pregunta simple: "¿Tiene tal o cual producto?". En Ruby, debe usar métodos que expresen el significado de la acción. Sí, podemos usar el cheque "mayor que cero", pero la forma natural es preguntar if products.any . Eso es literalmente: ¿hay productos? Tenga en cuenta que Ruby funciona bien con Unicode, por lo que si es necesario, en función de este idioma, puede crear idiomas especializados con adaptación regional. Por ejemplo, si desea redefinir en ruso todos los nombres de clases y métodos.

Un ejemplo interesante, aunque no del todo directo: Bato: un puerto rubí para filipinos .

Sobre el tema de la objetividad del lenguaje: Ruby distingue claramente entre variables / constantes y objetos. Debido a la naturaleza dinámica del lenguaje, los datos "viven" su vida como objetos. Cualquier identificador es una constante o variable que solo se refiere a un objeto. La incomprensión de este principio lleva a sorpresas:

 str1 = "Test" str2 = str1 str1.sub! "Te", "La" puts str2 # => "Last" ????    str1,  ?.. 

Aquí solo usamos el método de modificación del objeto, cuyas referencias fueron almacenadas por dos variables. Noto que esta no es una forma tradicional para que Ruby cambie. Por lo general, los objetos se mantienen sin cambios y los cambios dan lugar a nuevos objetos. Además, el método sub! Utilizado aquí tiene un sufijo, un signo de exclamación, que es el esquema de nomenclatura aceptado por Ruby para los métodos que modifican el objeto en sí. Sin este símbolo, el método simplemente genera un nuevo objeto.

Otra característica de Ruby, que a menudo desconcierta a los desarrolladores que provienen de otros lenguajes de programación: el concepto de "bloque". Sintácticamente, el bloque se ve igual que en otros lenguajes de programación, y en dos versiones a la vez: {…} y do..end (no olvide que Ruby fue creado para humanos, por lo que elegimos corchetes para una mejor legibilidad si la expresión es de una sola línea y palabras si hay muchas líneas) La esencia de un bloque en Ruby es el código que se almacena como un objeto y se puede activar llamando a yield . La contrapartida directa en C y C ++ son funciones de devolución de llamada. En Javascript, una función anónima como some_func('on_element_click', function(event) {…} ).

Gracias a este concepto, Ruby es uno de los lenguajes de programación más concisos y expresivos. Por ejemplo, la conversión de los elementos de una matriz de acuerdo con la función de cuadratura se verá así:

 (1..5).map { |x| x * x } # => 1, 4, 9, 16, 25, 

donde { |x| x * x } { |x| x * x } : un bloque con una variable local declarada x , es decir, una función para convertir elementos de matriz. Y el método al que se transmite simplemente se llama mapa (es decir, "mapa"). Y no necesita escribir la palabra return , aunque esto es posible, porque todo ya está claro (en Ruby, el resultado de la última operación siempre es el valor de retorno). Además, el código de bloque es un código llamado de forma autónoma para cada elemento de la matriz. Es por eso que no tiene sentido intentar iniciar las variables dentro del bloque y esperar que su valor se conserve durante el procesamiento del siguiente elemento. Un bloque es una función de procesamiento almacenada, y no más.

Si queremos analizar una cadena con números ingresados ​​desde el teclado, simplemente escriba:

 gets.chomp.split.map(&:to_i) 

Es decir, lea la línea (gets), descarte cualquier basura como caracteres de chomp línea ( chomp ), to_i en palabras ( split ), llame a la conversión con la función to_i (estrictamente hablando, el método de los objetos del tipo "string"). Y nada mas. Split sabe que en el lenguaje humano normal, "romper una línea" significa separarlo por palabras, donde los delimitadores son espacios y signos de puntuación. El mapa se puede usar en una forma tan corta con el nombre del método que se tomará del objeto. Aunque sería posible escribir el map { |x| x.to_i } completo map { |x| x.to_i } map { |x| x.to_i } , o incluso { |x| return x.to_i } { |x| return x.to_i } . Pero esto no mejora la legibilidad, por lo que puede dejar solo el map(&:to_i) .

Observo que el concepto del bloque impregna francamente a Ruby. Incluso el código de vista

 class HelloWorld (1..3).each { puts 'Hi from class declaration!' } def hi   puts 'Hello World!' end end HelloWorld.new.hi 

se muestra en la pantalla:

Hi from class declaration!
Hi from class declaration!
Hi from class declaration!
Hello World!


¿Qué puede parecer inesperado aquí? El bucle dentro de la declaración de clase imprime mensajes. Luego recibimos un mensaje de un método de instancia de esta clase. Y el secreto es muy simple. Ruby es un lenguaje con un modelo de programación regular. Una forma típica de llamar a cualquier método con un bloque:

 method_with_block(args) do ... end 

Las palabras class y def en el ejemplo son esencialmente los nombres de los métodos a los que se pasan los argumentos HelloWorld , hi . El argumento HelloWorld se convertirá para nosotros en el nombre constante de la clase, y hi se convertirá en el nombre del método. El resto de la palabra end es un bloque. Y el código de bloqueo se activa llamando a rendimiento, después de lo cual todo se ejecuta secuencialmente. Es decir, incluso aquí no hay prácticamente ninguna diferencia entre llamar a un método regular y declarar métodos, clases, módulos.

También preste atención a la construcción de activación HelloWorld.new.hi . HelloWorld - constante - apunta a un objeto de tipo Class . Este objeto tiene un new método. El resultado de llamar a new es un objeto creado de tipo HelloWorld , desde el cual llamamos al método hi . E incluso aquí se manifiesta la regularidad de Ruby. No escribimos something = new HelloWorld , sino que simplemente llamamos al método de un objeto específico (la Class referencia HelloWorld ), que genera un objeto de tipo HelloWorld .

La falta de comprensión del idioma también se ve facilitada por largas cadenas de llamadas:



Si conoces JavaScript o jQuery, entonces no ves nada terrible aquí. Los que vinieron de C y C ++ pueden estar confundidos sobre el número de puntos. Ruby usa transformación funcional de objetos. Es decir, toda esta cadena es el proceso de convertir una cadena, que consiste en seleccionar palabras, convertirlas en números, seleccionar solo las pares, cuadrar y agregar el resultado.

Cualquier método en Ruby genera un objeto de valor. No hay excepciones Incluso nulo es un objeto. Dado que Ruby es un lenguaje dinámico con un recolector de basura automático, no es necesario crear nuevas variables. Los objetos intermedios serán eliminados. Es decir, una expresión larga se puede analizar fácilmente en una secuencia de asignación de valores a variables locales, que sucesivamente llaman los métodos correspondientes. ¿Pero por qué, si todo está claro ya?

En los programas de Ruby, es extremadamente raro ver bucles como for , while , loop . Se proporcionan en la sintaxis, pero casi nunca se usan. Por qué Sí, porque no llevan una carga semántica.

Ejemplo: en una variedad de productos necesita encontrar un "bollo con semillas de amapola". Para los lenguajes de programación tradicionales, podemos usar aproximadamente el siguiente código Ruby:

 products…# -    — . found_product = nil for i in 0...products.size do if products[i].name == '  '   found_product = products[i]   break end end if  found_product != nil #  ,  - . end 

En este caso, el código normal de Ruby se ve así:

 products… # -   - found_product = products.find { |product| product.name.eql? '  ' } unless found_product.nil? #  ,  - . end 

Es decir, escribimos literalmente en una línea: busque el producto por su nombre. Y eso es todo. Porque en realidad solo nos interesa la selección de bienes, y no todos los índices de bienes y su cantidad.

Ejemplo de vida: llegaste a la tienda y le preguntaste al desafortunado vendedor de dos maneras: la primera: " Para todos los productos de cero a 15143, si el nombre del producto es igual a un bollo con semillas de amapola, dámelo "; el segundo: " Dame un bollo con semillas de amapola ". Ambas opciones parecen ser sintácticamente correctas, pero la segunda es natural. Por alguna razón, la mayoría de los programadores consideran que la primera opción es normal. Y los programadores de Ruby son los segundos. Y el método de find aquí es solo uno de los reemplazos de bucle. Llamo la atención sobre esto, anticipando comentarios de que otros idiomas también tienen una búsqueda de matriz con una función de selección.

Entonces, aunque hay construcciones de sintaxis for , while y loop en Ruby, casi nadie las usa porque hay métodos específicos: each , each_index , each_with_index , select , map , reduce , find , detect y muchos otros que expresan un significado específico: para cada índice, para cada elemento y su índice, seleccionar, transformar, contraer, buscar, etc. Y si necesitamos obtener índices, usaremos array.each_index . Y si necesita seleccionar elementos, use select . Énfasis en la naturalidad. Solo preguntamos qué es lo que realmente hay que hacer. No se necesita índice, no es necesario solicitarlo. Consulte la documentación del módulo Enumerable para obtener más detalles.

Resumen


Ruby es un lenguaje sintácticamente simple pero flexible con un modelo de objeto desarrollado, cuyo énfasis principal es un código conciso pero bien percibido centrado en una persona viva. Ruby está presente de forma predeterminada en el paquete de cualquier sistema operativo moderno (o se puede instalar en Windows). Se ha escrito una gran cantidad de programas en este idioma, hay comunidades estables listas para ayudar con consejos o acciones. Los programas Ruby son scripts de administración básicos para Linux y MacOS (OpenSuSE / SuSE y brew.io respectivamente), esto es matemática y aprendizaje automático , estas son pruebas (Rspec, Cucumber, Capybara ...), esto es implementación de aplicaciones (Puppet, Chef) y mucho mas

Si los estudiantes conocen a Ruby, esto ampliará significativamente sus horizontes y les permitirá tener una visión completamente diferente de las cosas familiares. Además, es muy fácil aprender otros lenguajes de programación de secuencias de comandos después de Ruby, pero la pregunta es si desea usarlos.

Source: https://habr.com/ru/post/es419765/


All Articles