En publicaciones anteriores, hablamos sobre lo que hacen nuestros estudiantes en pasantías: científicas (por ejemplo, en JetBrains Research ) e industriales . En esta publicación queremos compartir cómo enseñamos programación industrial.

Brevemente: en cuatro cursos, un ex alumno prueba una docena o dos tecnologías e idiomas, escribe y elimina constantemente una gran cantidad de código, pasa una revisión de código de camaradas más experimentados (no siempre el primer intento), profundiza en algún tema y finalmente defiende un diploma significativo. Todo esto tiene lugar en la universidad y otorga un diploma estatal. Y en el verano puedes relajarte o hacer prácticas en Rusia en JetBrains, Yandex y JetBrains Research (si quieres más ciencia) o ir al extranjero (Google, Facebook y otros). Ahora con más detalle.
Sobre mi
Mi nombre es Yegor Suvorov, estudio en la Escuela Superior de Economía, internado en Google (dos veces), Asana, GSA Capital, participé con éxito en la programación internacional de Olimpiadas ( estudiantes y escuelas ). El año pasado me gradué de la licenciatura de la Universidad Académica, así que revisé casi todo lo descrito en el post. También participo en el desarrollo de un programa de capacitación en ingeniería de software y realizo ejercicios prácticos en varias materias (Paradigmas y lenguajes de programación, C ++).
Componentes principales
En esta publicación, solo consideraremos la subdirección "Programación industrial". Aunque todavía tenemos "Aprendizaje automático", "Lenguajes de programación" y algunos otros, los programas en las instrucciones se superponen, especialmente en los primeros dos cursos.
La formación consta de tres partes principales. Primero daré una descripción general, y luego contaré con más detalle acerca de cada parte.
- Artículos básicos Desde el primer semestre, los niños aprenden a trabajar con las manos. Cada seis meses, todos los "programadores industriales" deben aprobar 2-4 asignaturas básicas (y algunas asignaturas son necesarias para otras subdirecciones). Propósito: impulsar a un estudiante en más o menos todas las áreas de programación, para que pueda caminar a través de los niveles de abstracciones hacia arriba y hacia abajo. Comenzando por escribir su sistema operativo de juguete con espacio de usuario en C con una pizca de ensamblador (para los más persistentes) y la línea de comando, luego a través de la semántica de movimiento en C ++ y hasta transformadores de mónada. Esto es necesario para formar los horizontes y la experiencia de diferentes programas. Enseñamos no solo lenguajes: programación paralela, redes, bases de datos, también. Y, por supuesto, pocos temas no se refieren al código, pero es lo mismo en el caso: por ejemplo, Ingeniería de Software (curso general: por qué necesitamos equipos / gerentes / gestión de proyectos y riesgos) y diseño de interfaz (de lo contrario pensarán que "los moldes están remachados - es fácil ") También hay matemáticas y algoritmos, pero este es un tema para una publicación separada.
- Práctica semestral . Deben completarse necesariamente, a partir del segundo semestre. Propósito: dar al alumno que intente hacer cosas diferentes más grandes que la tarea y comprender cómo es más. Al comienzo del semestre, se lleva a cabo una feria de proyectos donde los posibles líderes de investigación hablan sobre lo que puede hacer con ellos. Un título para un líder, por cierto, es opcional; mucho más importante es lo que una persona y práctica específicas pueden darle al estudiante. En un semestre, puede crear una aplicación de escritorio + móvil en Qt y comprender cómo trabajar generalmente en un proyecto durante todo el semestre sin requisitos técnicos claros (con dificultad). Lo siguiente es probar Android y sentirse como "hacer un cliente confiable para la red social"; resulta difícil, incluso si la funcionalidad es muy limitada. En otro, intente crear algún tipo de herramienta de aprendizaje automático en Python y tenga en cuenta que no desea tratar este tema en absoluto. En el cuarto, ve a terminar el compilador de Haskell, horrorízate y regresa al amoroso C ++ al diploma. O viceversa. Depende del alumno: este es el significado de la práctica. Como resultado, el alumno forma una dirección favorita (en la que puede trabajar y hacer un diploma) o experimenta en un montón de direcciones diferentes. Ganar-ganar de todos modos. Por cierto, si no te gusta ninguno de los proyectos, puedes crear el tuyo. Pero en este caso, primero debe interesar a algún asesor científico o encontrar a alguien del exterior, y luego convencernos de que algo significativo y protegido puede salir del proyecto.
- Artículos opcionales Aparecer en el tercer año. Motivo: no todos quieren profundizar en el kernel de Linux, del mismo modo que no todos quieren profundizar en el diseño de Scala Collections con toneladas implícitas. Y así puede elegir en qué temas profundizar. Por ejemplo, si a un estudiante no le gustó la cantidad de maneras de disparar una rodilla en las ventajas, puede tomar un curso sobre virtualización de contenedores en Linux, escribir en C puro y ser feliz. Y viceversa: si el "volumen 3 del manual del desarrollador de software de arquitecturas Intel 64 e IA-32" todavía tiene pesadillas, puede entrar en el hermoso mundo de Scala con abstracciones de unicornio. En cada módulo (medio semestre), se ofrecen aproximadamente 4 cursos, de los cuales se deben elegir dos.
Además, queremos que los estudiantes disfruten aprendiendo. En cualquier momento, puede chatear con los administradores de programas y proponer mejoras en cualquier campo. Recopilamos comentarios cuatro veces al año y, atención, los tomamos en cuenta y mejoramos constantemente el programa. No reclutamos específicamente a muchos estudiantes para que tengamos la oportunidad de hablar personalmente con todos. Hay 30 estudiantes en el segundo y tercer año, y en el cuarto año - 15.
También estamos constantemente creando o buscando nuevos cursos a pedido de los estudiantes, buscando buenos maestros que entiendan el tema y puedan enseñar. Entonces, en este módulo, en solo unas pocas semanas, apareció con éxito un curso experimental de ingeniería inversa de SPbCTF . Y si no puede encontrar un curso adecuado, puede, por acuerdo, pasar por algo significativo con Computer Science Center , ShAD o Coursera.
Artículos básicos
Temas básicos de programación: C ++, sistemas similares a Unix, paradigmas y lenguajes de programación, arquitectura informática, Java, sistemas operativos, programación funcional, bases de datos, diseño de software, ingeniería de software, programación paralela, tecnologías de red informática, diseño de interfaz, desarrollo móvil.
Juntos, estos temas cubren casi todas las tareas que pueden ocurrir en el trabajo. También protegen contra varios errores "clásicos", como comparar números de coma flotante con ==, expectativas de adecuación de comportamiento indefinido, condiciones de carrera y hablar sobre la existencia de patrones de diseño y tareas no programadas en el desarrollo de productos.
Por supuesto, en el proceso de aprendizaje, los estudiantes constantemente "tienen en sus manos el laboratorio y la tarea". Tomemos algo clásico, por ejemplo, la implementación del archivador en el algoritmo Huffman. Hacer que "funcione de alguna manera" no es tan difícil. Pero para hacer una buena arquitectura del proyecto (al menos para separar la entrada-salida, la compresión de bits y el algoritmo en sí), use correctamente las capacidades de C ++ (la regla de tres o cinco dependiendo del medio año) y, en general, diseñe el código de tal manera que sea agradable de leer y no completamente vergonzoso poner en código abierto: un arte separado que los maestros enseñan en un curso de C ++, comunicándose constantemente con los estudiantes y analizando en detalle todas las líneas de código. Sobre los temas restantes es similar. Ningún curso se limita a pruebas teóricas. En todos los temas con escritura de código habrá revisión de código de un programador experimentado.
C ++ . El primer año de estudio. Comenzando con C, terminando con C ++ 14. Mostramos RAII, Valgrind y autotests, aprendemos a escribir tanto bibliotecas (my_vector con una garantía de excepciones) como aplicaciones (el mismo archivador). Por qué: debido a que C ++ todavía se usa activamente en la industria, además resuena activamente con la programación del sistema (falta de recolección de basura, puede mostrar el diseño de los datos en la memoria ...).
Sistemas tipo Unix . Primer semestre El curso del joven luchador sobre cómo trabajar con la línea de comando y el sistema de archivos sin C:\
y D:\
. Ejemplo de trabajo de prueba: en el par, se escucha la imagen de un Ubuntu instalado ligeramente roto, es necesario arreglarlo. Un ejemplo de tarea: revisa los archivos en una carpeta en Bash y llama a alguien útil con expresiones regulares.
Paradigmas y lenguajes de programación . Primer semestre Una docena de temas (al menos OOP, programación funcional, SQL, subprocesos múltiples), y cada tema que los estudiantes pueden probar en una o dos tareas. Por supuesto, de manera bastante superficial, pero aún da una idea de cuán versátil es la programación y qué cosas geniales se pueden ensamblar utilizando diferentes métodos. Tanto OOP, FP y SQL se describirán en detalle, pero ya en el primer año el estudiante sabe acerca de su existencia y puede, por ejemplo, organizar afirmaciones en el código o escribir un par de pruebas unitarias simples si lo desea.
Arquitectura informática Primer año Registros, un ensamblaje de algo parecido a una computadora a partir de puertas lógicas, cachés, una tubería de procesador, representación de números y otra teoría. Por qué: unir piezas de información sobre todo tipo de cosas de bajo nivel en una sola imagen.
Java Segundo año de estudio. Termina con transmisiones y un proyecto de curso para Android (por ejemplo, jugar un tic-tac-toe recursivo con un bot y un modo de red). Mostramos Maven, IDEA, JUnit, trabajo asincrónico con la red. Por qué: hay muchas cosas girando en la JVM ahora, hay toneladas de bibliotecas, es bueno saberlo.
Sistemas operativos Segundo año Hardcore No se preocupe con los cargadores de arranque: los estudiantes reciben arranque múltiple en el prefabricado, cambian al modo protegido, y luego pueden escribir un asignador de memoria, hilos, procesos, sistema de archivos, partición de anillo de protección e incluso carga ELF en C. Quizás no sea tan extenso como los "Sistemas operativos modernos" de Tannenbaum, pero puede ver claramente si es interesante profundizar en él o si desea permanecer en un espacio de usuario aislado. Si está interesado, bienvenido a un curso especial de programación del kernel de Linux. Por cierto, una versión muy ligera está disponible en Stepik : no hay ningún sistema operativo escrito allí, pero hay las tareas necesarias de teoría y verificación. Para no volar debido al bajo rendimiento, simplemente repásalo.
Programación funcional Dos clases sobre cálculo lambda y luego fui a Haskell. Terminamos con transformadores de mónadas. Por supuesto, todo está detallado: una mónada no es una caja, sino solo una abstracción útil de dicha plantilla para escribir código. Sin embargo, los proyectos intermedios son más teóricos que prácticos: escriba la inferencia automática de tipos en el cálculo lambda. Pero ahora se está preparando la continuación del curso (como un tema adicional del programa de maestría), donde se planean múltiples subprocesos y un servidor web. Lea también en el Computer Science Center .
Bases de datos Nos familiarizamos con el DBMS relacional (en el ejemplo de PostgreSQL), SQL. Diseñamos una base de datos para un área temática determinada, y luego organizamos una revisión de código para cada uno en base a la guía del maestro. Luego el maestro hace una revisión de revisión de código. Los concursos del formulario "escriben una solicitud para esta base de datos". Trabajos de consultas de perfiles simples (EXPLICAR). Nuevamente, se hace eco del curso en el Computer Science Center .
Ingeniería de software . Habla sobre cómo se puede organizar el trabajo de un programador, qué hacen los demás en la empresa, por qué los buenos gerentes siguen siendo útiles y por qué la gestión de proyectos también es difícil. ¿Cuál es el punto de la planificación, por qué no siempre funciona, por qué no todos los errores deben repararse ... El objetivo es tener una comprensión de lo que se necesita para proyectos que no sean personas. Por supuesto, no es realista revelar todo en detalle en un semestre, pero, por ejemplo, es útil saber que después del desarrollo del proyecto todavía no hay un apoyo menos importante.
Diseño de software . Todo tipo de formas de modelar la realidad y (diagramas UML), métodos de descomposición, patrones de diseño. Como ejemplos, al final del curso, entendemos GFS, BigTable, CMake ... En la práctica, aprendemos no solo a escribir código, sino también a describir la arquitectura y aplicar plantillas donde son apropiadas.
Programación concurrente Comenzamos con subprocesos y mutexes simples, al final analizamos y escribimos algoritmos sin bloqueo / sin espera, penetramos en MESI, estudiamos tecnologías de nivel superior como el marco de unión de horquilla, OpenMP, OpenCL, Intel TBB.
Tecnología de red informática . Conferencias: una descripción detallada de los principales protocolos de la pila TCP / IP: mensajes en ICMP, una excursión histórica a RIP, todo tipo de registros en DNS, cómo funciona FTP / HTTP / SMTP / DHCP, qué es NAT e incluso un poco sobre IPv6. Prácticas: escribimos en las ventajas de nuestro cliente y servidor TCP multiplataforma, primero para el mensajero de juguete, y luego el cliente UDP para DNS.
Diseño de interfaz El estudiante no escribe una sola línea de código, sino que pasa por todas las etapas de diseño de una buena experiencia de usuario: se le ocurre un proyecto, realiza una investigación (incluida una encuesta de personas reales), desarrolla y verifica escenarios de uso, y al final puede dibujar una interfaz en Sketch o Figma . El objetivo es comprender que para un buen producto no solo necesita código, sino también un montón de otros trabajos preparatorios. La revisión del código no está aquí, pero todos los artefactos intermedios se discuten activamente con el maestro. Me parece poco realista pasar la tarea en el primer intento (sin embargo, no es obligatorio).
Desarrollo móvil . Curso avanzado de desarrollo de Android. Ya estamos escribiendo más en Kotlin que en Java, utilizamos todo tipo de cosas específicas de Kotlin para Android. En comparación con el proyecto Java del segundo año, la aplicación es más complicada aquí, trabajamos más con dependencias externas y bibliotecas, pensamos más en la interfaz y los usuarios (aquí el curso tiene algo en común con el diseño de la interfaz).
Pruebas de software . Básicamente, existe una gran cantidad de teoría que da nombre a todas las prácticas estándar que los estudiantes probablemente han inventado en otras materias: prueba del flujo de control o flujo de datos, prueba de pares (pruebas de todos los pares) ... También hay un poco de práctica específica: elaborar un plan de prueba para tal y tal la técnica, para encontrar casos extremos en tal y tal aplicación, y ejecutar varios escenarios en una aplicación web usando Selenium para que no sea aburrido componer simplemente casos.
Big Data Software Engineering, también conocido como Big Data Software Engineering. Lea junto con el Computer Science Center . Conectamos bases de datos, programación paralela, sistemas distribuidos y otras palabras de moda, estas están en conferencias. En la práctica el año pasado, los estudiantes escribieron su directorio telefónico distribuido desde cero. En los próximos lanzamientos, parece correcto cambiar el énfasis de un nivel bajo a herramientas realmente utilizadas en la industria como Zookeeper, Cassandra y otros animales que dan miedo. Hasta ahora, la principal dificultad es cómo emular las condiciones de "big data" para los estudiantes y evaluar sus soluciones: no hay necesidad de aumentar Zookeeper si no hay una demostración clara de que sin ella todo es muy malo.
Practica
La segunda parte importante de la capacitación es la práctica. Desde el primer año, el alumno realiza algunas tareas prácticamente útiles bajo la guía de un colega experimentado. Por ejemplo, otra aplicación para administrar un calendario o notas. O nueva funcionalidad en una aplicación existente. O estudia la complejidad de computabilidad de una familia de fórmulas si se lleva a la dirección de la informática.
En los primeros cursos, no requerimos novedad o practicidad (después de todo, el objetivo es dar algo de juego), pero los requisitos de diploma para la calidad de los proyectos y la protección están aumentando. En los últimos cursos, además de la pregunta "¿qué se ha hecho?" Es importante que los estudiantes digan por qué se hace y por qué. Al mismo tiempo, "realmente quiero esta compañía en particular, en la que trabaja mi supervisor de investigación", en sí misma no es la respuesta. Pero "allí, los discos duros mueren cada segundo, por lo que este código abierto no funciona, este artículo es puramente teórico, pero Google tiene una solución, pero está cerrado", eso es todo. No funcionará como un diploma para proteger un ejercicio innecesario del segundo año: los desarrolladores curiosos con computadoras portátiles y Google están listos para defender (y algunas defensas). "Nadie ha hecho esto todavía", prácticamente lo más peligroso que se puede decir. Por cierto, defendemos no solo los diplomas, sino también las prácticas, regularmente desde el primer año.
Aquí hay algunas fotos con protección típica. Fotógrafo: Dima Drozdov.


