ti-enxame.com

Como manter um produto de software grande e complexo com manutenção ao longo dos anos?

Trabalho como desenvolvedor de software há muitos anos. Foi minha experiência que os projetos se tornam mais complexos e insustentáveis ​​à medida que mais desenvolvedores se envolvem no desenvolvimento do produto.

Parece que o software em um certo estágio de desenvolvimento tem a tendência de ficar "mais hackier" e "hackier", especialmente quando nenhum dos membros da equipe que definiu a arquitetura trabalha mais na empresa.

Acho frustrante que um desenvolvedor que tenha que mudar alguma coisa tenha dificuldade em obter uma visão geral da arquitetura. Portanto, há uma tendência para corrigir problemas ou fazer alterações de maneira que funcione na arquitetura original. O resultado é um código que se torna cada vez mais complexo e ainda mais difícil de entender.

Existe algum conselho útil sobre como manter o código fonte realmente sustentável ao longo dos anos?

157
chrmue

A única solução real para evitar a podridão do código é codificar bem!

Como codificar bem é outra questão. É difícil o suficiente, mesmo se você é um excelente programador trabalhando sozinho. Em uma equipe heterogênea, torna-se muito mais difícil ainda. Em (sub) projetos terceirizados ... apenas ore.

As boas práticas usuais podem ajudar:

  1. Mantenha simples.
  2. Mantenha simples. Isso se aplica especialmente à arquitetura, o "quadro geral". Se os desenvolvedores estão tendo dificuldades para entender o cenário geral, eles estão codificando-os. Portanto, simplifique a arquitetura para que todos os desenvolvedores a entendam. Se a arquitetura precisa ser menos que simples, os desenvolvedores devem ser treinados para entender essa arquitetura. Se não o internalizarem, não deverão codificá-lo.
  3. Apontar para baixo acoplamento e alta coesão . Certifique-se de que todos na equipe entendam essa idéia. Em um projeto que consiste em partes coesas e fracamente acopladas, se algumas delas se tornarem uma bagunça insustentável, você pode simplesmente desconectar e reescrever essa parte. É mais difícil ou quase impossível se o acoplamento estiver apertado.
  4. Ser consistente. Quais padrões seguem pouco importa, mas siga alguns padrões. Em uma equipe, todos devem seguir os mesmos padrões, é claro. Por outro lado, é fácil ficar muito apegado aos padrões e esquecer o resto: por favor, entenda que, embora os padrões sejam úteis, eles são apenas uma pequena parte da criação de um bom código. Não faça um grande número disso.
  5. Revisões de código pode ser útil para que uma equipe trabalhe de forma consistente.
  6. Certifique-se de que todas as ferramentas - IDEs, compiladores, controle de versão, sistemas de construção, geradores de documentação, bibliotecas, computadores , cadeiras , ambiente geral etc. etc. - são bem mantidas para que os desenvolvedores não precisem perder seu tempo com problemas secundários, como combater conflitos de versão de arquivo de projeto, atualizações do Windows, ruído e qualquer coisa banal, mas irritante. Ter que gastar repetidamente um tempo considerável com coisas tão desinteressantes reduz o moral, o que pelo menos não melhora a qualidade do código. Em uma equipe grande, pode haver um ou mais funcionários cujo trabalho principal é manter as ferramentas do desenvolvedor.
  7. Ao tomar decisões tecnológicas, pense no que seria necessário para mudar a tecnologia; quais decisões são irreversíveis e quais não são. Avalie as decisões irreversíveis com muito cuidado. Por exemplo, se você decidir escrever o projeto em Java , é uma decisão praticamente irreversível. Se você decidir usar algum formato binário auto-fervido para arquivos de dados, isso também será uma decisão bastante irreversível (quando o código estiver disponível e você precisar continuar apoiando esse formato). Porém, as cores da GUI podem ser facilmente ajustadas, os recursos inicialmente deixados de fora podem ser adicionados mais tarde, portanto, menos estresse sobre esses problemas.
138
Joonas Pulakka

