ti-enxame.com

Eu herdei 200 mil linhas de código espaguete - e agora?

Espero que isso não seja uma pergunta muito geral; Eu realmente poderia usar alguns conselhos experientes.

Sou recém-contratado como o único "Engenheiro de SW" em uma pequena loja de cientistas que passaram os últimos 10 a 20 anos reunindo uma vasta base de códigos. (Foi escrito em uma linguagem praticamente obsoleta: G2 - pense Pascal com gráficos). O programa em si é um modelo físico de uma planta de processamento químico complexo; a equipe que o escreveu possui um conhecimento de domínio incrivelmente profundo, mas pouco ou nenhum treinamento formal em fundamentos de programação. Recentemente, eles aprenderam algumas lições difíceis sobre as consequências do gerenciamento de configurações inexistentes. Seus esforços de manutenção também são bastante prejudicados pelo grande acúmulo de "lodo" não documentado no próprio código. Vou poupar-lhe a "política" da situação (há sempre política!), Mas basta dizer que não há um consenso de opinião sobre o que é necessário para o caminho a seguir.

Eles me pediram para começar a apresentar à equipe alguns dos princípios do desenvolvimento moderno de software. Eles querem que eu apresente algumas das práticas e estratégias padrão do setor em relação às convenções de codificação, gerenciamento do ciclo de vida, padrões de design de alto nível e controle de origem. Francamente, é uma tarefa bastante assustadora e não sei por onde começar.

Inicialmente, estou inclinado a ensiná-los em alguns dos conceitos centrais de O Programador Pragmático , ou de Fowler Refatoração ("Código cheira", etc). Também espero introduzir várias metodologias ágeis. Mas, finalmente, para ser eficaz, acho que vou precisar aprimorar os 5-7 princípios básicos; em outras palavras, quais são os princípios ou práticas mais importantes que eles podem começar a implementar realisticamente e que darão a eles o maior retorno possível.

Portanto, essa é a minha pergunta: o que você incluiria em sua lista das estratégias mais eficazes para ajudar a endireitar o espaguete (e evitá-lo no futuro)?

468
kmote

Prefácio

Esta é realmente uma tarefa assustadora, e há muito o que abordar. Portanto, estou humildemente sugerindo isso como um guia abrangente para sua equipe, com dicas para ferramentas e material educacional apropriados.

Lembre-se: Estas são diretrizes e que, como tal, devem ser adotados, adaptados ou descartados com base nas circunstâncias.

Cuidado: Despejar tudo isso em uma equipe ao mesmo tempo provavelmente falhará. Você deve tentar escolher elementos que dariam o melhor retorno possível e apresentá-los lentamente, um de cada vez.

Nota: nem tudo isso se aplica diretamente a sistemas de programação visual como o G2. Para obter detalhes mais específicos sobre como lidar com eles, consulte a seção Adendo no final.


