Como ensinamos Engenharia de Software no HSE de São Petersburgo

Em posts anteriores, falamos sobre o que nossos alunos fazem em estágios: científico (por exemplo, na JetBrains Research ) e industrial . Neste post, queremos compartilhar como ensinamos programação industrial.



Resumidamente: em quatro cursos, um ex-aluno tenta uma dúzia ou duas tecnologias e idiomas, constantemente escreve e remove muito código, passa uma revisão de código de camaradas mais experientes (nem sempre a primeira tentativa), investiga alguns tópicos e defende um diploma significativo. Tudo isso acontece na universidade e dá um diploma estadual. E no verão, você pode relaxar ou fazer estágio na Rússia na JetBrains, Yandex e JetBrains Research (se você quiser mais ciência) ou ir para o exterior (Google, Facebook e outros). Agora com mais detalhes.


Sobre mim


Meu nome é Yegor Suvorov, estudo na Higher School of Economics, internado com o Google (duas vezes), Asana, GSA Capital, participei com sucesso das Olimpíadas de programação internacional ( alunos e escolas ). No ano passado, me formei na graduação da Universidade Acadêmica, por isso passei por quase tudo descrito no post. Também participo do desenvolvimento de um programa de treinamento em engenharia de software e conduzo exercícios práticos em diversas disciplinas (paradigmas e linguagens de programação, C ++).


Componentes principais


Neste post, consideraremos apenas a subdiretação "Programação Industrial". Embora ainda tenhamos “Machine Learning”, “Programming Languages” e alguns outros, os programas nas direções se sobrepõem, especialmente nos dois primeiros cursos.


O treinamento consiste em três partes principais. Primeiro darei uma visão geral e, depois, contarei mais detalhadamente sobre cada parte.


  1. Itens básicos . Desde o primeiro semestre, as crianças aprendem a trabalhar com as mãos. A cada seis meses, todos os "programadores industriais" devem passar de 2 a 4 disciplinas básicas (e algumas disciplinas são necessárias para outras sub-direções). Objetivo: bombear um aluno em mais ou menos todas as áreas da programação, para que você possa percorrer os níveis de abstração para cima e para baixo. Começando por escrever seu sistema operacional de brinquedo com espaço do usuário em C com uma pitada de assembler (para os mais persistentes) e a linha de comando, depois através da semântica de movimento em C ++ e até transformadores de mônada. Isso é necessário para formar os horizontes e a experiência de diferentes programações. Ensinamos não apenas linguagens: programação paralela, redes, bancos de dados também. E, é claro, poucos assuntos não são sobre código, mas é o mesmo no caso: por exemplo, Engenharia de Software (curso de visão geral: por que precisamos de equipes / gerentes / gerenciamento de projetos e riscos) e design de interface (caso contrário, eles pensam que “os moldes são rebitados - é fácil. ”) Há também matemática e algoritmos, mas esse é um tópico para uma postagem separada.
  2. Prática semestral . Eles devem ser preenchidos necessariamente, a partir do segundo semestre. Objetivo: dar ao aluno que tente fazer coisas diferentes que não sejam as tarefas de casa e entender como é. No início do semestre, é realizada uma feira de projetos em que os líderes em potencial falam sobre o que você pode fazer com eles. Um diploma para um líder, a propósito, é opcional - muito mais importante é o que uma pessoa e prática específica podem dar ao aluno. Em um semestre, você pode criar um aplicativo de desktop + móvel no Qt e entender como geralmente trabalha em um projeto durante todo o semestre sem requisitos técnicos claros (com dificuldade). O próximo passo é experimentar o Android e sentir como "criar um cliente confiável para a rede social" - acaba sendo difícil, mesmo que a funcionalidade seja severamente limitada. Em outro, tente criar algum tipo de ferramenta de aprendizado de máquina no Python e perceba que você não deseja lidar com esse tópico. Na quarta - vá terminar o compilador Haskell, fique horrorizado e volte para o querido C ++ para obter o diploma. Ou vice-versa. Depende do aluno - este é o significado da prática. Como resultado, o aluno forma uma direção favorita (na qual você pode trabalhar e fazer um diploma), ou experimenta várias direções diferentes. Vantajoso para as duas partes de qualquer maneira. A propósito, se você não gosta de nenhum dos projetos, pode criar o seu próprio. Mas, nesse caso, primeiro você precisa interessar a um consultor científico ou encontrar alguém de fora e depois nos convencer de que algo significativo e protegido pode sair do projeto.
  3. Itens opcionais . Aparecer no terceiro ano. Razão: nem todo mundo quer se aprofundar no kernel do Linux, assim como nem todo mundo quer se aprofundar no design do Scala Collections com toneladas de implícitos. E assim você pode escolher em quais tópicos se aprofundar. Por exemplo, se um aluno não gostou do número de maneiras de acertar um joelho nas vantagens, ele pode fazer um curso sobre virtualização de contêineres no Linux, escrever em C puro e ser feliz. E vice-versa: se o "volume 3 manual do desenvolvedor de software das arquiteturas Intel 64 e IA-32" ainda tiver pesadelos, você poderá entrar no belo mundo de Scala com abstrações de unicórnios. Em cada módulo (meio semestre), são oferecidos aproximadamente 4 cursos, dos quais dois devem ser escolhidos.

