Como são mantidas enormes bibliotecas de código aberto, mantendo um código longe das práticas de "código limpo"?

80

Ainda não tenho experiência em escrever código de alta qualidade, por isso leio livros sobre o assunto como o Código Limpo, de Robert C. Martin, e continuo verificando o código de bibliotecas conhecidas para melhorar minhas habilidades.

Embora muitas bibliotecas de código aberto tenham sido mantidas por anos, o que significa que é muito improvável que elas não estejam no caminho certo, eu encontrei o código em muitas delas longe dos princípios abordados para escrever código limpo - por exemplo, métodos que contêm centenas de linhas de código.

Portanto, minha pergunta é: os princípios do código limpo são muito restritos e podemos ficar sem eles em muitas bibliotecas como essas? Caso contrário, como são mantidas enormes bibliotecas sem considerar muitos desses princípios?

Agradeço qualquer breve esclarecimento. Peço desculpas se a pergunta parece ser boba de um novato.

EDITAR

Confira este exemplo na biblioteca Butterknife - uma das bibliotecas mais conhecidas da comunidade Android.

Islam Salah
fonte
71
Você está sofrendo de uma amostra tendenciosa. Você diz que verifica o código das bibliotecas "conhecidas". Bem, as bibliotecas que entraram em colapso devido ao seu próprio peso porque não estavam seguindo as melhores práticas não são "conhecidas", desapareceram na obscuridade.
Jörg W Mittag
3
Você verificou, por exemplo, as fontes Linux?
Restabelecer Monica - M. Schröder
55
A principal medida para o valor de um software não é o quão "limpo" é o código, é o quão bem ele cumpre uma tarefa específica. Enquanto algumas pessoas gostam de escrever software apenas para escrever algo, para a maioria das pessoas, o código é apenas um meio para atingir um fim.
Whatsisname
3
Ninguém discorda de você. A questão é como manter um código ruim por anos? Por que não foi limpo sobre essas muitas iterações de evolução?
Islam Salah
13
A premissa da pergunta (que os projetos de código aberto mantidos há muito tempo devem aderir inerentemente à noção de melhores práticas de um autor de livro) é completamente falsa e não sei de onde você o tirou. Você poderia expandir a premissa da sua pergunta, por favor?
Lightness Races in Orbit

Respostas:

84

Boa resposta aqui já, mas deixe-me dizer uma palavra sobre o seu exemplo de canivete : embora eu não tenha idéia do que o código faz, à primeira vista, ele não me parece realmente insustentável. Os nomes de variáveis ​​e métodos parecem ter sido escolhidos deliberadamente, o código está corretamente recuado e formatado, possui alguns comentários e os métodos longos mostram pelo menos alguma estrutura de blocos.

Sim, de forma alguma segue as regras de "código limpo" do tio Bob, e alguns dos métodos são muito longos (provavelmente toda a classe). Mas, olhando para o código, ainda vejo estrutura suficiente para que eles possam ser "limpos" facilmente, extraindo esses blocos em métodos por conta própria (com baixo risco de introduzir bugs ao usar ferramentas de refatoração).

O verdadeiro problema com esse código é: adicionar um bloco e outro bloco e outro bloco funciona até certo ponto, às vezes ao longo de anos. Mas todos os dias o código fica mais difícil de evoluir um pouco e leva um pouco mais de tempo para modificá-lo e testá-lo. E quando você realmente precisa alterar algo que não pode ser resolvido "adicionando outro bloco", mas requer reestruturação, você desejará que alguém tenha começado a limpar o código mais cedo.

Doc Brown
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Yannis
158

Os princípios declarados em "Código Limpo" nem sempre são geralmente aceitos. A maior parte é de senso comum, mas algumas das opiniões do autor são bastante controversas e não são compartilhadas por todos.

Em particular, a preferência por métodos curtos não é aceita por todos. Se o código em um método mais longo não for repetido em outro lugar, extrair parte dele para um método separado (para que você obtenha vários métodos mais curtos) aumenta a complexidade geral, pois esses métodos agora são visíveis para outros métodos que não deveriam se importar com eles. Portanto, é uma troca, não uma melhoria objetiva.

Os conselhos do livro também são (como todos os conselhos) voltados para um tipo específico de software: aplicativos corporativos. Outros tipos de software, como jogos ou sistemas operacionais, têm restrições diferentes das do software corporativo; portanto, padrões e princípios de design diferentes estão em jogo.

