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


470

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 construindo uma vasta base de códigos. (Foi escrito em uma linguagem praticamente obsoleta: G2 - pense em 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 ( sempre há 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 The Pragmatic Programmer , ou Fowler's Refactoring ("Code Smells", 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)?



13
Como o G2 é semelhante ao não-código, mas sim ao código automatizado escrito por alguma interface gráfica, acho que você precisa especificar se você está realmente refatorando no G2 ou refazendo a coisa toda de maneira sensata.
Erik Reppen

101
Faça o que fizer, não reescreva isso do zero. Seria um erro grave. 20 anos de conhecimento químico: são coisas que você nunca seria capaz de recriar. E você, com razão, perderia o respeito dos cientistas.
Francesco

13
Adicione o conselho fundamentado de Joel Spolsky sobre não reescrever ao comentário de @ Francesco: joelonsoftware.com/articles/fog0000000069.html .
Govert

16
Agradável citações eu li recentemente que é uma espécie de relacionados: "Software é o único campo de engenharia que joga em conjunto protótipos e tenta vendê-los como bens entregues"
Chris S

Respostas:


466

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 materiais educacionais apropriados.

Lembre-se: são diretrizes e, como tal, devem ser adotadas, adaptadas ou descartadas 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 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 de 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 ele sabe como usá-lo.
  • Aponte-os para bons IDEs por 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 compilação.
  • Associe o sistema de construção a sistemas de integração contínua e inspeção contínua .
  • Com a ajuda do acima, identifique a qualidade do código "pontos ativos" e refatorar .

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 que trabalha 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 ...

A rigidez vem com moderação!

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 maneira diferente . Uma construção não deve exigir muita pesquisa ou muita adivinhação. Você quer ser capaz de 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 compilação e a sua evolução ao longo do tempo também garantem um nível consistente de qualidade.

Você precisa READMEapontar rapidamente as especificidades do projeto e orientar normalmente 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 compilaçã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 desenvolver uma identidade em equipe e uma linguagem compartilhada . Você não deseja errar no 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 retira 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 nazistas , porque acredito em ter uma língua 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 recuo é outra ideia nesse sentido.

  • Vá, com sua gofmtferramenta, que elimina completamente qualquer debate e esforço ( e ego !! ) inerentes ao estilo: corra gofmtantes de se comprometer.

Verifique se 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 revisões de código são o seu arsenal contra esse demônio.

Além disso, como você verá abaixo, o código é a documentação , e isso é uma outra área onde convenções incentivar a legibilidade e 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 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 não duvidosos 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 é exatamente 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 uma linha 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? -> Veja a 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 Gitfaz isso direito e tenta forçá-lo a escrever bons logs mais do que a maioria dos outros sistemas SCMs, usando short logse long logs. Vincule o ID da tarefa (sim, você precisa de um) e deixe um resumo genérico para shortloge expanda no log longo: escreva a história do conjunto de alterações .

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

Regra geral: se você estava procurando 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 fazer 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 interrompa sua infraestrutura (modificando áreas comuns como código, sistema de compilação, documentação ...),
  • NÃO afetando o trabalho de outras pessoas ,
  • CAPAZ de executar atempadamente qualquer tarefa solicitada .

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


Rigidez versus 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 realizar o trabalho é bom. NUNCA deixe que isso se torne um hábito e NUNCA deixe que esse código se torne a base de código real a ser suportada.


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 uma competição bem-educada e produtiva .
  • NÃO acompanhe os defeitos: é apenas uma boa manutenção da casa.
  • FAZER identificar causas : é apenas a processos de futuro-impermeabilização.
  • MAS NÃO atribua 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 a 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 presumo que eles 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. Os 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 repetidamente 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 futura do trabalho para outros projetos.


Por que tudo isso??!

Por que nos preocupamos com tudo isso? Para a qualidade do código . Ou é um 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 é quantitativa, 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 . O sonar é popular no mundo Java, mas pode se adaptar a qualquer tecnologia; E há muitos outros. Mantenha seu código sob o microscópio e procure esses insetos e micróbios irritantes e irritantes.


Mas e se o 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 (cheia de vapor 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, 200.000 linhas de JSPs, 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 isso? Acabamos de fazer todas as opções acima. Ou tentou muito.

É um esforço de equipe, mas injetamos lentamente nossas regulamentações e ferramentas de processo para monitorar o ritmo cardíaco de nosso produto, enquanto cortamos apressadamente a "gordura": código de porcaria, dependências inúteis ... Não paramos todo o desenvolvimento para faça isso: temos períodos ocasionais de relativa paz e tranquilidade, onde somos livres para enlouquecer na base de código e separá-la, mas na maioria das vezes fazemos tudo por padrão, usando o modo "revisar e refatorar" a cada chance que temos : durante compilações, durante o almoço, durante corridas de correção de bugs, durante as tardes de sexta-feira ...

Houve alguns grandes "trabalhos" ... 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.

Outro foi a injeção de "utilidade ferramenta correias", mesmo que nós estávamos tentando reduzir dependências: Google Goiaba e Apache Commons emagrecer o seu código e e reduzir a superfície de bugs em 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 precisávamos 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 as coisas (você precisa de testes de unidade e é melhor escrevê-las antes de refatorar as coisas), mas, em geral, o benefício para a nossa 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. Testes 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 e frutas baixas .

    As violações têm níveis de severidade, e classes grandes com um grande número de de alta severidade 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 elas 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 problemas, pois você pode apresentar novos sem querer.
    • Vá ao 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: revise -o (faça anotações, envie relatórios de problemas),
    • talvez: limpe -o (limpeza de estilo e pequenas violações),
    • idealmente: refatorá- lo (reorganize 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 ...

  • Sem código "fonte"

    Frequentemente, 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 oculte de você. Os sistemas de programação gráfica sob medida não são incomuns nos 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 próprio depurador, pelo intérprete, pelas ferramentas e formatos de documentação. 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 trabalhei em um desses eu mesmo. 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 IDE visual que usava os procedimentos 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), muitos drivers conectáveis ​​a fontes de dados heterogêneas e um visual canvas para projetar pipelines para processar dados de N datasources e, no final, gerar M transformadas, e possíveis visualizações brilhantes e relatórios on-line complexos (e interativos). Seu típico sistema de programação visual sob medida, sofrendo de 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 pode extrair a maior parte da programação deste sistema para usar mais ferramentas e linguagens convencionais, "apenas" precisa adaptá-lo às restrições do seu sistema.

Sobre controle de versão e armazenamento

No final, você quase sempre pode fazer a versão das 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 está exatamente usando 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 da indústria 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. Muito 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 essa 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 seu sistema de programação e fazer o melhor possível. 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.
  • Open Source qualquer ferramenta que você escreve.

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 Obscure Idioma X . Se não houver, inicie um!

  • Faça perguntas no Stack Overflow ,
  • Talvez até escreva uma proposta para um novo site StackExchange na área 51 .

Talvez seja bonito por dentro , mas ninguém tem idéia até agora, então ajude a derrubar essa parede feia e deixe os outros dar uma espiada!


22
NOTA: Os comentários sobre isso foram limpos à medida que estavam ficando fora de controle. Haylem incorporou os mais relevantes e úteis na resposta. Além disso - a resposta está muito próxima do limite de 30.000 caracteres para as postagens. Por favor, edite com extremo cuidado.
ChrisF

3
Falta apenas uma peça na Integração Contínua, que é uma distinção importante: NÃO culpe as pessoas por checkins ruins, culpe-as por não limparem imediatamente. Não há problema em cometer um erro. Erros ajudam você a aprender, mas deixar seus colegas de trabalho sofrer com seus erros desperdiça tempo, energia e, na pior das hipóteses, ensina ressentimento.
Jason

96
Quando posso comprar esta resposta em capa dura?
LarsH # 8/12

5
Eu fui inicialmente desligado por esta resposta. Não sei bem por que, mas as palavras me atrapalharam e pareciam um pouco alto demais. No entanto, ao ler o guia seção por seção (ao contrário de uma sessão), achei extremamente útil. Se você acha esta resposta assustadora e chegou a esse comentário sem lê-lo, volte e leia apenas uma seção.
precisa saber é o seguinte

5
muito rígida, muito enrolada e afirmando o óbvio. Se essa é sua agenda / estratégia, ninguém mais o ouvirá depois de um mês.
Joppe

101

O 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.

Editar: 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.

Há um post semelhante sobre como lidar com o código herdado , pode ser uma boa referência a seguir - Conselhos sobre como trabalhar com o código herdado


19
Infelizmente, uma das desvantagens da linguagem G2 é que os arquivos de origem não são legíveis por humanos (é fundamentalmente uma linguagem gráfica, semelhante ao LabView ) e, portanto, implementar o Controle de Versão não é trivial. Este é, de fato, um dos nossos maiores obstáculos atualmente (IMO).
kmote

4
@kmote: O criador do G2 possui alguma de suas próprias ferramentas especiais para ajudar no controle de versão? Alguém mais criou essa ferramenta?
FrustratedWithFormsDesigner

39
Todo pacote de controle de origem pode gerenciar binários, embora com algumas limitações. Toda ferramenta que eu conheço tem a capacidade de usar um visualizador e editor de diferenças personalizado, use esse recurso. Arquivos de origem binários não são uma desculpa para não usar o controle de versão.
mattnz

11
Você pode fazer a engenharia reversa do formato de arquivo G2 e criar um utilitário para despejá-lo no formato de texto compatível com diferenças. Isso pode parecer assustador, mas para uma base de código tão grande, valeria a pena o esforço (na minha opinião ingênua).
Joey Adams

6
@Erik: Usar o Controle de Versão SOMENTE como uma ferramenta de "reversão" é como comprar um Porsche para fazer compras - Faz isso tão bem quanto qualquer outra coisa, mas pode fazer muito mais por você ...
mattnz

43

Quando tenho que trabalhar com código espaguete, a primeira coisa em que trabalho é a 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. Em seguida, execute o programa e teste tudo! O teste contínuo é de importância crucial ao refatorar.


17
Trabalhar efetivamente com o código legado é provavelmente uma leitura obrigatória para isso.
Oded

3
Melhor ainda .. Ao invés de apenas executar o programa, a unidade testar seus novos módulos :)
Demian Brecht

1
Essa é a melhor abordagem (junto com a etapa óbvia de colocar todo o lote no controle de versão). Toda a bobagem nas grandes respostas é muito geral e muito grande para ser aplicada de uma só vez. passos de bebê até que você tenha algum conceito da coisa geral. Eu herdei um projeto de 50k uma vez (na verdade, quatro versões dos mesmos 50k). Depois de um mês, eu tinha uma versão e me livrava de cerca de 10 mil linhas através de refatoração / reestruturação básica. Coloque-o no repositório, 2-certifique-se de que você pode construí-lo, 3-refatorar / reestruturar, repita 3 até terminar.

22

Não sei se isso é uma opção para você, mas começaria a 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.


16
O OP é o primeiro desenvolvedor profissional. A melhor maneira de o OP convencê-lo a contratar mais é fornecer um valor extra óbvio nos primeiros 6 a 12 meses. Se isso puder ser alcançado, o OP terá credibilidade e poderá contratar mais.
MarkJ

20

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

  • Em primeiro lugar: 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.
  • Instale um sistema de rastreamento de erros .Mantis é bastante agradável na minha opinião.
  • Examine a análise de código estático (se houver algo disponível para o idioma com o qual você está trabalhando).
  • Tente alcançar o máximo de consistência em tudo, desde a 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á uma razão pela qual o código parece certo, pode ser bom ou ruim, ou ambos; P). Michael Feathers Trabalhar efetivamente com o Legacy Code é um excelente recurso para isso.

10

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 os problemas que resultam de muitas interdependências e talvez jogue uma linha do Buckaroo Banzai :

Você pode verificar sua anatomia o quanto quiser, e mesmo que haja variação normal, quando se trata disso, tão longe dentro da cabeça, tudo parece o mesmo. 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, necessariamente, continuar a não usar essas novas e agradáveis ​​interfaces 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.


1
@kmote Eles não teriam contratado você se não reconhecessem que precisam de ajuda e querem fazer as coisas melhor. A parte mais difícil pode ajudá-los a se lembrar de que seu trabalho não é consertar o (s) problema (s), mas ajudá- los a consertar o (s) problema (s). Buckaroo Banzai é bastante popular entre os tipos científicos de uma certa idade - talvez ele possa ajudá-lo a manter as coisas leves.
Caleb

9

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

insira a descrição da imagem aqui

ou isto:

insira a descrição da imagem aqui

contra 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 conselhos muito sábios 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 semelhante ao de uma operação de scram ) que não parece ser tão à primeira vista.