Além disso, queremos que os alunos gostem de aprender. A qualquer momento, você pode conversar com os gerentes de programas e propor melhorias em qualquer campo. Coletamos feedback quatro vezes por ano e - atenção - levamos em conta e melhoramos constantemente o programa. Não recrutamos especificamente muitos alunos para termos a oportunidade de conversar pessoalmente com todos. Há 30 alunos no segundo e terceiro anos e no quarto ano - 15.


Também estamos constantemente criando ou procurando novos cursos a pedido dos alunos, procurando bons professores que entendam a matéria e sejam capazes de ensinar. Portanto, neste módulo, em apenas algumas semanas, um curso experimental de engenharia reversa do SPbCTF apareceu com sucesso. E se você não conseguir encontrar um curso adequado, poderá, por acordo, passar por algo significativo com o Computer Science Center , ShAD ou Coursera.


Itens básicos


Disciplinas básicas de programação: C ++, sistemas tipo Unix, paradigmas e linguagens de programação, arquitetura de computadores, Java, sistemas operacionais, programação funcional, bancos de dados, Design de Software, Engenharia de Software, programação paralela, tecnologias de redes de computadores, design de interfaces, desenvolvimento móvel.


Juntos, esses assuntos abrangem quase todas as tarefas que podem ocorrer no trabalho. Eles também protegem contra vários erros "clássicos", como comparar números de ponto flutuante com ==, expectativas de adequação de comportamento indefinido, condições de corrida e falam sobre a existência de padrões de design e tarefas não programadas no desenvolvimento de produtos.


Obviamente, no processo de aprendizado, os alunos constantemente “põem as mãos no laboratório e na lição de casa”. Tomemos algo clássico, por exemplo, a implementação do arquivador no algoritmo de Huffman. Fazer com que “funcione de alguma forma” não é tão difícil. Mas, para fazer uma boa arquitetura do projeto (pelo menos para separar a entrada-saída, a compactação de bits e o próprio algoritmo), use corretamente os recursos do C ++ (regra de três ou cinco, dependendo do semestre) e geralmente projete o código de forma que seja agradável de ler e não seja completamente embaraçoso colocar em código aberto - uma arte separada que os professores ensinam em um curso C ++, comunicando-se constantemente com os alunos e analisando todas as linhas de código em detalhes. Nos assuntos restantes é semelhante. Nenhum curso é limitado a testes teóricos. Em todos os assuntos com código de escrita, haverá uma revisão de código de um programador experiente.


C ++ . O primeiro ano de estudo. Começando com C, terminando com C ++ 14. Mostramos RAII, Valgrind e autotests, aprendemos a escrever bibliotecas (my_vector com garantia de exceções) e aplicativos (o mesmo arquivador). Por que: como o C ++ ainda é usado ativamente no setor, ele também ressoa ativamente com a programação do sistema (falta de coleta de lixo, é possível mostrar o layout dos dados na memória ...).


Sistemas Unix-like . Primeiro semestre. O curso do jovem lutador sobre como trabalhar com a linha de comando e o sistema de arquivos sem C:\ e D:\ . Exemplo de trabalho de teste: no par, a imagem de um Ubuntu instalado ligeiramente quebrado é ouvida, é necessário corrigi-lo. Um exemplo de lição de casa: examine os arquivos em uma pasta no Bash e ligue para alguém útil com expressões regulares.


Paradigmas e linguagens de programação . Primeiro semestre. Uma dúzia de tópicos (pelo menos OOP, programação funcional, SQL, multithreading) e os alunos de cada tópico podem experimentar uma ou duas tarefas de casa. Obviamente, superficialmente, mas ainda dá uma compreensão de quão versátil é a programação e que coisas legais podem ser montadas usando métodos diferentes. OOP, FP e SQL serão então descritos em detalhes, mas já no primeiro ano o aluno sabe sobre sua existência e pode, por exemplo, organizar afirmações no código ou escrever alguns testes de unidade simples, se desejar.