testes de unidade são seus amigos . Implementá-los força baixo acoplamento. Isso também significa que as partes "hacky" do programa podem ser facilmente identificadas e refatoradas. Isso também significa que quaisquer alterações podem ser testadas rapidamente para garantir que não quebrem a funcionalidade existente. Isso deve incentivar seus desenvolvedores a modificar os métodos existentes, em vez de duplicar o código por medo de quebrar as coisas.

Os testes de unidade também funcionam como uma documentação extra para o seu código, descrevendo o que cada parte deve fazer. Com extensos testes de unidade, seus programadores não precisam conhecer toda a arquitetura do seu programa para fazer alterações e usar as classes/métodos existentes.

Como um bom efeito colateral, esperamos que os testes de unidade também reduzam a contagem de erros.

55
Tom Squires

Todo mundo aqui é rápido em mencionar rot de código, e eu entendo e concordo completamente com isso, mas ainda falta a imagem maior e o maior problema em questão aqui. O apodrecimento do código não acontece apenas. Além disso, são mencionados testes de unidade que são bons, mas na verdade não solucionam o problema. Pode-se ter uma boa cobertura de teste de unidade e um código relativamente livre de erros, no entanto, ainda possui código e design apodrecidos.

Você mencionou que o desenvolvedor que trabalha em um projeto tem dificuldade em implementar um recurso e perde a visão geral da arquitetura geral e, portanto, implementa um hack no sistema. Onde está a liderança técnica para aplicar e influenciar o design? Onde estão as revisões de código nesse processo?

Você não está realmente sofrendo de apodrecimento do código, mas está sofrendo de apodrecimento da equipe. O fato é que não deve importar se os criadores originais do software não estão mais na equipe. Se o líder técnico da equipe existente entender completamente e verdadeiramente o design subjacente e for bom no papel de líder técnico, isso não será um problema.

40
maple_shaft

Existem várias coisas que podemos fazer:

Dê a uma pessoa a responsabilidade geral pela arquitetura. Ao escolher essa pessoa, garanta que ela tenha a visão e a habilidade para desenvolver e manter uma arquitetura, e que ela tenha a influência e autoridade para ajudar outros desenvolvedores a seguir a arquitetura. Essa pessoa deve ser um desenvolvedor experiente, de confiança da gerência e respeitado por seus colegas.

Crie uma cultura em que todos os desenvolvedores se apropriem da arquitetura. Todos os desenvolvedores precisam estar envolvidos no processo de desenvolvimento e manutenção da integridade da arquitetura.

Desenvolva um ambiente em que as decisões arquitetônicas sejam facilmente comunicadas. Incentive as pessoas a falar sobre design e arquitetura - não apenas no contexto do projeto atual, mas em geral também.

As melhores práticas de codificação facilitam a visualização da arquitetura - leve tempo para refatorar, comentar o código, desenvolver testes de unidade etc. Coisas como convenções de nomenclatura e práticas de codificação limpas podem ajudar muito na comunicação da arquitetura, assim como uma equipe que você precisa reserve um tempo para desenvolver e seguir seus próprios padrões.

Garanta que toda a documentação necessária seja clara, concisa, atualizada e acessível. Torne públicos os diagramas de arquitetura de alto e baixo nível (fixá-los na parede pode ajudar) e publicamente de manutenção.

Finalmente (como perfeccionista natural), preciso reconhecer que a integridade da arquitetura é uma aspiração digna, mas que pode haver coisas mais importantes - como formar uma equipe que possa trabalhar bem em conjunto e realmente enviar um produto em funcionamento.

18
Kramii

A maneira como resolvo esse problema é cortá-lo na raiz:

Minha explicação será usar termos da Microsoft/ . NET , mas será aplicável a qualquer plataforma/caixa de ferramentas:

  1. Use padrões para nomeação, codificação, checkins, fluxo de bugs, fluxo de processos - basicamente qualquer coisa.
  2. Não tenha medo de dizer adeus aos membros da equipe que não seguem os padrões. Alguns desenvolvedores simplesmente não podem trabalhar dentro de um conjunto definido de padrões e se tornarão inimigos da 5ª coluna no campo de batalha para manter a base de código limpa
  3. Não tenha medo de alocar membros da equipe menos qualificados para testes por longos períodos de tempo.
  4. Use todas as ferramentas do seu arsenal para evitar o check-in do código em decomposição: isso envolve ferramentas dedicadas, bem como testes de unidade pré-escritos que testam os arquivos de construção, arquivos de projeto, estrutura de diretório, etc.
  5. Em uma equipe de cerca de 5 a 8 membros, peça ao seu padrinho que refatore quase constantemente - limpando a bagunça que os outros deixam para trás. Mesmo se você encontrar os melhores especialistas no campo, ainda terá uma bagunça - é inevitável, mas pode ser restringido pela constante refatoração.
  6. Faça testes de unidade e os mantenha - NÃO dependa dos testes de unidade para manter o projeto limpo, eles não.
  7. Discuta tudo. Não tenha medo de gastar horas para discutir as coisas da equipe. Isso disseminará as informações e removerá uma das causas principais do código incorreto: confusão sobre tecnologias, objetivos, padrões etc.
  8. Tenha muito cuidado com os consultores que escrevem código: o código deles, quase por definição, será realmente uma merda.
  9. Faça revisões de preferência como a etapa do processo antes do check-in. Não tenha medo de reverter confirmações.
  10. Nunca use o princípio de abrir/fechar , a menos que no último estágio antes do lançamento: ele simplesmente faça com que o código em decomposição seja deixado para cheirar.
  11. Sempre que um problema é solucionado, reserve um tempo para entendê-lo ao máximo antes de implementar uma solução - a maioria das rotações de código vem da implementação de soluções para problemas não totalmente compreendidos.
  12. Use as tecnologias certas. Geralmente, eles vêm em conjuntos e são novos: é melhor depender de uma versão beta de uma estrutura da qual você terá suporte no futuro, do que depender de estruturas extremamente estáveis, mas obsoletas, sem suporte.
  13. Contrate as melhores pessoas.
  14. Demitir o resto - você não está executando um café.
  15. Se o gerenciamento não é dos melhores arquitetos e eles interferem no processo de tomada de decisão - encontre outro emprego.
18
casper

Limpe o código apodrecido refatorando, enquanto escreve testes de unidade. Pague (isso) a dívida do projeto em todo o código que você tocar, sempre que:

  • Desenvolver um novo recurso
  • Corrigir um problema

Acelere bastante seu ciclo de desenvolvimento de teste primeiro:

  • Refatoração para converter módulos de código em uma linguagem de script
  • Use máquinas de teste rápidas e baseadas na nuvem

Refatorar o código para usar baixo acoplamento (de unidades altamente coesas internamente):

  • Mais simples, (mais) funções (rotinas)
  • Módulos
  • Objetos (e classes ou protótipos)
  • Funções puras (sem efeitos colaterais)
  • Preferindo delegação, sobre herança
  • Camadas (com APIs)
  • Coleções de pequenos programas de uso único que podem operar juntos

O crescimento orgânico é bom; um grande projeto inicial é ruim.

Tenha um líder que tenha conhecimento sobre o design atual. Caso contrário, leia o código do projeto até ter conhecimento.

Leia livros de refatoração.

12
MarkDBlackwell

Resposta simples: você não pode.

É por isso que você deve procurar por software pequeno e simples software. Não é fácil.

Isso só é possível se você pensar o suficiente sobre o seu problema aparentemente complexo para defini-lo da maneira mais simples e concisa possível.

A solução para problemas realmente grandes e complexos ainda pode ser resolvida com base em módulos pequenos e simples.

Em outras palavras, como outros apontaram, a simplicidade e o acoplamento flexível são os principais ingredientes.

Se isso não for possível ou possível, você provavelmente está pesquisando (problemas complexos sem soluções simples conhecidas ou nenhuma solução conhecida). Não espere que a pesquisa produza diretamente produtos de manutenção, não é para isso que serve a pesquisa.

11
Joh

Eu trabalho em uma base de código para um produto que está em desenvolvimento contínuo desde 1999, então, como você pode imaginar, já é bastante complexo. A maior fonte de hackers em nossa base de código é das inúmeras vezes em que tivemos que portá-la de ASP Classic a ASP.NET , de ADO para ADO.NET, de postbacks para Ajax , alternando bibliotecas da interface do usuário, padrões de codificação etc.