A linguagem também é um fator: o Clean Code assume Java ou uma linguagem semelhante - se você usar C ou Lisp, muitos conselhos não se aplicam.

Em suma, o livro é uma única pessoa opiniões sobre uma determinada classe de software. Não se aplica a todos os lugares.

Quanto aos projetos de código aberto, a qualidade do código varia de péssima a brilhante. Afinal, qualquer pessoa pode publicar seu código como código aberto. Mas se você olhar para um projeto de código aberto maduro e bem-sucedido com vários colaboradores, pode ter certeza de que eles adotaram conscientemente um estilo que funcione para eles. Se esse estilo está em contradição com alguma opinião ou diretriz, então (para ser franco), é a diretriz errada ou irrelevante, pois o código de trabalho supera as opiniões.

JacquesB
fonte
18
+1 para "voltado para um tipo específico de software". Isso pode ser estendido à maioria dos livros sobre esse assunto e tópicos semelhantes. Pegue tudo que você lê com um grão de sal, pois pode ser tendencioso no momento em que é escrito, no ambiente de destino, na metodologia de desenvolvimento e em todos os tipos de outros fatores.
Reginald Blue
16
Seguir esse livro produz estritamente o que muitos chamam de "código de lixo".
115518 Frank Hileman
16
@FrankHileman: seguindo nenhuma das recomendações desse livro ainda mais.
Doc Brown
5
@ jpmc26 - Sua resposta vinculada pertence a um campo que eu estou intimamente familiarizado com a programação científica. Recentemente, recebi um item da lista de desejos, que era tornar o modelo gravitacional usado em várias simulações do Johnson Space Center relativisticamente correto. Contando comentários e linhas em branco, o código que escrevi que calcula a perturbação relativística da gravidade newtoniana tem 145 linhas e tudo em uma única função. Normalmente, eu me arrepiava ao ver que eu mesmo escrevi uma função com 45 linhas, muito menos 145. Mas não neste caso. ...
David Hammen
12
... A função em questão implementa uma única equação, a equação X no jornal Y, portanto segue definitivamente a regra de propósito único. (O fato de a equação cobrir um quarto de página está nos detalhes.) Não há um local significativo para dividir essa função em partes e não há um motivo significativo para fazê-lo. Os comentários, que tio Bob despreza? Eles são absolutamente necessários neste caso, e isso é típico na programação científica. Embora seja bom ver as referências relevantes do diário na documentação do modelo TeX, também é bom vê-las na implementação.
David Hammen
34

Sumário

Como JacquesB escreve, nem todo mundo concorda com o "Código Limpo" de Robert C. Martin.

Os projetos de código aberto que você descobriu estar "violando" os princípios que você esperava provavelmente terão outros princípios.

Minha perspectiva

Por acaso supervisiono várias bases de código que aderem muito aos princípios de Robert C. Martin. No entanto, eu realmente não afirmo que eles estão certos , só posso dizer que eles funcionam bem para nós - e que "nós" é de fato uma combinação de pelo menos

  • o escopo e a arquitetura de nossos produtos,
  • o mercado-alvo / expectativas do cliente,
  • quanto tempo os produtos são mantidos,
  • a metodologia de desenvolvimento que usamos,
  • a estrutura organizacional da nossa empresa e
  • hábitos, opiniões e experiências passadas de nossos desenvolvedores.

Basicamente, isso se resume a: cada equipe (seja uma empresa, um departamento ou um projeto de código aberto) é única. Eles terão prioridades e pontos de vista diferentes e, é claro, farão trocas diferentes. Essas compensações e o estilo de código em que resultam são em grande parte uma questão de gosto e não pode ser provado "errado" ou "certo". As equipes só podem dizer "fazemos isso porque funciona para nós" ou "devemos mudar isso porque não funciona para nós".

Dito isto, acredito que, para manter com êxito grandes bases de códigos ao longo dos anos, cada equipe deve concordar com um conjunto de convenções de códigos que julgar adequadas para os aspectos mencionados acima. Isso pode significar adotar práticas de Robert C. Martin, de outro autor, ou inventar suas próprias; pode significar anotá-las formalmente ou documentá-las "por exemplo". Mas eles deveriam existir.

Exemplo

Considere a prática de "dividir o código de um método longo em vários métodos particulares".