Resumo Executivo para o Impaciente

  • Defina uma estrutura rígida do projeto , com:
    • modelos de projeto ,
    • convenções de codificação ,
    • sistemas familiares de construção ,
    • e conjuntos de diretrizes de uso para sua infraestrutura e ferramentas.
  • Instale um bom [~ # ~] scm [~ # ~] e verifique se eles sabem como usá-lo.
  • Aponte-os para bons IDEs para sua tecnologia e verifique se eles sabem como usá-los.
  • Implemente verificadores de qualidade de código e relatórios automáticos no sistema de construção.
  • Acople o sistema de construção a integração contínua e sistemas de inspeção contínua .
  • Com a ajuda do acima, identifique código de qualidade "hotspots" e refator .

Agora, para a versão longa ... Cuidado, preparem-se!


A rigidez é (geralmente) boa

Esta é uma opinião controversa, pois a rigidez é frequentemente vista como uma força trabalhando contra você. É verdade para algumas fases de alguns projetos. Mas uma vez que você o vê como um suporte estrutural, uma estrutura que elimina as suposições, reduz bastante a quantidade de tempo e esforço desperdiçados. Faça com que funcione para você, não contra você.

Rigidez = Processo / Procedimento .

O desenvolvimento de software precisa de bons processos e procedimentos pelas mesmas razões pelas quais as fábricas ou fábricas de produtos químicos possuem manuais, procedimentos, exercícios e diretrizes de emergência: prevenção de maus resultados, aumento da previsibilidade, maximização da produtividade ...

Embora a rigidez seja moderada!

Rigidez da estrutura do projeto

Se cada projeto vem com sua própria estrutura, você (e os novatos) estão perdidos e precisam começar do zero toda vez que os abrir. Você não quer isso em uma loja de software profissional e também não quer isso em um laboratório.

Rigidez dos sistemas de construção

Se cada projeto parecer diferente, há uma boa chance de que eles também sejam construídos de forma diferente . Uma construção não deve exigir muita pesquisa ou muita adivinhação. Você quer fazer a coisa canônica e não precisa se preocupar com detalhes: configure; make install, ant, mvn install, etc ...

A reutilização do mesmo sistema de construção e a sua evolução ao longo do tempo também garantem um nível consistente de qualidade.

Você precisa de um README rápido para apontar as especificidades do projeto e orientar graciosamente o usuário/desenvolvedor/pesquisador, se houver.

Isso também facilita muito outras partes da sua infraestrutura de construção, a saber:

Portanto, mantenha sua construção (como seus projetos) atualizada, mas torne-a mais rígida ao longo do tempo e mais eficiente na denúncia de violações e práticas inadequadas.

Não reinvente a roda e reutilize o que você já fez.

Leitura recomendada:

Rigidez na escolha das linguagens de programação

Você não pode esperar, especialmente em um ambiente de pesquisa, que todas as equipes (e menos ainda todos os desenvolvedores) usem a mesma pilha de linguagem e tecnologia. No entanto, você pode identificar um conjunto de ferramentas "oficialmente suportadas" e incentivar o uso delas. O resto, sem uma boa justificativa, não deve ser permitido (além da prototipagem).

Mantenha sua pilha de tecnologia simples e a manutenção e a amplitude das habilidades necessárias ao mínimo: um núcleo forte.

Rigidez das convenções e diretrizes de codificação

As convenções e diretrizes de codificação são o que permitem que você desenvolva uma identidade como equipe e um jargão compartilhado . Você não deseja errar terra incognita toda vez que abrir um arquivo de origem.

Regras absurdas que tornam a vida mais difícil ou proíbem ações explicitamente, na medida em que os commits são recusados ​​com base em violações simples e simples, são um fardo. Contudo:

  • um conjunto de regras básicas bem pensado elimina grande parte dos gemidos e pensamentos: ninguém deve quebrar sob nenhuma circunstância;

  • e um conjunto de regras recomendadas fornece orientações adicionais.

Abordagem pessoal: Sou agressivo quando se trata de convenções de codificação, alguns até dizem nazi , porque eu acredito em ter uma lingua franca , um estilo reconhecível para minha equipe. Quando o código de porcaria é verificado, ele se destaca como uma afta na face de uma estrela de Hollywood: desencadeia uma revisão e uma ação automaticamente. De fato, às vezes fui longe em defender o uso de ganchos pré-confirmação para rejeitar confirmações não conformes. Como mencionado, não deve ser muito louco e atrapalhar a produtividade: deve impulsioná-lo. Apresente-os lentamente, especialmente no começo. Mas é preferível gastar tanto tempo corrigindo códigos defeituosos que você não pode trabalhar em problemas reais.

Alguns idiomas ainda impõem isso por design:

  • O Java foi criado para reduzir a quantidade de porcaria que você pode escrever com ele (embora sem dúvida muitos consigam fazê-lo).
  • A estrutura de blocos do Python por indentação é outra idéia nesse sentido.

  • Vá, com sua ferramenta gofmt, que tira completamente qualquer debate e esforço ( e ego !! ) inerentes ao estilo: run gofmt antes de você confirmar.

Certifique-se de que a podridão do código não pode passar despercebida. Convenções de código , integração contínua e inspeção contínua , programação de pares e análises de código é o seu arsenal contra esse demônio.

Além disso, como você verá abaixo, o código é a documentação , e essa é outra área em que as convenções incentivam a legibilidade e a clareza.

Rigidez da documentação

A documentação anda de mãos dadas com o código. O próprio código é documentação. Mas deve haver instruções claras sobre como construir, usar e manter as coisas.

Usar um único ponto de controle para documentação (como um WikiWiki ou DMS) é uma coisa boa. Crie espaços para projetos, espaços para brincadeiras e experiências mais aleatórias. Todos os espaços reutilizam regras e convenções comuns. Tente fazer parte do espírito de equipe.

A maioria dos conselhos aplicáveis ​​ao código e às ferramentas também se aplica à documentação.

Rigidez nos comentários do código

Comentários de código, como mencionado acima, também são documentação. Os desenvolvedores gostam de expressar seus sentimentos sobre o código (principalmente orgulho e frustração, se você me perguntar). Portanto, não é incomum que eles os expressem em termos inequívocos nos comentários (ou mesmo no código), quando um pedaço de texto mais formal poderia ter transmitido o mesmo significado com menos palavrões ou drama. Não há problema em deixar passar alguns por motivos divertidos e históricos: também faz parte do desenvolvimento de uma cultura de equipe . Mas é muito importante que todos saibam o que é aceitável e o que não é, e esse ruído de comentário é apenas isso: ruído .

Rigidez nos logs de consolidação

Os registros de confirmação não são uma "etapa" irritante e inútil do ciclo de vida do seu SCM: você não o pula para chegar em casa a tempo ou prosseguir com a próxima tarefa, ou para conversar com os amigos que foram almoçar. Eles são importantes e, como (a maioria) bom vinho, quanto mais o tempo passa, mais valiosos eles se tornam. Então faça-os direito. Fico espantado quando vejo colegas de trabalho escrevendo frases de efeito para commits gigantes ou para hacks não óbvios.

As confirmações são feitas por um motivo, e esse motivo nem sempre é expresso claramente pelo seu código e pela única linha do log de confirmação que você inseriu. Há mais do que isso.

Cada linha de código tem uma história e uma história Os diffs podem contar sua história, mas você deve escrever sua história.

Por que atualizei esta linha? -> Porque a interface mudou.

Por que a interface mudou? -> Como a biblioteca L1 que o definiu foi atualizada.

Por que a biblioteca foi atualizada? -> Como a biblioteca L2, necessária para o recurso F, dependia da biblioteca L1.

E qual é o recurso X? -> Ver tarefa 3456 no rastreador de problemas.

Não é minha escolha de SCM e também pode não ser a melhor para o seu laboratório; mas Git acerta isso e tenta forçá-lo a escrever bons logs mais do que a maioria dos outros sistemas SCMs, usando short logs e long logs. Vincule o ID da tarefa (sim, você precisa de um) e deixe um resumo genérico para o shortlog e expanda no log longo: escreva a história do changeset .

É um log: Está aqui para acompanhar e registrar as atualizações.

Regra geral: Se você procurou algo sobre essa alteração posteriormente, é provável que seu registro responda à sua pergunta?

Projetos, documentação e código estão vivos

Mantenha-os sincronizados, caso contrário eles não formarão mais essa entidade simbiótica. Faz maravilhas quando você tem:

  • clear confirma registros no seu SCM, com links para IDs de tarefas no rastreador de problemas,
  • onde os tickets desse rastreador estão vinculados aos conjuntos de alterações no seu SCM (e possivelmente às compilações no seu sistema de IC),
  • e um sistema de documentação vinculado a todos eles.

O código e a documentação precisam ser coesos .

Rigidez nos testes

Regras de ouro:

  • Qualquer novo código deve vir com (pelo menos) testes de unidade.
  • Qualquer código legado refatorado deve vir com testes de unidade.

Obviamente, eles precisam:

  • para testar algo valioso (ou é um desperdício de tempo e energia),
  • para ser bem escrito e comentado (como qualquer outro código que você faz check-in).

Eles também são documentação e ajudam a delinear o contrato do seu código. Especialmente se você usar TDD . Mesmo se não, você precisa deles para sua paz de espírito. Eles são sua rede de segurança quando você incorpora um novo código (manutenção ou recurso) e sua torre de vigia para se proteger contra a podridão do código e falhas ambientais.

Obviamente, você deve ir além e ter testes de integração e testes de regressão para cada bug reproduzível corrigido.

Rigidez no uso das ferramentas

Não há problema em um desenvolvedor/cientista ocasional querer experimentar algum novo verificador estático na fonte, gerar um gráfico ou modelo usando outro ou implementar um novo módulo usando uma DSL. Mas é melhor se houver um conjunto canônico de ferramentas que todos os membros da equipe devem conhecer e usar.

Além disso, permita que os membros usem o que querem, desde que sejam TODOS:

  • produtivo ,
  • NÃO requer assistência regularmente
  • NÃO se ajusta regularmente à sua infraestrutura geral ,
  • NÃO interrompe sua infraestrutura (modificando áreas comuns como código, sistema de compilação, documentação ...),
  • NÃO afeta o trabalho de outras pessoas ,
  • CAPAZ de executar oportuna qualquer tarefa solicitada .

Se não for esse o caso, imponha que eles retornem aos padrões.


Rigidez vs Versatilidade, Adaptabilidade, Prototipagem e Emergências

Flexibilidade pode ser boa. Permitir que alguém ocasionalmente use um hack, uma abordagem rápida e suja ou uma ferramenta favorita para fazer o trabalho é bom. [~ # ~] nunca [~ # ~] deixe que se torne um hábito e [~ # ~] nunca [~ # ~] deixe esse código se tornar a base de código real para suportar.


Questões de espírito de equipe

Desenvolva um senso de orgulho em sua base de código

  • Desenvolva um senso de orgulho no Código

Evite Jogos de Culpa

  • NÃO use jogos de Integração Contínua/Inspeção Contínua: promove boas maneiras e competição produtiva .
  • NÃO acompanhe os defeitos: é apenas uma boa manutenção da casa.
  • DO identificando causas-raiz : são apenas processos à prova de futuro.
  • MAS NÃO atribuir culpa : é contraproducente.

É sobre o código, não sobre os desenvolvedores

Torne os desenvolvedores conscientes da qualidade de seu código, MAS faça com que eles vejam o código como uma entidade independente e não como uma extensão de si mesmos, que não pode ser criticada.

É um paradoxo: você precisa incentivar programação sem ego para um ambiente de trabalho saudável, mas confiar no ego para fins motivacionais.


De cientista a programador

Pessoas que não valorizam e se orgulham do código não produzem um bom código. Para que essa propriedade surja, eles precisam descobrir o quão valioso e divertido pode ser. Simples profissionalismo e desejo de fazer o bem não são suficientes: é preciso paixão. Então você precisa transformar seus cientistas em programadores (no sentido amplo).

Alguém argumentou nos comentários que, após 10 a 20 anos em um projeto e seu código, qualquer um se sentiria apegado. Talvez eu esteja errado, mas suponho que tenham orgulho dos resultados do código e do trabalho e seu legado, não do código em si ou do ato de escrevê-lo.

Por experiência, a maioria dos pesquisadores considera a codificação uma necessidade ou, na melhor das hipóteses, uma distração divertida. Eles só querem que funcione. Aqueles que já são bastante versados ​​e têm interesse em programação são muito mais fáceis de persuadir a adotar as melhores práticas e a alternar tecnologias. Você precisa levá-los até a metade do caminho.


Manutenção de código faz parte do trabalho de pesquisa

Ninguém lê documentos de pesquisa ruins. É por isso que eles são revisados ​​por pares, revisados, refinados, reescritos e aprovados uma e outra vez até que estejam prontos para publicação. O mesmo se aplica a uma tese e a uma base de código!

Deixe claro que a constante refatoração e atualização de uma base de código evita a podridão do código e reduz a dívida técnica, além de facilitar a reutilização e adaptação futuras do trabalho para outros projetos.


Por que tudo isso??!

Por que nos preocupamos com tudo isso? Para qualidade do código . Ou é código de qualidade ...?

Essas diretrizes visam direcionar sua equipe para esse objetivo. Alguns aspectos fazem isso simplesmente mostrando-lhes o caminho e deixando-os fazer (o que é muito melhor) e outros os pegam pela mão (mas é assim que você educa as pessoas e desenvolve hábitos).

Como você sabe quando a meta está ao seu alcance?

Qualidade é Mensurável

Nem sempre é quantitativamente, mas é mensurável . Como mencionado, você precisa desenvolver um senso de orgulho em sua equipe, e mostrar progresso e bons resultados é essencial. Avalie a qualidade do código regularmente e mostre o progresso entre os intervalos e como isso é importante. Faça retrospectivas para refletir sobre o que foi feito e como isso tornou as coisas melhores ou piores.

Existem ótimas ferramentas para inspeção contínua . Sonar sendo popular no mundo Java, mas pode se adaptar a qualquer tecnologia; e há muitas outras. Mantenha seu código sob o microscópio e procure-os insetos e micróbios irritantes irritantes.


Mas e se meu código já for uma porcaria?

Todas as opções acima são divertidas e fofas como uma viagem a Never Land, mas não é tão fácil de fazer quando você já tem um monte de porcaria (fumegante e fedorento) e uma equipe relutante em mudar.

Aqui está o segredo: você precisa começar em algum lugar .

Anedota pessoal: Em um projeto, trabalhamos com uma base de código que pesava originalmente 650.000+ Java LOC, mais de 200.000 linhas de JSPs, mais de 40.000 JavaScript LOC e mais de 400 MBs de dependências binárias.

Após cerca de 18 meses, são 500.000 Java LOC (MAIS LIMPO) , 150.000 linhas de JSPs e 38.000 JavaScript LOC , com dependências de até 100 MB (e elas não estão mais no nosso SCM!).

Como fizemos? Acabamos de fazer todas as opções acima. Ou tentou arduamente.

É um esforço de equipe, mas lentamente injetamos em nossos regulamentos e ferramentas de processo para monitorar a freqüência cardíaca de nosso produto, enquanto apressadamente cortando a "gordura": código de porcaria, dependências inúteis ... Não paramos todo o desenvolvimento para fazer isso: temos períodos ocasionais de relativa paz e sossego, onde são livres para enlouquecer na base de código e desmembrá-la, mas na maioria das vezes fazemos tudo por padrão para um modo de "revisão e refatoração" a cada chance que temos: durante construções, durante o almoço, durante corridas de erros, durante sexta-feira tardes ...

Houve alguns "trabalhos" grandes ... Mudar nosso sistema de compilação de uma compilação Ant gigante de 8500+ XML LOC para uma compilação Maven com vários módulos foi um deles. Tivemos então:

  • módulos claros (ou pelo menos já era muito melhor e ainda temos grandes planos para o futuro),
  • gerenciamento automático de dependências (para manutenção e atualizações fáceis e remoção de depósitos inúteis),
  • construções mais rápidas, fáceis e reproduzíveis,
  • relatórios diários de qualidade.

Outra foi a injeção de "cintos de ferramentas utilitárias", embora tentássemos reduzir as dependências: o Google Guava e o Apache Commons diminuem o seu código e reduzem a superfície para erros no seu código muito.

Também convencemos nosso departamento de TI de que talvez o uso de nossas novas ferramentas (JIRA, Fisheye, Crisol, Confluence, Jenkins) fosse melhor do que as existentes. Ainda precisamos lidar com alguns que desprezamos (QC, Sharepoint e SupportWorks ...), mas foi uma experiência geral aprimorada, com um pouco mais de espaço.

E todos os dias, agora há uma quantidade entre uma e dezenas de confirmações que lidam apenas com a correção e refatoração de coisas. Ocasionalmente, quebramos coisas (você precisa de testes de unidade e é melhor escrevê-las antes de refatorar as coisas), mas no geral o benefício para o nosso moral E para o produto tem sido enorme. Chegamos lá uma fração de uma porcentagem de qualidade de código por vez. E é divertido vê-lo aumentar !!!

Nota: Novamente, a rigidez precisa ser abalada para abrir espaço para coisas novas e melhores. Na minha anedota, nosso departamento de TI está parcialmente certo ao tentar impor algumas coisas sobre nós e errado para outras. Ou talvez eles estivessem certos . As coisas mudam. Prove que são as melhores maneiras de aumentar sua produtividade. Execuções de avaliação e protótipos estão aqui para isso.


O ciclo de refatoração de código de espaguete incremental super secreto para uma qualidade incrível

       +-----------------+      +-----------------+
       |  A N A L Y Z E  +----->| I D E N T I F Y |
       +-----------------+      +---------+-------+
                ^                           |
                |                           v
       +--------+--------+      +-----------------+
       |    C L E A N    +<-----|      F I X      |
       +-----------------+      +-----------------+

Depois de ter algumas ferramentas de qualidade no seu cinto de ferramentas:

  1. Analise seu código com verificadores de qualidade de código.

    Linters, analisadores estáticos ou o que você tem.

  2. Identifique seus pontos críticos hotspots AND frutas penduradas baixas .

    As violações têm níveis de severidade, e grandes classes com um grande número de severidades são uma grande bandeira vermelha: assim, elas aparecem como "pontos de acesso" nos tipos de visualizações do radiador/mapa de calor.

  3. Corrija os pontos de acesso primeiro.

    Maximiza seu impacto em um curto espaço de tempo, pois eles têm o maior valor comercial. Idealmente, as violações críticas devem ser tratadas assim que aparecerem, pois são possíveis vulnerabilidades de segurança ou causas de travamento e apresentam um alto risco de induzir uma responsabilidade (e, no seu caso, mau desempenho para o laboratório).

  4. Limpe as violações de baixo nível com varreduras automatizadas de base de código .

    Ele melhora a relação sinal-ruído para que você possa ver violações significativas no seu radar à medida que aparecem. Geralmente, há um grande exército de pequenas violações no início, se elas nunca foram resolvidas e sua base de código foi deixada solta na natureza. Eles não apresentam um "risco" real, mas prejudicam a legibilidade e a manutenção do código. Corrija-os conforme você os encontra durante o trabalho em uma tarefa ou em grandes tarefas de limpeza com varreduras de código automatizadas, se possível. Tenha cuidado com grandes varreduras automáticas, se você não tiver um bom conjunto de testes e sistema de integração. Certifique-se de concordar com os colegas de trabalho o momento certo para executá-los para minimizar o aborrecimento.

  5. Repita até ficar satisfeito.

    O que, idealmente, você nunca deveria ser, se este ainda for um produto ativo: continuará evoluindo.

Dicas rápidas para uma boa manutenção da casa

  • Quando no modo de hotfix , com base em uma solicitação de suporte ao cliente:

    • Geralmente, é uma prática recomendada [~ # ~] não [~ # ~] resolver outros problemas, pois você pode apresentar novos sem querer.
    • Vá até lá no estilo SEAL: entre, mate o bug, saia e envie seu patch. É uma greve cirúrgica e tática.
  • Mas, para todos os outros casos , se você abrir um arquivo, tenha o dever de:

    • definitivamente: analise (faça anotações, envie relatórios de problemas),
    • talvez: limpe (limpeza de estilo e pequenas violações),
    • idealmente: refatorar (reorganizar grandes seções e seus vizinhos).

Apenas não se desvie para passar uma semana de um arquivo para outro e acabar com um maciço conjunto de milhares de correções, abrangendo vários recursos e módulos - isso dificulta o rastreamento futuro. Um problema no código = um ticket no seu rastreador. Às vezes, um conjunto de alterações pode afetar vários tickets; mas se isso acontecer com muita frequência, provavelmente você está fazendo algo errado.


Adendo: Gerenciando ambientes de programação visual

Os jardins murados dos sistemas de programação sob medida

Vários sistemas de programação, como o G2 do OP, são bestas diferentes ...

  • "Código" sem fonte

    Freqüentemente, eles não dão acesso a uma representação textual do seu "código" fonte: ele pode ser armazenado em um formato binário proprietário ou talvez ele armazene coisas no formato de texto, mas as oculta. Sistemas de programação gráfica sob medida não são incomuns em laboratórios de pesquisa, pois simplificam a automação de fluxos de trabalho repetitivos de processamento de dados.

  • Sem ferramentas

    Além de seus próprios, é isso. Você geralmente é limitado pelo ambiente de programação, pelo depurador, pelo intérprete, pelas ferramentas e formatos de documentação. Eles são jardins murados , exceto se eventualmente capturarem o interesse de alguém motivado o suficiente para fazer engenharia reversa de seus formatos e criar ferramentas externas - se a licença permitir.

  • Falta de documentação

    Muitas vezes, esses são sistemas de programação de nicho, usados ​​em ambientes bastante fechados. As pessoas que os usam frequentemente assinam NDAs e nunca falam sobre o que fazem. As comunidades de programação para eles são raras. Portanto, os recursos são escassos. Você está preso à sua referência oficial, e é isso.

A parte irônica (e muitas vezes frustrante) é que todas as coisas que esses sistemas fazem poderiam obviamente ser alcançadas usando linguagens de programação de uso geral e geral, e provavelmente muito mais eficientemente. Mas isso requer um conhecimento mais profundo da programação, enquanto você não pode esperar que seu biólogo, químico ou físico (para citar alguns) saiba o suficiente sobre programação e muito menos tenha tempo (e desejo) para implementar (e manter) sistemas complexos, que podem ou não durar muito. Pela mesma razão que usamos DSLs, temos esses sistemas de programação sob medida.

Anedota pessoal 2: Na verdade, eu mesmo trabalhei em uma delas. Eu não fiz o link com a solicitação do OP, mas o meu projeto era um conjunto de grandes partes interconectadas de software de processamento e armazenamento de dados (principalmente para pesquisa em bioinformática, saúde e cosméticos, mas também para negócios inteligência ou qualquer domínio que implique no rastreamento de grandes volumes de dados de pesquisa de qualquer tipo e na preparação de fluxos de trabalho de processamento de dados e ETLs). Um desses aplicativos era, simplesmente, um visual IDE que usava os sinos e os assobios usuais: interfaces de arrastar e soltar, espaços de trabalho de projeto com versão (usando arquivos de texto e XML para armazenamento de metadados)); drivers conectáveis ​​a fontes de dados heterogêneas e uma tela visual para projetar pipelines para processar dados de fontes de dados N e, no final, gerar saídas M transformadas e possíveis visualizações brilhantes e relatórios on-line complexos (e interativos). um pouco da síndrome do NIH sob o pretexto de projetar um sistema adaptado às necessidades dos usuários.

E, como você esperaria, é um sistema agradável, bastante flexível para suas necessidades, embora às vezes um pouco exagerado, para que você se pergunte "por que não usar ferramentas de linha de comando?" E, infelizmente, sempre liderando empresas de médio porte equipes trabalhando em grandes projetos para muitas pessoas diferentes, usando-o com diferentes "melhores" práticas.

Ótimo, estamos condenados! - O que fazemos sobre isso?

Bem, no final, todas as opções acima ainda são válidas. Se você não conseguir extrair a maior parte da programação deste sistema para usar mais ferramentas e linguagens convencionais, "apenas" precisará adaptá-lo às restrições do seu sistema.

Sobre controle de versão e armazenamento

No final, você quase sempre pode versão coisas, mesmo com o ambiente mais restrito e murado. Na maioria das vezes, esses sistemas ainda vêm com suas próprias versões (o que, infelizmente, é bastante básico, e oferece apenas reverter para versões anteriores sem muita visibilidade, mantendo apenas os instantâneos anteriores). Não é exatamente o uso de conjuntos de alterações diferenciais como o seu SCM de escolha, e provavelmente não é adequado para vários usuários que enviam alterações simultaneamente.

Mas, ainda assim, se eles fornecem essa funcionalidade, talvez a sua solução seja seguir nossas amadas diretrizes padrão do setor acima e transpor essas para este sistema de programação !!

Se o sistema de armazenamento for um banco de dados, provavelmente expõe as funcionalidades de exportação ou pode ser feito backup no nível do sistema de arquivos. Se estiver usando um formato binário personalizado, talvez você possa simplesmente tentar fazer a versão com um VCS que tenha um bom suporte para dados binários. Você não terá controle refinado, mas pelo menos terá as costas protegidas contra catástrofes e terá um certo grau de conformidade com a recuperação de desastres.

Sobre o teste

Implemente seus testes na própria plataforma e use ferramentas externas e tarefas em segundo plano para configurar backups regulares. Provavelmente, você inicia esses testes da mesma maneira que iniciaria os programas desenvolvidos com esse sistema de programação.

Claro, é um trabalho de hacker e definitivamente não está de acordo com o que é comum na programação "normal", mas a idéia é se adaptar ao sistema enquanto tenta manter uma aparência de processo profissional de desenvolvimento de software.

A estrada é longa e íngreme ...

Como sempre em ambientes de nicho e sistemas de programação sob medida, e conforme exposto acima, você lida com formatos estranhos, apenas um conjunto limitado (ou totalmente inexistente) de ferramentas possivelmente desajeitadas e um vazio no lugar de uma comunidade.

A recomendação: Tente implementar as diretrizes acima fora do seu sistema de programação sob medida, o máximo possível. Isso garante que você possa confiar em ferramentas "comuns", que possuem suporte adequado e motivação da comunidade.

A solução alternativa: Quando isso não for uma opção, tente adaptar essa estrutura global à sua "caixa". A idéia é sobrepor esse modelo de boas práticas padrão do setor sobre o sistema de programação e tirar o melhor proveito dele. O conselho ainda se aplica: defina a estrutura e as melhores práticas, incentive a conformidade.

Infelizmente, isso implica que você pode precisar mergulhar e fazer uma tremenda quantidade de trabalho nas pernas. Assim...

Últimas palavras famosas e pedidos humildes:

  • Documente tudo o que você faz.
  • Compartilhe sua experiência.
  • Código aberto qualquer ferramenta que você escrever.

Ao fazer tudo isso, você irá:

  • não apenas aumenta suas chances de obter apoio de pessoas em situações semelhantes,
  • mas também forneça ajuda a outras pessoas e promova discussões em torno de sua pilha de tecnologia.

Quem sabe, você poderia estar no início de uma nova comunidade vibrante de linguagem obscura X . Se não houver, inicie um!

Talvez seja bonito por dentro , mas ninguém tem idéia até agora, tão ajuda derrube esta parede feia e deixe que outras pessoas dêem uma espiada!

464
haylem

O primeiro primeiro passo seria a introdução de um sistema de controle de versão (SVN , Git, Mercurial, TFS, etc.). Isso é necessário para um projeto que terá re-fatoração.

Edit: referente ao VSC - Todo pacote de controle de origem pode gerenciar binários, embora com algumas limitações. A maioria das ferramentas do mercado tem a capacidade de usar um visualizador e editor de diferença personalizado, use esse recurso. Arquivos de origem binários não são uma desculpa para não usar o controle de versão.

Existe uma publicação semelhante sobre como lidar com código legado , pode ser uma boa referência a seguir - Conselho sobre como trabalhar com código legado

101
Yusubov

Quando tenho que trabalhar com código espaguete, a primeira coisa em que trabalho é modularização . Encontre lugares onde você pode desenhar linhas e extrair (mais ou menos) partes independentes da base de código. Eles provavelmente não serão muito pequenos, devido a um alto grau de interconectividade e acoplamento, mas algumas linhas de módulos surgirão se você procurá-las.

Depois de ter os módulos, você não fica mais com a difícil tarefa de limpar todo um programa bagunçado. Agora, em vez disso, você tem vários módulos desarrumados independentes menores para limpar. Agora escolha um módulo e repita em uma escala menor. Encontre lugares onde você pode extrair grandes funções em funções menores ou mesmo em classes (se o G2 as suportar).

Tudo isso é muito mais fácil se o idioma tiver um sistema de tipos suficientemente forte, porque você pode fazer com que o compilador faça muito trabalho pesado para você. Você faz uma alteração em algum lugar que (intencionalmente) quebra a compatibilidade e tenta compilar. Os erros de compilação levarão você diretamente aos locais que precisam ser alterados e, quando você parar de obtê-los, encontrará tudo. Execute o programa e teste tudo! O teste contínuo é de importância crucial ao refatorar.

43
Mason Wheeler

Não sei se isso é uma opção para você, mas começaria a tentar convencê-los a contratar mais desenvolvedores profissionais. Dessa forma, eles poderiam se concentrar em problemas de domínio (tenho certeza que eles têm o suficiente lá).

Acredito que sejam pessoas muito inteligentes, mas tornar-se um bom desenvolvedor exige muito tempo. Eles estão prontos para gastar tanto tempo em uma atividade que não é o principal negócio? IMHO, este não é o caminho para alcançar os melhores resultados.

22
Gilney

Uau. Parece que você tem um grande desafio pela frente! Eu faria algo ao longo das seguintes linhas:

  • Primeiro de tudo: Priorize . O que você deseja alcançar primeiro? Qual é o mais importante para o estado atual do projeto? Do que você tirará o máximo proveito versus quanto tempo levará para chegar lá?.
  • Verifique se você possui um sistema de controle de versão . Git ou Mercurial por exemplo.
  • Obtenha algum tipo de sistema de integração contínua (por exemplo, Jenkins ) em funcionamento.
  • Obtenha um sistema de rastreamento de erros em funcionamento. Mantis é bastante agradável na minha opinião.
  • Examine análise estática do código (se houver algo disponível para o idioma com o qual você está trabalhando atualmente).
  • Tente obter o máximo de consistência em qualquer coisa, desde nomeação de variáveis ​​até convenções e diretrizes gerais de código na base de código.
  • Teste o sistema . Isso é extremamente importante para um grande sistema legado como esse na minha opinião. Use casos de teste para documentar o comportamento existente , independentemente de o comportamento parecer estranho ou não (geralmente há um motivo para o código parecer um certo motivo, pode ser bom ou ruim, ou ambos; P). Michael Feathers trabalhando efetivamente com o código legado é um excelente recurso para isso.
20
Andreas Johansson

Eles dizem que o primeiro passo para resolver um problema é admitir que você tem um. Com isso em mente, você pode começar gerando um gráfico de dependência que ilustra o vasto emaranhado que é sua base de código atual. Boa ferramenta para gerar diagrama de dependência? tem alguns anos, mas contém alguns indicadores para ferramentas que podem ajudar a criar esses gráficos. Eu usaria um gráfico grande e feio que mostra o máximo possível para levar o ponto para casa. Fale sobre problemas que resultam de muitas interdependências e talvez atire ma linha de Buckaroo Banzai :

Você pode verificar sua anatomia o quanto quiser, e mesmo que haja variação normal, quando se trata exatamente disso, dentro da cabeça, tudo parece igual. Não, não, não, não puxe isso. Você nunca sabe ao que pode estar ligado.

A partir daí, apresente um plano para começar a arrumar a bagunça. Divida o código em módulos que sejam o mais independentes possível. Esteja aberto a sugestões de como fazer isso - as pessoas com quem você está conversando conhecem melhor o histórico e a funcionalidade do código. O objetivo, no entanto, é pegar um grande problema e transformá-lo em um número menor de problemas que você pode priorizar e começar a limpar.

Algumas coisas para focar:

  • Crie interfaces limpas entre os módulos e comece a usá-los. O código antigo pode, por necessidade, continuar a não usar essas novas interfaces agradáveis ​​por um tempo - esse é o problema que você está começando a resolver. Mas faça com que todos concordem em usar apenas as novas interfaces daqui para frente. Se houver algo que eles precisam que não esteja nas interfaces, corrija as interfaces, não as rodeie.

  • Procure casos em que a mesma funcionalidade foi repetida. Trabalhe em prol da unificação.

  • Lembre a todos de tempos em tempos que essas mudanças visam tornar a vida mais fácil, não mais difícil. A transição pode ser dolorosa, mas é para um bom propósito, e quanto mais todos estiverem a bordo, mais rapidamente os benefícios virão.

10
Caleb

Depois de examinar Gensym G2 um pouco, parece que a maneira de abordar esse problema será altamente dependente de quanto da base de código se parece com isso:

enter image description here

ou isto:

enter image description here

versus isso, cortesia de 99 garrafas de cerveja :

beer-bottles()

i:integer =99;
j:integer;
constant:integer =-1;

begin
for i=99 down to 1
    do
    j = (i+constant);
        if (i=1) then begin
            post"[i] bottle of beer on the wall";
            post" [i] bottle of beer";
            post" Take one down and pass it around ";
            post" No bottle of beer on the wall"; 
        end 
        else begin
            post"[i] bottles of beer on the wall";
            post" [i] bottles of beer";
            post" Take one down and pass it around ";
            if (i=2) then 
                post" [j] bottle of beer on the wall"
           else
                post" [j] bottles of beer on the wall"; 
           end
    end
end

No caso deste último, você está trabalhando com código-fonte que é efetivamente uma quantidade conhecida e algumas das outras respostas oferecem alguns sábios conselhos para lidar com isso.

Se a maior parte da base de código for a última, ou mesmo uma parte considerável, você estará enfrentando o problema interessante de ter código que provavelmente não pode ser refatorado por ser extremamente especializado ou, pior ainda, algo que parece pode ser removível, mas, a menos que esteja devidamente documentado, você não sabe se está removendo o código crítico (pense em algo como operação de scram ) que não parece estar tão primeiro olhar.

Embora obviamente sua primeira prioridade seja obter algum tipo de controle de versão on-line, como indicado ElYusubov , e parece que o controle de versão foi suportado desde a versão 8. . Como o G2 é uma combinação de duas metodologias de linguagem diferentes, você provavelmente achará mais eficaz usar o controle de versão que é fornecido com ele, em vez de tentar encontrar outra coisa e fazê-lo funcionar.

Em seguida, embora alguns provavelmente defendam que você comece a refatorar, sou um forte defensor de garantir que você entenda completamente o sistema com o qual está trabalhando antes de começar a tocar em qualquer código, especialmente ao lidar com códigos e diagramas visuais desenvolvidos por desenvolvedores sem treinamento formal (ou experiência) em metodologias de engenharia de software. O motivo disso é várias vezes, mas o motivo mais óbvio é que você está trabalhando com um aplicativo que potencialmente tem mais de 100 pessoas/ano de trabalho nele e realmente precisa ter certeza de que sabe o que está fazendo e quanto documentação que existe nele. Como você não disse em qual setor o sistema está implantado, com base no que eu tenho lido sobre o G2, parece seguro assumir que é provavelmente um aplicativo de missão crítica que pode até ter um potencial por também ter implicações na segurança da vida . Assim, entender exatamente o que está fazendo será muito importante. Existe um código que não está documentado e trabalha com os outros membros da equipe para garantir que a documentação seja colocada no lugar para garantir que as pessoas possam determinar o que o código faz.

Em seguida, comece a agrupar os testes de unidade com o máximo de diagramas visuais e de base de código possível. Devo admitir alguma ignorância em relação a como fazer isso com o G2, mas pode quase valer a pena criar sua própria estrutura de teste para colocar isso em prática. Esse também é o momento ideal para começar a apresentar os outros membros da equipe para que eles sejam usados ​​em algumas das práticas de engenharia mais rigorosas envolvidas com a qualidade do código (ou seja, todo código deve ter testes de unidade e documentação).

Depois de realizar testes de unidade em uma quantidade razoável de código, você pode começar a abordar a refatoração de maneira como a sugerida por haylem ; no entanto, lembre-se de que você está lidando com algo destinado ao desenvolvimento de sistemas especializados e refatorá-lo pode ser uma batalha difícil. Este é realmente um ambiente em que há algo a ser dito para não escrever código extremamente genérico às vezes.

Por fim, preste muita atenção ao que os outros membros da equipe dizem, apenas porque a qualidade do código e do diagrama não é a melhor não necessariamente reflete mal sobre eles. Por fim, é provável que, por enquanto, eles saibam mais sobre o que o aplicativo faz, e é por isso que é mais importante que você se sente e certifique-se de entender o que ele faz antes de fazer mudanças radicais também.

9
rjzii

Geralmente, as reclamações que você ouve de imediato não têm nada a ver com os problemas importantes. Afinal, é totalmente normal ouvir essas reclamações em qualquer projeto de software.

Difícil de entender código? Verifica. Base de código maciça? Verifica.

O verdadeiro problema é que as pessoas saem e, quando a nova pessoa entra na organização, ocorre uma desorientação típica. Além disso, há um problema de expectativas irreais e problemas de qualidade de código.

Aqui está o que eu abordaria, a fim de:

  1. Backups, tanto o servidor quanto a versão local
  2. Configurar rastreador de erros
  3. Configurar sistema de controle de versão
  4. Configurar FAQ/Wiki
  5. Primeira análise de todos os cientistas/programadores
    • Lembre-os da regra 80/20. 20% dos erros são responsáveis ​​por 80% dos problemas.
    • Concentre-se nos maiores problemas e mantenha as solicitações de aprimoramento etc.
    • O objetivo aqui não é assustar as pessoas com uma grande lista, mas uma lista de pequenas vitórias alcançáveis. Afinal, você tem que provar seu valor também.
  6. Configurar sistema de compilação
    • Comece a trabalhar para obter construções confiáveis ​​(isso pode demorar um pouco)
    • identificar e nomear cada projeto
    • identificar dependências cíclicas
    • se houver binários de alguns projetos de código aberto, tente obter fontes
  7. Identifique como o código G2 pode ser modularizado, por exemplo APIs, serviços
  8. Identifique como o código G2 pode ser testado, documentado.
  9. Configurar sistema de revisão de código
  10. Segundo relatório
  11. Identifique uma equipe de crack de melhores programadores e trabalhe com eles para agrupar seus módulos.
  12. As revisões de código existem nesta fase para melhorar a comunicação e a documentação. Mantenha a calma nesta fase. Resolver quaisquer problemas do processo.
  13. Instale o sistema para outros programadores. Deixe os membros da equipe de crack se tornarem mentores para os demais. Lembre-se de que o dimensionamento é o problema aqui. Você está efetivamente em uma função de gerenciamento.
9
Chui Tey

Perguntas como estas são toda a razão pela qual o projeto Software Carpentry existe.

Nos últimos 14 anos, ensinamos aos cientistas e engenheiros habilidades básicas de desenvolvimento de software: controle de versão, testes, como modularizar código e assim por diante. Todos os nossos materiais estão disponíveis gratuitamente sob uma licença Creative Commons, e realizamos uma dúzia de workshops gratuitos de dois dias por ano para ajudar as pessoas a começar.

Com base nisso, acho que o melhor ponto de partida é provavelmente o excelente livro (curto) de Robert Glass Fatos e falácias da engenharia de software: sua abordagem baseada em evidências é uma boa Uma maneira de convencer os cientistas de que o que estamos dizendo sobre boas práticas de programação é mais do que apenas opinião.
Quanto às práticas específicas, as duas que as pessoas mais desejam adotar são controle de versão e teste de unidade; uma vez instaladas, elas podem enfrentar o tipo de refatoração sistemática descrita por Michael Feathers em Trabalhando efetivamente com o código legado.
Eu não recomendo mais Programador Pragmático (muita exortação, difícil para os iniciantes colocarem em prática), e acho que o McConnell's Código concluído é demais para começar (embora seja ótimo dar a eles seis meses ou um ano, uma vez que eles tenham dominado o básico).

Eu também recomendaria altamente o excelente artigo de Paul Dubois "Mantendo a correção em programas científicos" ( Computação em ciências e engenharia, maio-junho de 2005), que descreve uma abordagem de "defesa em profundidade" que combina uma dúzia de práticas diferentes de maneira lógica e coerente.

9
Greg Wilson

Acho que, antes de tudo, você precisa esclarecer sua situação. O que eles querem de você?

  • É muito improvável que eles queiram que você aprenda um idioma antigo, porque isso agora parece um beco sem saída: há uma chance decrescente de encontrar alguém que saiba ou queira aprender G2, para que o conhecimento seja enterrado na pilha de códigos em colapso quando os cientistas atuais saem ou o código todo corrigido falha cada vez mais.
  • Os cientistas (ou alguns deles) estão prontos para aprender uma nova linguagem e muitos paradigmas de programação? Ou eles querem separar a programação e a atividade científica a longo prazo, e talvez tenham mais programadores, se necessário? Parece uma separação racional e mais eficiente de conhecimentos.

Eu acho que o requisito básico aqui é "salvar o conhecimento no sistema", então você precisa ir e escavá-lo!

A primeira tarefa é escrever uma documentação.

Analise a estrutura e os requisitos como se isso fosse uma nova tarefa, mas com a ajuda de um sistema existente. Eles ficarão satisfeitos porque você PERGUNTA, em vez de ENSINAR primeiro - e rapidamente obterá conhecimento suficiente, mas mais organizado, do ponto de vista de um programador: "o que está acontecendo aqui?" Os documentos (estrutura estática do sistema, fluxo de trabalho, componentes, problemas) serão imediatamente valiosos para eles e talvez mostrem informações mais relevantes para eles do que para você (alguns dos caras podem ter "AHA!") E começar a corrigir alguns códigos imediatamente ) ...

Você deve então começar a perguntar para onde eles querem ir?

Se eles estão prontos para se afastar do G2 , que sistema eles querem ver (plataforma, idioma, interface, estrutura geral)? Você pode começar a escrever um invólucro externo ao redor do sistema, se possível, tendo a estrutura de destino, mas mantendo os componentes originais, iniciando lentamente um tipo de estrutura que permite que novos componentes sejam implementados nesse ambiente de destino. Você precisa encontrar os serviços principais (conexões de dados persistentes e "kits de ferramentas": cálculo básico, desenho, ... bibliotecas) e fornecer a eles um ambiente familiar em uma nova plataforma e linguagem, que permita a transição por você ou eles: pegue os códigos antigos um por um, reimplemente (e LIMPE!) no novo ambiente. Quando estiver pronto, eles conhecem o novo idioma; e a camada de serviço (feita principalmente por você, desculpe) está pronta para hospedar os novos componentes.

Se eles não se moverem , você deve aprender G2 e criar a estrutura modular lá, na qual você ou eles devem mover os componentes (com limpeza) . Enfim, a linguagem é apenas uma serialização de dados e árvore de algoritmos ...

Ao analisar e escrever os documentos, leia, use e anuncie os padrões de design do GoF! :-)