Em suma, fizemos um trabalho razoável para manter a base de código sustentável. As principais coisas que fizemos e que contribuíram para isso são:

1) Refatoração constante - Se você precisar tocar em um pedaço de código hacky ou difícil de entender, espera-se que dedique um tempo extra para limpar e é dada a margem de manobra no cronograma para fazê-lo. Os testes de unidade tornam isso muito menos assustador, porque você pode testar contra regressões mais facilmente.

2) Mantenha um ambiente de desenvolvimento limpo - Esteja atento ao excluir código que não é mais usado e não deixe cópias de backup/cópias de trabalho/código experimental existe no diretório do projeto.

3) Padrões de codificação consistentes para a vida útil do projeto - Vamos ser sinceros, nossos pontos de vista sobre os padrões de codificação evoluem com o tempo. Sugiro manter o padrão de codificação iniciado por toda a vida útil de um projeto, a menos que você tenha tempo para voltar e adaptar todo o código para estar em conformidade com o novo padrão. É ótimo que você tenha terminado notação húngara agora, mas aplique essa lição a novos projetos e não apenas mude o meio do caminho nesse novo projeto.

9
JohnFx

Desde que você marcou a pergunta com gerenciamento de projetos, tentei adicionar alguns pontos que não são de código :)

  • Planeje a rotatividade - suponha que toda a equipe de desenvolvimento tenha desaparecido quando chegar à fase de manutenção - nenhum desenvolvedor que se preze quer ficar preso mantendo o sistema para sempre. Comece a preparar os materiais de entrega assim que tiver tempo.

  • Consistência/uniformidade não pode ser estressada o suficiente. Isso desencorajará uma cultura de 'vá sozinho' e incentivará os novos desenvolvedores a perguntar, se eles estiverem em dúvida.

  • Mantenha o mainstream - tecnologias usadas, padrões e padrões de design - porque um novo desenvolvedor da equipe (em qualquer nível) terá mais chances de começar a funcionar rapidamente.

  • Documentação - especialmente arquitetura - por que as decisões foram tomadas e os padrões de codificação. Além disso, mantenha referências/notas/roteiros para documentar o domínio comercial - você ficaria surpreso com o quão difícil é para os negócios corporativos explicar o que eles fazem com um desenvolvedor sem experiência no domínio.

  • Estabeleça as regras claramente - não apenas para sua equipe de desenvolvimento atual, mas pense nos futuros desenvolvedores de manutenção. Se isso significa colocar um hiperlink para a documentação padrão relevante de design e codificação em todas as páginas, que assim seja.

  • Verifique se a arquitetura e, especialmente, as camadas de código estão claramente demarcadas e separadas - isso permitirá a substituição de camadas de código à medida que novas tecnologias surgirem, por exemplo, substitua uma interface do usuário de formulários da Web por HTML5 - jQuery UI etc., que pode comprar um ano ou mais de maior longevidade.

8
StuartLC

Uma propriedade do código altamente sustentável é pureza da função .

Pureza significa que as funções devem retornar o mesmo resultado para os mesmos argumentos. Ou seja, eles não devem depender dos efeitos colaterais de outras funções. Além disso, é útil se eles próprios não tiverem efeitos colaterais.

É mais fácil testemunhar essa propriedade do que as propriedades de acoplamento/coesão. Você não precisa se esforçar para alcançá-lo, e eu pessoalmente o considero mais valioso.

Quando sua função é pura, seu tipo é uma documentação muito boa por si só. Além disso, escrever e ler documentação em termos de argumentos/valor de retorno é muito mais fácil do que mencionar algum estado global (possivelmente acessado por outros threads O_O).

Como um exemplo do uso extensivo de pureza para ajudar na manutenção, você pode ver GHC . Trata-se de um grande projeto com cerca de 20 anos em que grandes refatorações estão sendo realizadas e novos recursos importantes ainda estão sendo introduzidos.

Por fim, não gosto muito do ponto "Mantenha as coisas simples". Você não pode manter seu programa simples quando estiver modelando coisas complexas. Tente criar um compilador simples e seu código gerado provavelmente acabará lento. Claro, você pode (e deve) simplificar as funções individuais, mas o programa inteiro não será simples como resultado.