Embora, obviamente, sua primeira prioridade seja obter algum tipo de controle de versão on-line, como apontado ElYusubov , e parece que o controle de versão é suportado desde a versão 8.3 . 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 tenho lido sobre o G2, parece seguro presumir que é provavelmente um aplicativo de missão crítica que pode até ter o potencial de 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 pela 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.


1
@haylem - Não faço ideia, e pode ser inteiramente possível que haja 200.000 LOC mais n diagramas e gráficos de fluxo no aplicativo. Portanto, 200.000 LOC podem estar subestimando significativamente a complexidade do aplicativo.
Rjzii

9

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 irrealistas 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

Perguntas como essas 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 algumas dúzias 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 (pequeno) livro de Robert Glass, Facts and Fallacies of Software Engineering : sua abordagem baseada em evidências é uma boa maneira de convencer os cientistas de que o que estamos dizendo a eles 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 implementados, eles podem enfrentar o tipo de refatoração sistemática que Michael Feathers descreve em Trabalhando efetivamente com o código legado .
Não recomendo The Pragmatic Programmer (muita exortação, difícil para os iniciantes colocarem em prática) e acho que o Código Completo de McConnell é demais para começar (embora seja ótimo dar a eles seis meses ou um ano, depois que eles dominam o básico).

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