Robert C. Martin diz que este estilo permite limitar o conteúdo de cada método para um nível de abstração - como um exemplo simplificado, um método público provavelmente só consistem em chamadas para métodos privados como verifyInput(...), loadDataFromHardDisk(...), transformDataToJson(...)e, finalmente sendJsonToClient(...), e esses métodos teriam os detalhes da implementação.

  • Algumas pessoas gostam disso porque os leitores podem obter uma visão geral rápida das etapas de alto nível e podem escolher quais detalhes desejam ler.
  • Algumas pessoas não gostam disso porque, quando você deseja conhecer todos os detalhes, é necessário pular na classe para acompanhar o fluxo de execução (é a isso que JacquesB provavelmente se refere quando escreve sobre adicionar complexidade).

A lição é: todos estão certos, porque têm direito a uma opinião.

Jens Bannmann
fonte
13

De fato, muitas bibliotecas de código aberto sofrem com práticas de codificação objetivamente ruins e são mantidas com dificuldade por um pequeno grupo de colaboradores de longo prazo que podem lidar com a baixa legibilidade porque estão familiarizados com as partes do código que mantêm com mais freqüência. . A refatoração do código para melhorar a legibilidade após o fato geralmente é um esforço hercúlea, porque todo mundo precisa estar na mesma página, não é divertido e não vale a pena, porque nenhum novo recurso foi implementado.

Como já foi dito, qualquer livro sobre código limpo indicando algo necessariamente contém conselhos que não são universalmente aceitos. Em particular, quase qualquer regra pode ser seguida com zelo excessivo, substituindo um problema de legibilidade por outro.

Pessoalmente, evito criar funções nomeadas se não tiver um bom nome para elas. E um bom nome deve ser curto e descrever fielmente o que a função faz ao mundo exterior. Isso também está relacionado à tentativa de ter o menor número possível de argumentos de função e nenhum dado gravável globalmente. Tentar reduzir uma função muito complexa para funções menores geralmente resulta em longas listas de argumentos quando a função era genuinamente complexa. Criar e manter código legível é um exercício de equilíbrio entre regras de senso comum mutuamente conflitantes. A leitura de livros é boa, mas apenas a experiência o ensinará a encontrar falsa complexidade , que é onde os ganhos reais de legibilidade são obtidos.

Kafein
fonte
2
Eu acrescentaria: simplesmente porque algo é "código aberto" não significa que apenas alguém é um colaborador. Muitas vezes, muitos projetos de código aberto são mantidos por panelinhas, para o bem ou para o mal, que isolam o projeto de outros colaboradores - e, a menos que seja bifurcado, ninguém mais contribui. Se ele não for bifurcado, seja porque ninguém precisa modificá-lo ou porque ninguém pode entender como, então o estilo convencional do código provavelmente permanecerá inalterado.
Can-ned_food
7

A maioria dos projetos de código aberto é mal gerenciada. Obviamente, há exceções a isso, mas você encontrará muitas porcarias no mundo de código aberto.

Isso não é uma crítica de todos os proprietários / gerentes de projetos cujos projetos eu estou falando, é simplesmente uma questão de tempo usado. Essas pessoas têm coisas melhores para fazer com seu tempo, como seu trabalho remunerado.

No começo, o código é obra de uma pessoa e provavelmente é pequeno. E código pequeno não precisa ser limpo. Ou melhor, o esforço necessário para tornar o código limpo é maior que o benefício.

Com o passar do tempo, o código é mais uma pilha de patches por muitas pessoas diferentes. Os criadores de patches não sentem a propriedade do código, apenas querem que esse recurso seja adicionado ou que esse bug seja corrigido da maneira mais fácil possível.

O proprietário não tem tempo para limpar as coisas e ninguém mais se importa.

E o código está ficando grande. E feio.

À medida que fica cada vez mais difícil encontrar o caminho do código, as pessoas começam a adicionar recursos no lugar errado. E, em vez de corrigir bugs, eles adicionam soluções alternativas para outros lugares no código.

Neste ponto, não é apenas o fato de as pessoas não se importarem, elas não ousam mais se limpar, pois têm medo de quebrar as coisas.

Já tive pessoas descrevendo bases de código como "punição cruel e incomum".

Minhas experiências pessoais não são tão ruins, mas já vi algumas coisas muito estranhas.

Stig Hemmer
fonte
23
Se você eliminar as palavras "aberto" e "fonte" nesta resposta, continuará a ser verdade.
Stephen M. Webb
Eu diria que isso é igualmente verdade para o software de código fechado.
Mark Rotteveel
3