Arquitetura de computadores . Primeiro ano. Registra, um conjunto de algo parecido com o computador, a partir de portas lógicas, caches, um pipeline de processador, representação de números e outras teorias. Motivo: junte informações sobre todos os tipos de coisas de baixo nível em uma única imagem.


Java Segundo ano de estudo. Ele termina com streams e um projeto de curso para Android (por exemplo, jogando um jogo da velha com o modo bot e de rede). Mostramos Maven, IDEA, JUnit, trabalho assíncrono com a rede. Motivo: agora existem muitas coisas girando na JVM, há toneladas de bibliotecas, é bom saber.


Sistemas operacionais . Segundo ano. Hardcore Sem problemas com os gerenciadores de inicialização - os alunos recebem inicialização múltipla na pré-fabricada, transição para o modo protegido e, em seguida, você pode gravar um alocador de memória, threads, processos, sistema de arquivos, particionamento de anel de proteção e até carregamento ELF em C. Talvez não seja tão extenso quanto os "Sistemas Operacionais Modernos" de Tannenbaum, mas você pode ver claramente se é interessante mergulhar nisso ou se deseja permanecer no espaço isolado do usuário. Se estiver interessado, bem-vindo a um curso especial de programação de kernel Linux. A propósito, uma versão muito leve está disponível no Stepik - não existe um SO escrito lá, mas há as tarefas necessárias de teoria e verificação. Para não voar devido ao mau desempenho, basta passar por isso.


Programação funcional . Duas aulas de cálculo lambda e depois foi para Haskell. Terminamos com transformadores de mônadas. Obviamente, tudo é detalhado: uma mônada não é uma caixa, mas apenas uma abstração útil desse modelo para escrever código. Projetos intermediários, no entanto, são mais teóricos do que práticos - escrevem inferência automática de tipo no cálculo lambda. Mas agora a continuação do curso está sendo preparada (como um assunto adicional do programa de mestrado), onde são planejados multithreading e um servidor web. Leia também no Centro de Ciência da Computação .


Bases de dados Nós nos familiarizamos com o DBMS relacional (no exemplo do PostgreSQL), o SQL. Criamos um banco de dados para uma determinada área e, em seguida, organizamos uma revisão de código entre si com base nas orientações do professor. Em seguida, o professor faz uma revisão da revisão de código. Os concursos do formulário "escrevem uma solicitação para este banco de dados". Trabalhos Consultas de criação de perfil simples (EXPLAIN). Mais uma vez, ecoa o curso no Centro de Ciência da Computação .


Engenharia de Software . Ele fala sobre como o trabalho de um programador pode ser organizado, o que todo mundo faz na empresa, por que bons gerentes ainda são úteis e por que o gerenciamento de projetos também é difícil. Qual é o objetivo do planejamento, por que nem sempre funciona, por que nem todos os erros precisam ser corrigidos ... O objetivo é entender o que é necessário para outros projetos que não as pessoas. Obviamente, não é realista divulgar tudo em detalhes em um semestre, mas, por exemplo, é útil saber que após o desenvolvimento do projeto ainda não há apoio menos importante.


Design de software . Todos os tipos de formas de modelar a realidade e (diagramas UML), métodos de decomposição, padrões de design. Como exemplos, no final do curso, entendemos GFS, BigTable, CMake ... Na prática, aprendemos não apenas a escrever código, mas também a descrever a arquitetura e a aplicar modelos onde forem apropriados.


Programação concorrente Começamos com threads simples e mutexes; no final, analisamos e escrevemos algoritmos sem bloqueio / sem espera, penetramos no MESI, estudamos tecnologias de nível superior, como estrutura de junção de forquilhas, OpenMP, OpenCL, Intel TBB.


Tecnologia de rede de computadores . Palestras: uma visão geral detalhada dos principais protocolos da pilha TCP / IP: mensagens no ICMP, uma excursão histórica ao RIP, todos os tipos de registros no DNS, como funciona o FTP / HTTP / SMTP / DHCP, o que é NAT e até um pouco sobre IPv6. Práticas: escrevemos nos benefícios nosso servidor e cliente TCP de plataforma cruzada, primeiro para o messenger de brinquedo e depois para o cliente UDP para DNS.