... meus 2 centavos

7
Lorand Kedves

Acabei de fazer uma série de apresentações sobre os princípios de Robert Martin SOLID para meus colegas de trabalho. Não sei como esses princípios se traduzem no G2, mas como você está procurando por 5 -7 fundamentos básicos, estes parecem ser um conjunto bem estabelecido para começar. Se você deseja arredondar para 7, você pode começar com DRY e lançar Fail-Fast.

4
StriplingWarrior

"O programa em si é um modelo físico de uma complexa planta de processamento químico ..."

"Como o G2 é como um código que não é código, mas automatizado, escrito por alguma GUI gadawful ..." - Erik Reppen

Assumindo que o objetivo principal do seu software é simular (talvez otimizar, executar estimativas de parâmetros) uma planta química complexa (- === -) ou partes de uma ... então eu ' gostaria de jogar fora uma sugestão bastante diferente:

Convém considerar o uso de linguagem de modelagem matemática de alto nível para extrair a essência, os principais modelos matemáticos, fora de software codificado manualmente.

O que uma linguagem de modelagem faz é separar a descrição do problema dos algoritmos usados ​​para resolvê-lo. Esses algoritmos geralmente são aplicáveis ​​à maioria das simulações/otimizações de uma determinada classe (por exemplo, processos químicos); nesse caso, eles realmente não devem ser reinventados e mantidos internamente.