Las prácticas le permiten aprender a trabajar "a la larga" con grandes proyectos, a veces parcialmente escritos por otros desarrolladores. No siempre es posible adivinar el tema del proyecto: por ejemplo, después de haber intentado un desarrollo de bajo nivel, un estudiante puede decidir estudiarlo en el futuro. Este es el significado de la práctica: entender lo que te gusta y lo que no, no en el trabajo, sino en condiciones con tasas más bajas. Aunque esta última práctica debería convertirse en una licenciatura sustancial. "Sustantivo" es cuando, según el diploma, al menos puedes escribir un artículo sobre Habr y no entrar en menos. O, si el trabajo es muy bueno, publíquelo en una revista científica, hable en una conferencia o, al menos, obtenga las ventajas.
Artículos electivos
La tercera parte, pero también importante, son elementos adicionales. Los temas son específicos, probablemente no sean necesarios para todos, pero los estudiantes interesados pueden probarlos. En los cursos superiores hay la mayoría de estas asignaturas: hay una base, queda por ampliar nuestros horizontes en una dirección interesante para el estudiante. Desafortunadamente, no hay tiempo suficiente para tomar todos los artículos. A veces el conjunto de cursos cambia, estos son los que me ofrecieron:
Lenguajes alternativos para la JVM . Un curso de dos módulos: en uno hablan sobre Kotlin, en el otro sobre Scala. Para Kotlin, analizamos tanto la interoperabilidad de Java como la escritura de nuestro propio DSL y corutinas. La última tarea opcional es agregar un depurador usando corutina al intérprete de lenguaje de juguete (escrito en la tarea anterior). En cuanto a Scala ... El lenguaje es grande, pero tenemos tiempo para entender todo tipo de implícitas :)
Programación en el kernel de Linux . Paso a paso, se está desarrollando un módulo kernel que emula un dispositivo de almacenamiento virtual: mmap, buffers, acceso concurrente, E / S sin bloqueo. En el camino, puede recordar interrupciones y desplazar la multitarea del curso de los sistemas operativos y estudiar las estructuras internas de Linux (por ejemplo, la cola de espera).
Compiladores Estamos escribiendo nuestro compilador de micro-idiomas en OCaml. Una máquina de pila intermedia, compilación en x86 sin ningún LLVM, integración con libc. Exclamaciones sorprendidas de los estudiantes "¿por qué solo cae en la expresión de una longitud de cien?" (probablemente porque el error está en la asignación de registros). Por cierto, un curso similar también está disponible en el Computer Science Center .
Gráficos por computadora . Curso de nivel relativamente bajo: estudiamos OpenGL, escribimos nuestros sombreadores para sombras y renderizado diferido, comparamos la mezcla de colores con y sin corrección gamma.
Construyendo un DBMS . Base de datos interna del dispositivo. Todo tipo de algoritmos de conexión, modelos formales, columna DBMS. En la práctica, puede implementar varios algoritmos de procesamiento de bloque por bloque en un DBMS de juguete con ventajas (por ejemplo, unión hash doblemente canalizada).
Virtualización de contenedores . Un estudio detallado de contenedores en Linux. Espacios de nombres y cgroups, por ejemplo, y la API, y cómo funciona. Todo tipo de herramientas auxiliares para la red. En el proceso, escribimos nuestro contenedor como Docker, pero no es tan simple: debe limitar correctamente un montón de todo, configurar la red, reenviar los archivos necesarios al contenedor ... Sin embargo, también se considera la orquestación de alto nivel usando Kubernetes como ejemplo.
Lo que queremos mejorar
Tanto nosotros como nuestros estudiantes estamos más satisfechos con el programa resultante (a juzgar por las encuestas). Sin embargo, puede hacerlo aún mejor, no solo mejorando los elementos existentes, sino también agregando nuevos.
Por ejemplo, todavía no está claro cómo transferir ciertos aspectos de la "experiencia laboral" a la universidad. El mismo trabajo con código heredado, ¿útil? Y entonces Incluso hay libros y técnicas específicas. Pero para hacer un buen curso de esto, se deben combinar varios factores:
- No distraiga a los maestros de su trabajo principal durante mucho tiempo, para que constantemente ayuden a los estudiantes a comprender un proyecto grande. Y si hay buena documentación, entonces ya no es así para Legacy.
- Los estudiantes deberían estar interesados. "Agregar mil líneas de código a un proyecto que no necesita" no está incluido.
- El resultado debe ser predecible. "Parece que esta es una tarea insoluble, lo siento, no pensaron": malas noticias según los resultados de revisar la tarea.
Desafortunadamente, aún no hemos descubierto cómo hacer esto. Lo más cercano está en la dirección del aprendizaje automático, donde se realizan seminarios todas las semanas en los que los estudiantes hacen presentaciones sobre algunos de los últimos artículos. Quizás esta experiencia se pueda transferir a la programación industrial.
Quizás las únicas áreas que no están cubiertas actualmente son el desarrollo web (incluido el front-end), los sistemas de automatización complejos (como 1C o SAP) y la seguridad informática (un curso experimental comenzó a principios de febrero de 2019). Es posible que hayamos olvidado algo más, o usted sabe cómo puede enseñar a programar aún mejor; estaremos encantados de analizarlo en los comentarios.
Sin embargo, creemos que los graduados que están listos para trabajar y que, si es necesario, deben recibir una enseñanza especial, entonces quizás los sistemas internos de la empresa, ya están dejando el bachillerato. Por cierto, un tema separado en el que ahora estamos pensando e intentando implementar es lo que, después de una serie de cursos tan ajustados, estudiar en un programa de maestría, pero este es un tema para una publicación separada.