Design de Interface O aluno não escreve uma única linha de código, mas passa por todas as etapas de criação de uma boa experiência do usuário: ele cria um projeto, realiza pesquisas (incluindo uma pesquisa com pessoas reais), desenvolve e verifica cenários de uso e, no final, você pode desenhar uma interface no Sketch ou Figma . O objetivo é entender que, para um bom produto, você precisa não apenas de código, mas também de vários outros trabalhos preparatórios. A revisão de código não está aqui, mas todos os artefatos intermediários são discutidos ativamente com o professor. Parece-me irrealista passar o dever de casa na primeira tentativa (no entanto, não é obrigatório).


Desenvolvimento móvel . Curso de desenvolvimento avançado para Android. Já estamos escrevendo mais no Kotlin do que em Java, usamos todos os tipos de coisas específicas do Kotlin para o Android. Comparado ao projeto Java do segundo ano, o aplicativo é mais complicado aqui, trabalhamos mais com dependências e bibliotecas externas, pensamos mais sobre a interface e os usuários (aqui o curso tem algo em comum com o design da interface).


Teste de software . Basicamente, há muita teoria que dá nomes a todas as práticas padrão que os alunos provavelmente inventaram em outras disciplinas: teste do fluxo de controle ou fluxo de dados, teste de pares (teste de todos os pares) ... Há também um pouco de prática específica - para elaborar um plano de teste para tal e tal metodologia, para encontrar casos extremos em tal e qual aplicação e executar vários cenários em uma aplicação Web usando o Selenium, para que não seria entediante simplesmente compor casos.


Engenharia de software de big data, também conhecida como engenharia de software de big data. Leia junto com o Computer Science Center . Conectamos bancos de dados, programação paralela, sistemas distribuídos e outras chavões - estas estão em palestras. Na prática, no ano passado, os alunos escreveram sua lista telefônica distribuída do zero. Nos próximos lançamentos, parece correto mudar a ênfase de um nível baixo para as ferramentas realmente usadas na indústria, como Zookeeper, Cassandra e outros animais assustadores. Até agora, a principal dificuldade é como imitar as condições de “big data” para os alunos e avaliar suas soluções: não há necessidade de criar o Zookeeper se não houver uma demonstração clara de que sem ele tudo está muito ruim.


Prática


A segunda parte importante do treinamento é a prática. Desde o primeiro ano, o aluno realiza algumas tarefas praticamente úteis, sob a orientação de um colega experiente. Por exemplo, outro aplicativo para gerenciar um calendário ou notas. Ou nova funcionalidade em um aplicativo existente. Ou estuda a complexidade da computabilidade de uma família de fórmulas se for levada na direção da Ciência da Computação.


Nos primeiros cursos, não exigimos novidade ou praticidade (afinal, o objetivo é dar um pouco de brincadeira), mas os requisitos de diploma para a qualidade dos projetos e a proteção estão aumentando. Nos últimos cursos, além da pergunta "o que foi feito?" é importante que os alunos digam por que isso foi feito e por quê. Ao mesmo tempo, "eu realmente quero essa empresa em particular, na qual meu supervisor de pesquisa trabalha", por si só não é a resposta. Mas "lá, os discos rígidos morrem a cada segundo, então esse código aberto não funciona, este artigo é puramente teórico, mas o Google tem uma solução, mas está fechada" - é isso. Ele não funcionará como um diploma para proteger um exercício desnecessário a partir do segundo ano - desenvolvedores curiosos com laptops e Google estão prontos para defender (e algumas pré-defesas). "Ninguém fez isso ainda" - praticamente a coisa mais perigosa que se pode dizer. A propósito, defendemos não apenas diplomas, mas também práticas regularmente desde o primeiro ano.


Aqui estão algumas fotos com proteção típica. Fotógrafo: Dima Drozdov.




As práticas permitem que você aprenda a trabalhar "em longo prazo" em projetos grandes, às vezes parcialmente escritos por outros desenvolvedores. Nem sempre é possível adivinhar o tema do projeto: por exemplo, depois de tentar um desenvolvimento de baixo nível, um aluno pode decidir se envolver no futuro. Este é o significado da prática: entender o que você gosta e o que não, não no trabalho, mas em condições com taxas mais baixas. Embora a última prática deva se transformar em um diploma de bacharel substancial. "Substantivo" é quando, de acordo com o diploma, você pode pelo menos escrever um artigo sobre Habr e não fazer menos. Ou, se o trabalho for muito bom, publique em uma revista científica, fale em uma conferência ou, pelo menos, colete as vantagens.


Itens eletivos


A terceira parte, mas também importante, é de itens adicionais. Os temas são específicos, provavelmente não são necessários para todos, mas os alunos interessados ​​podem prová-los. Nos cursos seniores, há a maioria dessas disciplinas: existe uma base, resta ampliar nossos horizontes em uma direção interessante para o aluno. Infelizmente, não há tempo suficiente para levar todos os itens. Às vezes, o conjunto de cursos muda, eis os que me foram oferecidos:


Idiomas alternativos para a JVM . Um curso de dois módulos: um fala sobre Kotlin e outro sobre Scala. Para o Kotlin, analisamos a interoperabilidade Java e escrevemos nosso próprio DSL e corotinas. A última lição de casa opcional é adicionar um depurador usando corutin ao interpretador de linguagem de brinquedos (escrito na lição de casa anterior). Quanto ao Scala ... A linguagem é grande, mas temos tempo para entender todos os tipos de implicitamente :)


Programação no kernel do Linux . Passo a passo, está sendo desenvolvido um módulo do kernel que emula um dispositivo de armazenamento virtual: mmap, buffers, acesso simultâneo, E / S sem bloqueio. No caminho, você pode se lembrar de interrupções e excluir multitarefa do curso de sistemas operacionais e estudar as estruturas internas do Linux (por exemplo, fila de espera).


Compiladores Estamos escrevendo nosso compilador de micro-linguagem no OCaml. Uma máquina de pilha intermediária, compilação em x86 sem nenhum LLVM, integração com libc. Exclamações surpresas dos estudantes "por que isso se aplica apenas à expressão de cem?" (provavelmente porque o erro está na alocação do registro). A propósito, um curso semelhante também está disponível no Centro de Ciência da Computação .


Computação gráfica . Curso de nível relativamente baixo: estudamos o OpenGL, escrevemos nossos shaders para sombras e renderização diferida, comparamos a mistura de cores com e sem correção de gama.


Construindo um DBMS . Banco de dados interno do dispositivo. Todos os tipos de algoritmos de conexão, modelos formais, DBMS da coluna. Na prática, você pode implementar vários algoritmos de processamento bloco a bloco em um DBMS de brinquedo com vantagens (por exemplo, junção de hash com pipeline duplamente canalizado).


Virtualização de contêiner . Um estudo detalhado de contêineres no Linux. Namespaces e cgroups, digamos - e a API, e como ela funciona. Todos os tipos de ferramentas auxiliares para a rede. No processo, escrevemos nosso contêiner como o Docker, mas não é tão simples - você precisa limitar corretamente tudo, configurar a rede, encaminhar os arquivos necessários para o contêiner ... No entanto, a orquestração de alto nível usando o Kubernetes como exemplo também é considerada.


O que queremos melhorar


Nós e nossos alunos provavelmente estamos satisfeitos com o programa resultante (a julgar pelas pesquisas). No entanto, você pode fazer ainda melhor, não apenas melhorando os itens existentes, mas também adicionando novos.


Por exemplo, ainda não está claro como transferir certos aspectos da "experiência de trabalho" para a universidade. O mesmo trabalho com o código legado - útil? E então Existem até livros e técnicas específicas. Mas, para fazer um bom curso disso, vários fatores devem ser combinados:


  1. Não distraia os professores de seu trabalho principal por um longo tempo, para que eles constantemente ajudem os alunos a entender um grande projeto. E se houver boa documentação - então isso não é mais tão legado.
  2. Os alunos devem estar interessados. "Adicione mil linhas de código a um projeto que você não precisa" não está incluído.
  3. O resultado deve ser previsível. "Parece que esta é uma tarefa insolúvel, desculpe, eles não pensaram" - más notícias de acordo com os resultados da verificação da lição de casa.

Infelizmente, ainda não descobrimos como fazer isso. O mais próximo é o aprendizado de máquina, onde são realizados seminários toda semana, onde os alunos fazem apresentações sobre alguns dos artigos mais recentes. Talvez essa experiência possa ser transferida para programação industrial.


Talvez as únicas áreas que atualmente não são cobertas sejam o desenvolvimento web (incluindo o front-end), sistemas complexos de automação (como 1C ou SAP) e segurança de computadores (um curso experimental iniciado no início de fevereiro de 2019). Podemos ter esquecido outra coisa, ou você sabe como pode ensinar a programar ainda melhor - teremos o maior prazer em discutir nos comentários.


No entanto, acreditamos que os graduados que estão prontos para trabalhar e que, se necessário, precisam ser especialmente ensinados, talvez os sistemas internos da empresa já estejam deixando o bacharelado. A propósito, um tópico separado no qual estamos pensando e tentando implementar é o que, após um conjunto tão restrito de cursos, estudar em um programa de mestrado, mas esse é um tópico para um post separado.

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


All Articles