Três pacotes comerciais usados ​​amplamente em seu setor são: gPROMS, Aspen Custom Modeller e (se seus modelos não incluem fenômenos distribuídos por domínios espaciais), existem pacotes de software baseados em Modelica, como o Dymola.

Todos esses pacotes suportam "extensões" de uma maneira ou de outra, de modo que, se você tem partes de seus modelos que requerem programação personalizada, elas podem ser encapsuladas em um objeto (por exemplo, uma .DLL) que pode ser referenciado pelas equações no modelo. Enquanto isso, a maior parte do seu modelo permanece sucinta, descrita de uma forma facilmente legível pelos cientistas diretamente. Essa é uma maneira muito melhor de capturar o conhecimento e o IP da sua empresa.

A maioria desses programas também deve permitir que você 'inicie pequenas' e transforme pequenas partes (submodelos) do seu código monolítico em seu formato, sendo chamadas externamente. Essa pode ser uma boa maneira de manter um sistema em funcionamento e validá-lo uma peça por vez.

Isenção de responsabilidade: trabalhei como engenheiro de software na empresa por trás do gPROMS por 8 anos. Naquele tempo, vi (e ocasionalmente incorporei) exemplos de software personalizado (por exemplo, provenientes da academia), que começaram pequenos e organizados, implementando alguma solução ou algoritmo inteligente, mas depois explodiram ao longo dos anos com extensões e modificações - sem a orientação útil de um engenheiro de software para mantê-lo limpo. (Eu sou um grande fã de equipes multidisciplinares.)