7
Rotsor

Como muitas dessas respostas parecem se concentrar em equipes grandes, mesmo desde o início, vou colocar minha opinião como parte de uma equipe de desenvolvimento de dois homens (três se você incluir o designer) para uma startup.

Obviamente, projetos e soluções simples são os melhores, mas quando você tem o cara que literalmente paga seu salário pelo pescoço, não tem tempo para pensar na solução mais elegante, simples e sustentável. Com isso em mente, meu primeiro grande ponto é:

Documentação Sem comentários, o código deve ser principalmente auto-documentado, mas coisas como documentos de design, hierarquias e dependências de classes, paradigmas arquitetônicos etc. Qualquer coisa que ajude um programador novo ou mesmo existente a entender a base de código . Além disso, documentar essas pseudo-bibliotecas ímpares que aparecem eventualmente, como "adicionar esta classe a um elemento para essa funcionalidade" pode ajudar, pois também impede que as pessoas reescrevam a funcionalidade.

No entanto, mesmo se você tiver um limite de tempo severo, acho que outra coisa boa a ter em mente é:

Evite hacks e correções rápidas. A menos que a solução rápida seja a solução real, é sempre melhor descobrir o problema subjacente para alguma coisa e, em seguida, corrigir isso. A menos que você literalmente tenha um cenário "faça isso funcionar nos próximos 2 minutos ou esteja demitido", fazer a correção agora é uma idéia melhor, porque você não corrigirá o código posteriormente, apenas passe para a próxima tarefa que você tem.

E minha dica favorita pessoal é mais uma citação, embora não me lembre da fonte:

"Codifique como se a pessoa que vem depois de você é um psicopata homicida que sabe onde você mora"

6
Aatch

Além das outras respostas, eu recomendaria camadas. Não são muitos, mas o suficiente para separar diferentes tipos de código.

Usamos um modelo de API interno para a maioria dos aplicativos. Há uma API interna que se conecta ao banco de dados. Então uma camada UI . Pessoas diferentes podem trabalhar em cada nível sem interromper ou quebrar outras partes dos aplicativos.

Outra abordagem é fazer com que todos leiam comp.risks e The Daily WTF para que eles aprendam o conseqüências de um design ruim e de uma programação ruim, e eles temem ver seu próprio código publicado em The Daily WTF .

6
jqa

Um princípio que não foi mencionado, mas que considero importante, é o princípio aberto/fechado .

Você não deve modificar o código que foi desenvolvido e testado: qualquer parte desse código está selada. Em vez disso, estenda as classes existentes por meio de subclasses ou use-as para escrever wrappers, decorator classes ou usar o padrão que achar adequado. Mas não altere o código de trabalho .

Apenas meus 2 centavos.