sugestões interessantes. Vou dar uma olhada. (Nota: link quebrado no jornal Dubois)
kmote

7

Acho que, antes de tudo, você precisa resolver 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 desejam 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 do GoF Design! :-)

... meus 2 centavos


Concordo que o passo 1 é descobrir o que eles querem de você, mas o próximo passo deve ser o de fazer isso, e se o próximo passo não é documentar o estado das coisas, não faça muito isso. Se você fizer isso, eles não vão gostar.
Bill

@ bill: A pergunta diz "não há um consenso de opinião sobre o que é necessário para o caminho a seguir". Eles não sabem! Suponho que haja debates sérios sem insights reais sobre o sistema que devem ser salvos "de alguma forma". A tarefa de um programador nessa situação é óbvia (pelo menos para mim): faça uma análise correta do ponto de vista técnico para ajudar a tomar uma decisão racional.
Lorand Kedves

É claro que eles não sabem o que querem, essa é a parte "resolva tudo", que é diferente de apenas escolher algo como documentação e padrões e dizer fazer essas coisas. Essas coisas são boas, mas deve ser um processo que envolva o grupo, e se você começar com coisas em que eles não vêem valor primeiro, será difícil obter uma entrada. - Saúde!
Bill

@ Bill: Eu acho que você diz exatamente o mesmo que escrevi sobre o conteúdo e a criação dessa documentação ... ;-)
Lorand Kedves