Então, posso dizer com alguma experiência que certas escolhas importantes feitas mal no início do desenvolvimento de um software (como uma linguagem ou biblioteca de chaves) tendem a permanecer e causar dor por um longo tempo ... Eles já 'moldaram' o software em torno deles. Parece-me que você pode estar enfrentando muitos anos de pura limpeza de código aqui. (Estou hesitante em usar números, mas estou pensando em mais de 10 anos, talvez muito mais, se você não conseguir transferir o código do G2 para algo que ofereça suporte a boas ferramentas de refatoração automatizada, como o Eclipse/Java quick-smart.)

Embora meu status padrão seja "refatorar e manter um sistema operacional", também acho que quando um problema fica "muito grande", uma mudança/reescrita mais radical se torna mais rápida em geral. (E, possivelmente, traz benefícios adicionais, como passar para uma tecnologia mais moderna.) Digo que, com alguma experiência em migrar para uma nova plataforma de software, mas pelo que entendi, é ainda mais dramático com uma porta para um pacote de modelagem matemática.

Para dar uma perspectiva, você pode se surpreender com a redução de tamanho. Por exemplo. os 200.000 LoC poderiam realmente ser representados em algo como 5.000 linhas de equações (OK, estou supondo aqui, mas eu poderia tentar obter um depoimento real de amigos da empresa); além de alguns módulos de função relativamente pequenos, escritos em algo como C (por exemplo, cálculos de propriedades físicas - embora possam existir novamente pacotes prontos para uso, dependendo do seu processo químico). Isso ocorre porque você simplesmente joga fora o código da solução algorítmica e deixa uma "pilha" de uso geral de solucionadores matemáticos fazer o trabalho duro. Depois de executar as simulações, você pode fazer muito mais com elas, como otimizar o processo - sem alterar uma linha de código.