Parece-me que você está perguntando como essas coisas funcionam se ninguém está fazendo o que deveria estar fazendo. E se funcionar, por que deveríamos estar fazendo essas coisas ?

A resposta, IMHO, é que funciona "suficientemente bom" , também conhecido como a filosofia " pior é melhor " . Basicamente, apesar da história difícil entre código aberto e Bill Gates, os dois adotaram de fato a mesma idéia: a maioria das pessoas se preocupa com recursos, não com bugs .

Isto, claro, também nos leva a " normalização do desvio " o que leva a situações como heartbleed , onde, precisamente como se para responder sua pergunta, um maciço, coberto pilha spaghetti de código-fonte aberto chamado OpenSSL foi " limpar " para algo como dez anos , acabando com uma enorme falha de segurança que afeta milhares de milhões de pessoas .

A solução foi inventar um sistema totalmente novo chamado LibreSSL , que usaria código clean-ish e, é claro, quase ninguém o usa .

Então, como são mantidos grandes projetos de código aberto mal codificados? A resposta está na pergunta. Muitos deles não são mantidos em um estado limpo. Eles são corrigidos aleatoriamente por milhares de pessoas diferentes para cobrir casos de uso em várias máquinas e situações estranhas nas quais os desenvolvedores nunca terão acesso para testar. O código funciona "bom o suficiente" até que não funcione , quando todos entram em pânico e decidem jogar dinheiro com o problema .

Então, por que você deveria se incomodar em fazer algo ' do jeito certo ' se ninguém mais está?

A resposta é que você não deveria. Você faz ou não , e o mundo continua girando independentemente, porque a natureza humana não muda na escala de uma vida humana . Pessoalmente, apenas tento escrever código limpo porque gosto da maneira como é fazê-lo.

não brilhante
fonte
1
Tantos links ... à primeira vista, pensei que essa resposta poderia ter sido associada à publicidade instantânea ou que era uma página da Wikipedia.
9139 Jonny Henly
2

O que constitui um bom código depende do contexto, e os livros clássicos que o orientam são, se não velhos demais para discutir código aberto, pelo menos parte de uma tradição travando a guerra sem fim contra bases de código internas ruins. Portanto, é fácil ignorar o fato de que as bibliotecas têm objetivos completamente diferentes e são escritas de acordo. Considere os seguintes problemas, em nenhuma ordem específica:

  • Quando importo uma biblioteca, ou de uma biblioteca, provavelmente não sou especialista em sua estrutura interna para saber exatamente qual minúscula fração de seu kit de ferramentas preciso para o que estiver trabalhando, a menos que esteja copiando A resposta do Stack Exchange me disse para fazer. Então eu começo a digitar from A import(se estiver em Python, digamos) e vejo o que aparece. Mas isso significa que o que vejo listado precisa refletir as tarefas lógicas que precisarei emprestar, e é isso que deve estar na base de código. Inúmeros métodos auxiliares que o tornam mais curto apenas me confundem.
  • As bibliotecas estão lá para o programador mais inexperiente que tenta usar algum algoritmo que a maioria das pessoas ouviu apenas vagamente. Eles precisam de documentação externa, e isso precisa refletir com precisão o código, o que não pode ser feito se continuarmos refatorando tudo para tornar felizes os aderentes ao método curto e ao fazer uma coisa.
  • Todo método de biblioteca que as pessoas emprestam pode quebrar o código em todo o mundo com conseqüências desastrosas se for retirado ou mesmo renomeado. Claro, eu gostaria que o sklearn corrigisse o erro de digitação em Calinski-Harabasz , mas isso poderia causar outro incidente no teclado esquerdo . De fato, na minha experiência, o maior problema com a evolução da biblioteca é quando eles se esforçam demais para adotar uma nova "melhoria" de código bom na forma como estruturam tudo.
  • Internamente, os comentários são em grande parte um mal necessário, na melhor das hipóteses, por todas as razões pelas quais não preciso me regurgitar (embora esses pontos exagerem um pouco). Um bom comentário diz por que o código funciona, não como. Mas as bibliotecas sabem que seus leitores são programadores competentes que não poderiam, digamos, escrever álgebra linear a uma saída de um saco de papel. Em outras palavras, tudo precisa ser comentado: por que funciona! (OK, isso é outro exagero.) É por isso que você vê a linha de assinatura, o bloco de comentários de 100 linhas, uma linha de código que poderia literalmente ter entrado na linha de assinatura (se o idioma permitir, é claro).
  • Digamos que você atualize algo no Github e aguarde para ver se seu código será aceito. Deve ficar claro por que sua alteração de código funciona. Por experiência, sei que a refatoração para tornar o parque de campismo mais limpo como parte de uma confirmação funcional muitas vezes significa muita economia de linha, reorganização e renomeação, o que dificulta o trabalho do revisor sem salário e causa outros problemas acima mencionados.