4

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


1
ooh, excelente sugestão! Lembrei-me dessa bela visão geral, juntamente com este resumo gratuito de e-books .
kmote

3

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 maneira, o primeiro conselho que daria é resistir ao desejo de fazer muito rapidamente.

Controle de fonte, 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 a engenharia reversa o suficiente para saber que pode testar sua versão de substituição adequadamente, você precisa ter muito cuidado.


3

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

  1. Seja paciente. Um buraco que levou 20 anos para cavar 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 vejo 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ão a trabalhar em seu ambiente. Existem muitos casos em que a metaprogramação e a criação de ferramentas não apenas o ajudam a romper com os impasses gigantes que as bases de código herdadas impõem a você, mas 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 fazê-los mais rapidamente e melhor. 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.


3
  1. Controle de revisão : mostre aos especialistas em domínio o benefício de poder reverter, ver quem mudou o quê etc. (Isso é mais difícil com arquivos binários, mas se o conteúdo é realmente código, certamente há algum tipo de G2 para conversor de texto que pode ativar as 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 o código espaguete provavelmente envolve muitas variáveis ​​globais) que abrangem quase todas as funcionalidades e casos de uso.

  3. Refatorar o 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 as opiniões com as quais concorda e de que a gerência compre a necessidade do consultor, mesmo que os especialistas em domínio não o façam. (Eles deveriam 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 bônus: peça ao consultor para aconselhar o dobro da alteração que realmente deseja, para que você possa ser o "cara legal" e ficar do lado dos especialistas em domínio, comprometendo-se a alterar apenas metade da quantidade sugerida pelo consultor.


3

"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 lançar 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, 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 são geralmente 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 amplamente utilizados 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 total: 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 tinham começado pequenos e arrumados, 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 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.

Finalmente, 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 dos autores originais para ajudar a extrair esses modelos, o mais rápido possível, não anos depois, quando 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.


2

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 de coisas que empregam o que sabem melhor para que você possa fazer o que faz de melhor. Coloque seus conhecimentos em uma caixa pela qual eles são responsáveis, mas com os quais você pode trabalhar.

  3. Use uma linguagem orientada a eventos com funções de primeira classe, se puder. Quando tudo mais falhar, 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ê estiver envolvido 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.


13
NUNCA vá cara a cara com os cientistas. NUNCA . Eles tornarão sua vida um inferno. :)
haylem

2

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 fiz 2-3 práticas 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 comecem a se sentir confortáveis ​​com eles (eu insistiria em introduzir uma nova alteração a cada ~ 1-2 semanas, à medida que se sentissem 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 de encerramento 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.


0

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 "atualização" lenta do código.

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

Por exemplo, dois desenvolvedores tiveram 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

O controle do código-fonte é a etapa 1, como já foi dito várias vezes. Embora as pessoas com quem você trabalha não sejam desenvolvedores profissionais e não respondam 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ê tem que pesquisar o que está lá fora. 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!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.