Por fim, eu diria: se a única documentação confiável dos vários modelos matemáticos (e algoritmos) for o próprio código, você precisará da ajuda dos cientistas e autores originais para ajudar a extrair esses modelos, o mais rápido possível, não anos depois. alguns deles podem ter se mudado. Eles devem achar que uma linguagem de modelagem matemática é uma maneira muito natural de capturar esses modelos - eles podem até (horror de choque) gostar de (re) escrever.


Finalmente, como minha resposta pode estar errada, gostaria de adicionar mais um livro à lista de bons livros já mencionados aqui: Clean Code, de Robert Martin. Cheio de dicas simples (e justificadas), fáceis de aprender e aplicar, mas que podem fazer muita diferença para as pessoas que desenvolvem novo código em sua empresa.

3
Luke Usherwood

O único problema de produção parece um problema de gerenciamento de alterações. Se esse for o caso, e o software o executar de outra forma, o primeiro conselho que daria é resistir ao desejo de fazer muito rapidamente.

Controle de origem, refatoração, desenvolvedores mais treinados são todas boas sugestões, mas se esta é a primeira vez que você lida com esse tipo de problema, movendo-se lentamente e fazendo alterações controladas não pode ser enfatizado o suficiente.

Às vezes, o desejo de destruir a bagunça será grande, mas até que você faça uma engenharia reversa o suficiente para saber que pode testar sua versão de substituição adequadamente, você precisa ter muito cuidado.