Tenho certeza de que pessoas com mais experiência do que eu podem mencionar outros pontos.

JG
fonte
Sobre o primeiro ponto. É por isso que você tem métodos públicos / privados. Você expõe a API pública que chama internamente métodos privados ou internos. O segundo ponto também é impreciso. Não vejo razão para que você não possa ter documentação sobre um método público curto e depois chame muitos métodos pequenos.
12128 FCin
@FCin Essa é a abordagem viável, desde que os mantenedores se lembrem de sempre usar a palavra-chave correta na frente de cada método, conforme eles vão e vêm. Ou eles poderiam simplesmente fazer algo mais fácil e menos propenso a erros.
JG
Em linguagens como C #, Java (sobre a qual o tio Bob costuma falar), os modificadores de acesso são a ferramenta mais básica usada para escrever realmente qualquer código. Usar a palavra-chave correta faz parte da escrita de qualquer código.
FC 12/07
@FCin Eles são explicados com menos frequência em outros idiomas, mas eu trabalhei até em bases de código C # internas, onde as pessoas não necessariamente usavam os modificadores que deveriam ter.
JG:
É por isso que eles devem ler o livro do Tio Bob :)
FCin
2

Já existem muitas respostas boas - quero dar a perspectiva de um mantenedor de código aberto.

Minha perspectiva

Sou mantenedor de muitos desses projetos com menos do que um ótimo código. Em algum momento, sou impedido de melhorar esse código devido a preocupações de compatibilidade, pois as bibliotecas são baixadas milhões de vezes por semana.

Isso torna a manutenção mais difícil - como membro principal do Node.js., há partes do código que receio tocar, mas há muito trabalho a ser feito independentemente, e as pessoas usam a plataforma com êxito e se divertem. O mais importante é que funcione.

No código legível

Quando voce diz:

Eu encontrei o código em muitos deles longe dos princípios abordados para escrever código limpo - por exemplo, métodos contendo centenas de linhas de código.

Linhas de código não são uma grande medida de quão legível é. No estudo que vinculei ao kernel do linux, foi analisado e uma pesquisa com programadores encontrou um código "regular" (código que as pessoas esperam basicamente) e um código consistente melhor do que o código "limpo" na compreensibilidade. Isso também se alinha à minha experiência pessoal.

Alguns projetos de código aberto não são muito acolhedores

Linus "notoriamente" disse que o linux não deveria ter um depurador embutido porque as pessoas que usam depuradores não são boas o suficiente para trabalhar no linux e ele não deseja atrair mais deles.

Pessoalmente, discordo totalmente de sua posição lá - mas também é algo que as pessoas fazem.

Benjamin Gruenbaum
fonte
1

Software de código aberto não significa necessariamente que vários autores estejam envolvidos. Quando um software (ou unidade de software) é escrito por um único autor, funções longas aparecem com freqüência.

Isso vem da natureza do processo de desenvolvimento. Um método simples é estendido ao longo do tempo, novos recursos são adicionados e corrigidos.

Métodos longos reduzem severamente o entendimento da funcionalidade para novos autores. No entanto, com um único autor, isso raramente é um problema e o problema tende a ser esquecido. Outra natureza do código aberto é o fato de que muitos softwares não são desenvolvidos ativamente; portanto, não há trabalho de refatoração que, por exemplo, dividisse métodos complexos em vários métodos simples.

Você não mostrou nenhum exemplo, mas, pelo que entendi, isso também está freqüentemente conectado à linguagem de desenvolvimento. Alguns idiomas aplicam regras estritas de aprendizado desde o início e testes de unidade pesados ​​(ou mesmo TDD). Testes de fiapos e de unidade geralmente evitam esse problema (é difícil testar métodos complexos / longos).

Em geral, é mais difícil limpar o código se o software for desenvolvido por um único autor e outros contribuintes estiverem corrigindo apenas pequenos problemas.

Sulthan
fonte