Ultimamente, tenho tentado me lembrar do seguinte fato.
Por um lado, há uma série de diretrizes e padrões de codificação para o que é considerado código "saudável", "limpo", "bem escrito" e assim por diante. Veja o "Código Limpo" que parece ser amplamente discutido aqui também. Regra de exemplo: métodos de 7 linhas e 1 ou 2 níveis de indentação. De alguma forma, espera-se que o código que não segue morra de baixa manutenção.
Por outro lado, trabalho com OpenCV, OpenCascade, VTK, etc. É um código científico. Eles têm métodos de 2 páginas (sen eu mesmo), o OpenCascade possui um método ou uma classe dividida em 10 arquivos (sem brincadeiras aqui), o VTK também é uma bagunça às vezes. No entanto, esses projetos prosperam, são mantidos e amplamente utilizados!
Onde está o problema? Temos permissão para escrever códigos científicos e com muita matemática de uma maneira que funcione, e podemos mantê-lo? Existe um conjunto separado de padrões para esses projetos, se houver?
Pode ser uma pergunta ingênua, mas estou no que parece ser um vazio de programação, tentando criar um conjunto de regras sobre como fazer e não fazer as coisas, que é a maneira como fui ensinado a trabalhar no ensino médio. Desde que me formei, quase não tive apoio de diretrizes com as coisas que tive que fazer, principalmente a programação - ninguém se incomoda em ensinar isso.
fonte
Respostas:
Não, não é.
O código de pesquisa geralmente é "descartado" e escrito por pessoas que não são desenvolvedores por experiência, por mais fortes que sejam suas credenciais acadêmicas. Alguns dos códigos de pesquisa que escrevi me faziam chorar . Mas funcionou!
Uma coisa a considerar é que os porteiros dos projetos conduzem o que é incluído. Se um grande projeto começou como um projeto de código acadêmico / de pesquisa, acaba funcionando e agora está uma bagunça, alguém precisa tomar a iniciativa de refatorá-lo.
É preciso muito trabalho para refatorar o código existente que não está causando problemas. Especialmente se for de todo o domínio específico ou não tiver testes. Você verá que o OpenCV possui um guia de estilo muito abrangente, mesmo que não seja perfeito. Aplicando isso retroativamente a todo o código existente? Isso não é para os fracos de coração.
Isso é ainda mais difícil se todo esse código funcionar. Porque não está quebrado. Por que consertar isso?
Esta é a resposta, em certo sentido. O código de trabalho ainda é útil e, portanto, é mais provável que seja mantido.
Pode ser uma bagunça, especialmente inicialmente. Alguns desses projetos provavelmente começaram como um projeto único que "nunca precisaria ser reutilizado e poderia ser jogado fora".
Considere também que, se você estiver implementando um algoritmo complexo, pode fazer mais sentido ter métodos maiores, pois você (e outras pessoas familiarizadas com o lado científico) pode conceitualmente entender melhor o algoritmo. Meu trabalho de tese foi relacionado à otimização. Ter a lógica do algoritmo principal como um método era consideravelmente mais fácil de entender do que estaria tentando separá-lo. Certamente violou a regra "7 linhas por método", mas também significou que outro pesquisador poderia examinar meu código e entender mais rapidamente minhas modificações no algoritmo.
Se essa implementação fosse abstraída e projetada bem, essa transparência seria perdida para não programadores .
Eu acho que as pessoas geralmente têm a idéia de que todos os projetos de código aberto começam como "ei, eu tenho uma ótima idéia para uma biblioteca que será muito popular e usada por milhares / milhões de outras pessoas" e, em seguida, todo projeto acontece assim.
A realidade é que muitos projetos são iniciados e morrem. Uma porcentagem ridiculamente pequena de projetos "chega" ao nível do OpenCV ou VTK etc.
O OpenCV começou como um projeto de pesquisa da Intel. A Wikipedia descreve como parte de uma "série de projetos". Seu primeiro lançamento não beta foi em 2006, ou sete anos após o início. Suspeito que o objetivo inicialmente era versões beta significativas, não código perfeito.
Além disso, a "propriedade" do OpenCV mudou significativamente. Isso faz com que os padrões mudem, a menos que todas as partes responsáveis adotem exatamente os mesmos padrões e os mantenham durante o projeto.
Devo também salientar que o OpenCV já existia há vários anos antes da publicação do Manifesto Ágil, a partir do qual o Clean Code se inspira (e o VTK quase 10). O VTK foi iniciado 17 anos antes da publicação do Clean Code (o OpenCV era "apenas" 9 anos antes).
fonte
Os cientistas não são desenvolvedores. O trabalho deles não é escrever código por si só. O trabalho deles é resolver problemas, e a programação é apenas uma das ferramentas que eles podem usar.
A maioria dos códigos empresariais criados por desenvolvedores profissionais, como eles se autodenominariam, é uma bagunça. A maior parte desse código não usa padrões de design ou os utiliza incorretamente. A maioria dos comentários é candidata ao TheDailyWTF . Portanto, como em nosso próprio setor, vemos resultados de pessoas cujo trabalho é escrever código, o que você esperaria de pessoas cujo trabalho não é escrever programas?
Todas as práticas que um desenvolvedor profissional real aprende durante sua carreira beneficiariam um cientista? Absolutamente. Seria possível para todo cientista passar de cinco a dez anos de sua vida aprendendo o desenvolvimento de software? Provavelmente não. Portanto, a qualidade do código é como é.
Outro fator é a cultura. Se seus pares não escrevem código limpo, por que você faria? Como ninguém se importa, você não está realmente disposto a fazer um esforço extra.
Finalmente, a maioria dos códigos científicos tem uma vida útil relativamente curta. Você escreve o código para uma pesquisa específica e, quando a pesquisa é concluída, você não o reutiliza. Depois de adquirir esse hábito, é difícil fazer a diferença entre bibliotecas reutilizáveis, como as que você cita e o código descartável.
fonte
Ignorar? Não. Re-considerar e ajustar? Certo. Muitos códigos científicos exigem muita matemática e são críticos para o desempenho. Coisas como a sobrecarga de chamadas de função podem realmente se tornar um problema; portanto, você pode acabar com estruturas mais profundamente aninhadas do que em um aplicativo comercial típico. Isso não significa que você deve mergulhar de cabeça em mil micro-otimizações. Você ainda deve se concentrar em escolher o algoritmo certo e fazer otimizações apenas cujos efeitos você pode medir.
Algumas das diferenças são óbvias e triviais. As diretrizes de codificação normalmente exigem a escolha de nomes significativos de variáveis e nomes com uma única letra serão imediatamente suspeitos. Um aplicativo científico ainda desejará nomes de variáveis significativos, mas às vezes o nome mais significativo será uma única letra, referindo-se a uma variável em uma equação conhecida.
fonte
Aj
eT0
porque é assim que as variáveis foram nomeadas nas funções que eu estava traduzindo para código. Usando algo comocorrelationIndex
oustartTime
você iria se queixar.Todas as respostas existentes abordaram essa questão de forma abrangente. No entanto, gostaria de salientar qual é o verdadeiro antípoda entre os gostos do OpenCV etc., versus, digamos, o código desenvolvido de acordo com as boas práticas de negócios (código completo, código limpo, SOLID, etc.)
Em geral, há muitos benefícios comerciais para o código-fonte ser o KISS - "mantenha as coisas simples, estúpidas". Há também um YAGNI relacionado - "Você não vai precisar".
Infelizmente, para softwares intensivos em computação nos domínios científicos, o código-fonte raramente é simples ou enxuto .
Tradicionalmente, o OpenCV sofria de falta de generalizações (muita duplicação de código para suportar opções diferentes), enquanto o VTK sofria de generalizações excessivas (modelos).
Nos primeiros dias, certas partes do OpenCV foram originalmente desenvolvidas em C. Mais tarde, o OpenCV adotou a API C ++ que conhecemos hoje. Alguns algoritmos são reescritos para aproveitar as interfaces C ++ (classes base abstratas) e modelos C ++. Outros algoritmos eram simplesmente invólucros para o código C original. Restos desse código podem ser encontrados espalhados no módulo "imgproc".
O OpenCV contém muita programação SIMD (vetorização). Até essa data, a programação SIMD em C ++ ainda requer o uso de intrínsecas (intel.com) , (arm.com) .
Os intrínsecos do SIMD são parecidos com a linguagem assembly, exceto que o compilador cuida da atribuição de registro de variáveis e o compilador tem liberdade para trocar a ordem das instruções por ganhos de desempenho. Os algoritmos escritos para usar intrínsecos do SIMD tiveram um alto custo de manutenção. Foi por isso que mencionei uma pergunta que fiz anteriormente - Custo de manutenção da base de código de programação SIMD .
Uma pessoa que não está fazendo programação SIMD pode facilmente ser levada a acreditar que o SIMD pode ser encapsulado de maneira elegante e que a programação SIMD de baixo nível não deve mais ser necessária. Isso é realmente muito longe da verdade. Desafio qualquer um a tentar implementar um algoritmo útil no SIMD (não fractais) e ver a dificuldade de uso nesses encapsulamentos propostos.
Abaixo está uma longa lista de idéias quando tento analisar por que o software computacional não pode ser o KISS ou o YAGNI. No entanto, todas essas idéias são generalizações excessivas e parecem não apoiar a observação acima.
Os principais fatores contribuintes são:
Vários dos fatores contribuintes acima são antípodas no desenvolvimento de software comercial:
fonte
Depende do que você chama de "padrões comuns de codificação". Eu não chamaria os extremos de Agile de "comuns". Em particular, considerar uma função com oito linhas muito longa ou com mais de dois níveis de indentação muito complexa são padrões ridículos no campo da programação numérica / científica.
Uma função de matriz de tempos de matriz muito simples tem mais de sete linhas e possui três níveis de recuo. A função se tornará consideravelmente mais complexa do que se deveria se preocupar com eficiência. Essa é uma operação tão comum que a eficiência é importante. Quebrá-lo em pedaços é exatamente o que você não quer fazer. Uma decomposição da matriz será ainda mais complexa.
fonte
Decidi postar isso como uma nova resposta, porque é uma perspectiva completamente diferente.
Vamos dar uma olhada em um exemplo de código que considero "código limpo" em termos de visão por computador e entendimento de imagem:
https://github.com/opencv/opencv/blob/05b15943d6a42c99e5f921b7dbaa8323f3c042c6/modules/photo/src/seamless_cloning_impl.cpp
Para aqueles familiarizados com MATLAB e computação científica, o código em C ++ é quase tão conciso quanto o código MATLAB mais limpo possível.
Agora temos que perguntar: por que toda a base de código da biblioteca (OpenCV neste exemplo) não é gravada no mesmo padrão que essa amostra de código?
Devemos estratificar a base de código de uma grande biblioteca científica em níveis de abstração .
No nível baixo , você está literalmente reimplementando adições e subtrações. Ou, literalmente, re-mapeando cada operação para as implementações mais rápidas em cada plataforma.
https://github.com/opencv/opencv/blob/master/modules/core/src/hal_replacement.hpp
O nível intermediário é onde encontramos o código "mais sujo", no qual são gastos entre 80% e 90% do tempo de execução da CPU. (Da mesma forma, talvez 80% - 90% do esforço de desenvolvimento foram gastos no nível intermediário, se considerarmos separadamente os esforços de desenvolvimento de software da pesquisa científica.)
No alto nível , temos o código mais limpo, escrito por pesquisadores.
É necessária uma forte excelência na organização do código-fonte para garantir que esses níveis não se misturem. Isso está além dos padrões de codificação , mais tem a ver com administração de código aberto .
Por exemplo, às vezes é tomada a decisão de dividir um projeto de código aberto em dois. Você não pode fazer essas coisas acontecerem por confirmações de código.
fonte