5
Giorgio
  • Seja um olheiro . Sempre deixe o código mais limpo do que o encontrado.

  • Corrija o janelas quebradas . Todos esses comentários "mudam na versão 2.0" quando você está na versão 3.0.

  • Quando houver grandes invasões, projete uma solução melhor como equipe e faça-o. Se você não pode consertar o hack como uma equipe, não entende o sistema suficientemente bem. "Peça ajuda a um adulto." As pessoas mais velhas podem ter visto isso antes. Tente desenhar ou extrair um diagrama do sistema. Tente desenhar ou extrair os casos de uso particularmente invasivos como diagramas de interação. Isso não corrige, mas pelo menos você pode vê-lo.

  • Que suposições não são mais verdadeiras que impulsionaram o design em uma direção específica? Pode haver uma pequena refatoração escondida atrás de um pouco dessa bagunça.

  • Se você explicar como o sistema funciona (mesmo apenas um caso de uso) e tiver que se desculpar repetidamente de um subsistema, esse é o problema. O que o comportamento tornaria o resto do sistema mais simples (não importa o quão difícil pareça implementar em comparação com o que existe). O subsistema clássico a ser reescrito é aquele que polui todos os outros subsistemas com sua semântica e implementação operacional. "Ah, você precisa alterar os valores antes de alimentá-los no subsistema froo e descompactá-los novamente à medida que obtém a saída do froo. Talvez todos os valores devam ser alterados quando lidos pelo usuário e armazenamento, e o resto do sistema está errado? Isso fica mais emocionante quando existem duas ou mais especificações diferentes.

  • Passe uma semana como uma equipe removendo avisos para que problemas reais sejam visíveis.

  • Reformate todo o código para o padrão de codificação.

  • Verifique se o seu sistema de controle de versão está vinculado ao seu rastreador de erros. Isso significa que mudanças futuras são agradáveis ​​e responsáveis, e você pode descobrir POR QUE.

  • Faça alguma arqueologia. Encontre os documentos de design originais e revise-os. Eles podem estar naquele PC antigo no canto do escritório, no espaço abandonado ou no arquivo que ninguém abre.

  • Republicar os documentos de design em um wiki. Isso ajuda a institucionalizar o conhecimento.

  • Escreva procedimentos do tipo lista de verificação para lançamentos e compilações. Isso impede as pessoas de pensarem, para que possam se concentrar na solução de problemas. Automatize compilações sempre que possível.

  • Tente integração contínua . Quanto mais cedo você obtiver uma compilação com falha, menos tempo o projeto poderá gastar fora do Rails.

  • Se o líder da sua equipe não faz essas coisas, isso é ruim para a empresa.

  • Tente garantir que todo o novo código obtenha testes de unidade adequados com cobertura medida. Portanto, o problema não pode ficar muito pior.

  • Tente testar alguns dos bits antigos que não foram testados. Isso ajuda a reduzir o medo da mudança.

  • Automatize seu teste de integração e regressão, se puder. Pelo menos tenha uma lista de verificação. Os pilotos são espertos, recebem lotes pagos e usam listas de verificação. Eles também estragam muito raramente.

5
Tim Williscroft

Leia e depois re-leia Código concluído por Steve McConnell. É como uma Bíblia de boa escrita de software, desde o design inicial do projeto até uma única linha de código e tudo mais. O que mais gosto sobre isso é o backup de décadas de dados sólidos; não é apenas o próximo melhor estilo de codificação.

4
dwenaus

Eu vim para chamar isso de "Efeito Winchester Mystery House". Como a casa, tudo começou bastante simples, mas, ao longo dos anos, muitos trabalhadores diferentes adicionaram tantos recursos estranhos sem um plano geral que ninguém mais o entende mais. Por que essa escada não leva a lugar nenhum e por que essa porta se abre apenas de uma maneira? Quem sabe?

A maneira de limitar esse efeito é começar com um bom design, que seja flexível o suficiente para lidar com a expansão. Várias sugestões já foram oferecidas sobre isso.

Porém, muitas vezes você aceita um trabalho onde o dano já foi causado e é tarde demais para um bom design sem executar uma reformulação e reescrita cara e potencialmente arriscada. Nessas situações, é melhor tentar encontrar maneiras de limitar o caos enquanto o adota em algum grau. Pode incomodar as sensibilidades de seu projeto de que tudo precisa passar por uma classe enorme e feia de 'gerenciadores' ou a camada de acesso a dados está fortemente acoplada à interface do usuário, mas aprenda a lidar com isso. Codifique defensivamente dentro dessa estrutura e tente esperar o inesperado quando aparecerem os 'fantasmas' dos programadores.

3
jfrankcarr

Eu só quero colocar uma questão não técnica e uma abordagem (talvez) pragmática.

Se o seu gerente não se importa com a qualidade técnica (código gerenciável, arquitetura simples, infraestrutura confiável e assim por diante), fica difícil melhorar o projeto. Nesse caso, é necessário educar o gerente e convencer a "investir" os esforços em manutenibilidade e abordar dívida técnica .

Se você sonha com a qualidade do código encontrada nesses livros, também precisa de um chefe preocupado com isso.

Ou se você quiser domesticar um "projeto Frankenstein", estas são as minhas dicas:

  • Organize e simplifique
  • Encurtar funções
  • Priorize a legibilidade sobre a eficiência (quando aceitável, é claro, e alguns ganhos de eficiência são muito difíceis de serem mantidos)