3
Bill

Os princípios mais importantes para trabalhar em tal situação são:

  1. Seja paciente. Um buraco que levou 20 anos para Dig não será preenchido em poucas semanas.

  2. Seja positivo. Resista à tentação de reclamar e resmungar.

  3. Seja pragmático. Observe uma mudança positiva que você pode realizar em um dia e faça isso hoje. Já possui um sistema de controle de versão? Implementá-lo e treinar pessoas. Então veja e veja se você pode automatizar o teste (teste de unidade ou algo semelhante). Enxágüe. Repetir.

  4. Seja um modelo. Mostre (não diga apenas) às pessoas como o ágil funciona sendo ágil. Os três primeiros pontos acima são as chaves para ser um Cara Bonzinho, que é o antecessor de um cara Ágil eficaz. Na minha opinião, as pessoas que são admiráveis ​​desenvolvedores não são apenas inteligentes, também são boas, modelam funcionários e colegas.

  5. Mapeie seu território. Eu tenho uma técnica para mapear bases de código herdadas gigantes. Clono o repositório, faço uma cópia de trabalho e tento mudar alguma coisa e ver o que mais quebra. Investigando o acoplamento (via estado global, ou APIs quebradas, ou a falta de API consistente ou quaisquer abstrações ou interfaces com as quais programar) e lendo o código que quebra quando eu mudo as coisas, descubro o problema, faço perguntas que levam a percepções do resto da equipe (acrescentamos que, porque o chefe X há 5 anos exigiu isso, nunca funcionou!). Com o tempo, você obterá um mapa mental do território. Depois de saber o tamanho, você saberá o suficiente para fazer seu mapa e chegar em casa. Incentive outras pessoas a mapear o território da sua base de código gigante e desenvolver o conhecimento técnico da equipe. Algumas pessoas se recusam a "documentação" porque não é ágil. Tanto faz. Também trabalho em ambientes científicos, e a documentação é essencial para mim, que manifestos ágeis sejam condenados.

  6. Crie pequenos aplicativos. Ao trabalhar com uma base de código herdada, percebo que estou no limite. Recupero meu espírito criando pequenos aplicativos auxiliares. Talvez esses aplicativos o ajudem a ler, entender e modificar essa gigantesca base de código G2. Talvez você possa criar uma mini IDE ou ferramenta de análise que o ajudará a trabalhar em seu ambiente. Há muitos casos em que a Metaprogramação e a Construção de Ferramentas não apenas o ajudam a sair do gigante impasses que as bases de código herdadas impõem a você, eles também dão ao seu cérebro a capacidade de voar sem restrições pela sua linguagem G2. Escreva suas ferramentas e auxiliares em qualquer idioma em que você possa executá-las mais rapidamente e com melhor qualidade. Para mim, essas linguagens incluem Python e Delphi Se você é do tipo Perl, ou gosta de programar em C++ ou C #, escreva suas ferramentas auxiliares nessa linguagem. Ensine o restante da equipe a criar pequenos aplicativos e ferramentas auxiliares e "componentes" e você ' Você verá que sua base de código herdada não é tão assustadora, afinal.

3
Warren P
  1. Controle de revisão: mostra aos especialistas em domínio o benefício de poder reverter, ver quem mudou o que etc. (Isso é mais difícil com arquivos totalmente binários, mas se o conteúdo é realmente código, certamente há algum tipo de conversor de G2 para texto que pode ativar diferenças.)

  2. Integração e teste contínuos: envolva os especialistas em domínio na criação de testes de ponta a ponta (mais fácil, pois eles já devem ter entradas e saídas esperadas em algum lugar) e testes de unidade pequena (mais difícil, porque provavelmente o código de espaguete) envolve muitas variáveis ​​globais) que cobrem quase todas as funcionalidades e casos de uso.

  3. Refatorar código comum em rotinas e componentes reutilizáveis. Pessoas que não são de software e sem controle de revisão provavelmente copiam e colam centenas de linhas por vez para fazer rotinas. Encontre-os e refatore-os, mostrando que todos os testes passam e o código ficou mais curto. Isso também ajudará você a aprender sua arquitetura. Se você tiver sorte no momento em que tiver que começar a tomar decisões difíceis de arquitetura, poderá estar abaixo de 100KLOC.