Na minha experiência, a programação é entrópica e não emergente (pelo menos no paradigma estruturado imperativo popular). Quando as pessoas escrevem código para "simplesmente trabalhar", a tendência é perder a organização. Agora, a organização do código exige tempo, às vezes muito mais do que fazê-lo funcionar.

Além da implementação de recursos e correções de bugs, reserve um tempo para a limpeza do código.

2
Eric.Void

refatoração de código e teste de unidade estão perfeitamente corretos. Mas, como esse projeto de longa duração está sendo invadido por hackers, isso significa que a gerência não está se esforçando para limpar a podridão. É necessário que a equipe introduza hacks, porque alguém não está alocando recursos suficientes para treinar pessoas e analisar o problema/solicitação.

Manter um projeto de longa duração é tanto uma responsabilidade do gerente de projeto quanto um desenvolvedor individual.

As pessoas não introduzem hacks porque gostam; eles são forçados pelas circunstâncias.

2
ViSu

Fiquei surpreso ao descobrir que nenhuma das numerosas respostas destacava o óbvio: faça o software consistir em inúmeras bibliotecas pequenas e independentes. Com muitas bibliotecas pequenas, você pode construir um software grande e complexo. Se os requisitos forem alterados, você não precisará descartar toda a base de códigos ou investigar como modificar uma grande base de códigos de buzinas para fazer algo diferente do que está fazendo atualmente. Você apenas decide quais dessas bibliotecas ainda são relevantes após a alteração dos requisitos e como combiná-las para obter a nova funcionalidade.

Use as técnicas de programação nessas bibliotecas que facilitam o uso da biblioteca. Observe que p. qualquer ponteiro de função de suporte a linguagem não orientada a objetos está suportando realmente programação orientada a objetos (OOP). Então, p. em C, você pode fazer OOP.

Você pode até considerar compartilhar essas bibliotecas pequenas e independentes entre muitos projetos (os submódulos do git são seus amigos).

Escusado será dizer que cada pequena biblioteca independente deve ser testada em unidade. Se uma biblioteca específica não pode ser testada por unidade, você está fazendo algo errado.

Se você usa C ou C++ e não gosta da idéia de ter muitos arquivos .so pequenos, é possível vincular todas as bibliotecas em um arquivo .so maior ou, alternativamente, pode vincular estática. O mesmo vale para Java, basta alterar .so para .jar.

1
juhist

Simples: reduza os custos de manutenção da maior parte do seu código para zero até que você tenha um número sustentável de peças móveis. O código que nunca precisa ser alterado não incorre em custos de manutenção. Eu recomendo que o objetivo de tornar o código realmente tenha zero custo de manutenção, não tentando reduzir o custo em muitas iterações de refatoração pequenas e exigentes. Faça o custo zero imediatamente.

Ok, é verdade que é muito, muito mais difícil do que parece. Mas não é difícil começar. Você pode pegar uma parte da base de código, testá-la, construir uma interface agradável sobre ela se o design da interface estiver uma bagunça e começar a aumentar as partes da base de código que são confiáveis, estáveis ​​(como na falta de motivos para mudar), enquanto simultaneamente encolhendo as partes que não são confiáveis ​​e instáveis. As bases de código que parecem um pesadelo para manter geralmente não distinguem as partes móveis que precisam ser mudadas das partes que não o fazem, pois tudo é considerado não confiável e propenso a mudanças.

Na verdade, eu recomendo separar a organização da sua base de código em partes "estáveis" e "instáveis", com as partes estáveis ​​sendo uma grande PITA para reconstruir e mudar (o que é uma coisa boa, pois elas não precisam alterados e reconstruídos se realmente pertencerem à seção "estável").

Não é do tamanho de uma base de código que dificulta a manutenção. É o tamanho da base de código que precisa ser mantida. Eu dependo de milhões de linhas de código sempre que, digamos, uso a API do sistema operacional. Mas isso não contribui para os custos de manutenção do meu produto, pois não preciso manter o código fonte do sistema operacional. Eu apenas uso o código e funciona. O código que eu apenas uso e nunca preciso manter não incorre em custos de manutenção do meu lado.

0
user204677