Politicamente, se você encontrar resistência dos veteranos nesse processo, contrate um consultor para entrar e falar sobre uma boa metodologia de software. Certifique-se de encontrar uma boa pessoa com suas opiniões com as quais concorda e peça para a gerência comprar a necessidade do consultor, mesmo que os especialistas em domínio não o façam. (Eles devem concordar - afinal, eles o contrataram, então, evidentemente, eles percebem que precisam de conhecimento em engenharia de software.) É um truque para desperdiçar dinheiro, é claro, mas a razão é que se você - o novo programador jovem e experiente - disser eles precisam fazer algo, eles podem ignorá-lo. Mas se a gerência pagar a um consultor US $ 5.000 para entrar e dizer a eles o que eles precisam fazer, eles confiarão mais nisso. Pontos de bônus : peça ao consultor para aconselhar o dobro da mudança que você realmente deseja, para que você possa ser o "mocinho" e ficar do lado dos especialistas em domínio , comprometendo-se a mudar apenas metade do que o consultor sugeriu.

3
Conrad Poelman

Faça a análise primeiro.

Eu faria algumas análises antes de decidir o que ensinar. Descobrir onde estão os maiores pontos problemáticos. Use-os para priorizar quais práticas serão adotadas.

Introduzir apenas algumas alterações de cada vez (em uma situação semelhante, eu fazia 2-3 treinos a cada 2 semanas) .

Eu limitaria as práticas a ~ 3, dependendo do nível de mudança, para o estilo de programação do SDLC; até que eles se sintam confortáveis ​​com eles (eu pressionaria para introduzir uma nova alteração a cada ~ 1-2 semanas, à medida que se sentirem mais à vontade com a idéia de aprender novas abordagens). Também é uma boa idéia identificar quais são os critérios para o sucesso. O que a prática deve realizar (mesmo que seja um objetivo moderado, como o moral da equipe). Dessa forma, você pode mostrar se é eficaz ou não.

  • Por que limitar o número de alterações?

Mesmo se você presumir que essas pessoas desejam ser melhores programadores e estão abertas ao aprendizado, há limites para quanto e com que rapidez as pessoas podem aprender novos conceitos e aplicá-los; especialmente se eles não tiverem o CS Foundation ou tiverem participado de um ciclo de vida de desenvolvimento de software anteriormente.

Adicione uma reunião semanal para discutir como as práticas os afetaram.

A reunião deve ser usada para discutir o que correu bem e o que precisa funcionar. Permita que eles tenham voz e sejam colaborativos. Discuta e faça planos para resolver os problemas que estão enfrentando e para visualizar as próximas mudanças que estão por vir. Mantenha a reunião focada nas práticas e sua aplicação. Evangelize um pouco sobre os benefícios que eles devem começar a ver com a aplicação das práticas.

Certas práticas têm precedência.

O uso adequado de um sistema de controle de versão (IMO) supera todo o resto. Logo atrás estão as lições de modularização, acoplamento/coesão e rastreamento de recurso/bug.

Remova práticas que não funcionam.

Não tenha medo de se livrar de práticas que não funcionam. Se houver um custo alto e pouco ou nenhum benefício, remova a prática.

Melhoria é um processo.

Transmitir que a melhoria sustentada e consistente é um processo. Identifique os maiores pontos problemáticos, aplique uma solução, aguarde/treine e repita. Inicialmente, parecerá agonizante e lento até você criar algum impulso. Mantenha todos focados nas melhorias que estão chegando e nas que já são bem-sucedidas.

2
dietbuddha

Eu descartaria o seguinte:

  1. Há um programador aqui. Dane-se a política. Eles conhecem o seu ofício. Você conhece o seu. Marque esse território mesmo que você precise mijar nele. Eles são cientistas. Eles podem respeitar esse tipo de coisa ou devem, uma vez que estão constantemente fazendo o mesmo. Por qualquer meio que puder, marque os limites agora. É isso que eu vou consertar. É por isso que não posso ser responsável.

  2. Os cientistas escrevem/testam os algoritmos. Os cientistas que desejam podem escrever seus próprios algoritmos em 1 a 3 idiomas em que todos podem concordar com a conversão para o código principal. Isso coloca o teste deles neles. Além disso, eles terão que ajudá-lo a isolar as coisas importantes da ciência versus o bom Deus sabe o que eles fizeram pela arquitetura. A base de código é mangueira. Há muitas barras e queimaduras que precisam ser feitas. Dê a eles opções para entregar a você versões de trabalho que empregam o que sabem melhor para que você possa fazer o que faz melhor. Coloque seus conhecimentos em uma caixa pela qual eles são responsáveis, mas com os quais você pode trabalhar. Idealmente, quando as coisas correrem bem em conversas de mega-refatoração, será mais sobre que tipos de coisas interessantes você pode fazer com a interface, em vez do tentáculo Z9 de drBobsFuncStructObjThingMk2_0109 quando irritou a variante global X19a91.

  3. Use uma linguagem orientada a eventos com funções de primeira classe, se puder. Quando tudo o mais falha, acionar um evento ou lançar um retorno de chamada para algum objeto com uma interface e um mecanismo de estado que realmente faça sentido pode economizar muito tempo quando você trabalha em um código que não faz muito sentido e possivelmente nunca vai. Os cientistas parecem gostar de Python. Não é difícil colar coisas C intensivas em matemática de nível inferior com isso. Apenas dizendo'

  4. Procure alguém que tenha resolvido esse ou um problema semelhante. Passe algum tempo sério pesquisando. Esses caras ouviram falar do G2 de alguém.

  5. Padrões de design. Adaptadores. Use-os. Use-os muito em situações como esta.

  6. Aprenda o que puder da ciência. Quanto mais você souber, melhor poderá determinar a intenção no código.

2
Erik Reppen

O controle do código-fonte é a etapa 1, como já foi dito várias vezes. Enquanto as pessoas com quem você trabalha podem não ser desenvolvedores profissionais e não respondem a muitas empresas ou jumbo agile. Eles também não são macacos de código de baixo nível, e tentar tratá-los dessa maneira, forçando-os a fazer as coisas do seu jeito, não voará.

Você precisa pesquisar o que está por aí. Se eles não usaram o controle do código-fonte, basta identificar as versões corretas do código (se possível) e o que todas as entregas possíveis levarão muito tempo. Então, você terá a tarefa de ensinar seus colegas a usar o controle do código-fonte e convencê-los de que vale a pena. Comece com os benefícios!

Enquanto estiver fazendo isso, encontre outras frutas baixas e corrija esses problemas.

Acima de tudo, ouça o que eles têm a dizer e trabalhe para melhorar sua situação. Não se preocupe em tentar colocar sua marca no que eles fazem.

Boa sorte!

0
Bill

Parece que o primeiro passo é vender à equipe a necessidade de investir em uma nova metodologia de software. De acordo com sua declaração, não há consenso na equipe e você precisará dela para avançar com uma lenta "atualização" do código.

Eu (se puder) pessoalmente pegaria as lições aprendidas e apresentaria cada um dos principais conceitos que você deseja como solução para o problema na indústria de software.

Por exemplo. dois desenvolvedores tinham cópias diferentes e acabaram implantando uma versão híbrida não testada -> Introduzir controle de versão, ramificação e teste.

Alguém removeu algumas linhas de código que não entendiam e causou uma interrupção -> introduziu o DDD.

Se as lições difíceis não estiverem sendo compartilhadas com você em detalhes suficientes, apenas mostre seus próprios exemplos de como as coisas deram errado quando essa disciplina não foi cumprida.

0
M Afifi