Por que é ruim escrever algo na linguagem X como se você estivesse escrevendo um programa na linguagem Y em termos de uso de um paradigma de codificação compartilhado?

25

Há um tempo atrás, fiz uma pergunta no SO sobre algo escrito em C ++, mas, em vez de obter uma resposta para o problema em questão, os comentários enlouqueceram no meu estilo de codificação, mesmo quando indiquei que era um código WIP e que pretendia limpá-lo mais tarde, quando o gabinete básico estivesse funcionando. (Eu recebi tantos votos negativos que decidi fazer a pergunta, pois meu representante no SO já é quase abismal)

Isso me fez pensar por que as pessoas adotam uma atitude tão rígida de "você é um noob, vá se foder". Eu estava sendo acusado de escrever C ++ como se fosse Java. Algo que não consigo entender e que ainda me deixa perplexo.

Eu tenho programado em algumas linguagens OOP há vários anos, embora em intervalos. Eu escolhi o idioma a ser usado em termos de bibliotecas disponíveis e ambientes ideais de execução para o trabalho em questão. Adoto padrões de design no código OOP e estou bastante confiante de que meu uso de padrões é sólido e que, em termos de OO, posso me manter. Entendo a caixa de ferramentas OOP, mas optei por usá-las somente quando acho que é realmente necessário, e não apenas usar um truque para mostrar meu raciocínio de codificação. (Que eu sei que não são de primeira qualidade, mas acho que também não estão no nível n00b).

Eu projeto meu código antes de escrever uma única linha. Para definir testes, listo os objetivos de uma determinada classe e os critérios de teste aos quais ela deve aderir. Como é mais fácil criar diagramas de sequência e depois escrever código, escolhi escrever meus testes depois que a interface se tornou óbvia.

Devo admitir que, no trecho de código que postei na pergunta, eu ainda estava usando ponteiros, em vez de usar ponteiros inteligentes. Eu uso RAII sempre que posso. Sei que RAII adequado significa proteção contra ponteiros nulos, mas trabalho de forma incremental. Era um trabalho em andamento e pretendia limpá-lo mais tarde. Essa maneira de trabalhar foi fortemente condenada.

Na minha opinião, eu deveria ter um exemplo de trabalho primeiro para poder ver se o caso base é uma maneira viável de pensar. Também acho que limpar o código é algo típico da fase de refatoração do ágil, após a comprovação do caso base. Devo admitir que, embora esteja adquirindo lentamente o padrão Cxx, prefiro usar o que entendo, em vez de correr o risco de usar conceitos que ainda não dominei no código de produção. Eu tento coisas novas de vez em quando, mas geralmente em projetos que tenho ao lado, apenas para esse fim.

[editar] Gostaria de esclarecer que a sugestão do mosquito [1] não apareceu na pesquisa que fiz antes de começar a fazer minha pergunta. No entanto, embora sua sugestão cubra um aspecto da pergunta, a pergunta a que ele se vinculou não responde ao cerne da minha pergunta, apenas parte dela. Minha pergunta é mais sobre a resposta que cheguei ao meu estilo de codificação e os aspectos profissionais de lidar com diferentes estilos de codificação e níveis (aparentes) de habilidade. Com a minha pergunta anterior sobre SO e sua resposta como um caso em questão. [/editar]

A questão então é: por que zombar de alguém que não usa seu estilo de codificação?

Os assuntos / subdivisões em questão para mim são:

  • Por que seria uma prática ruim de programação usar mais código propenso a erros em situações de protótipo, se a refatoração o tornar mais robusto posteriormente?
  • Como o programa escrito em C ++ seria como se estivesse escrito em Java? O que o torna um programa ruim (considerando que eu indiquei a intenção do estilo atual e o trabalho planejado para melhorar?)
  • Como eu seria um péssimo profissional se eu escolhesse usar um construto usado em um certo paradigma de programação (por exemplo, OOP / DP)?

[1] Desenvolva rápido e com bugs, corrija erros ou seja lento, tenha cuidado com cada linha de código?

Onno
fonte
5
Talvez seja melhor fazer essa pergunta às pessoas do The C ++ Lounge. Coloque seu traje à prova de fogo primeiro.
Robert Harvey
48
O pessoal de C ++ é uma raça incomum entre os programadores. Seu kit de ferramentas Java é uma caixa de ferramentas sensata e bem compreendida, com ferramentas familiares em um estojo de couro acolchoado que funcionará em qualquer loja de ferramentas. O C ++ é um conjunto completo de ferramentas com uma serra de fita, uma furadeira elétrica e algumas ferramentas que ninguém reconhece, todas as quais o público do C ++ pode lidar como ninjas. Isso os aflige quando alguém entra e coloca alguma ferramenta de volta na prateleira no lugar errado. Eles são a "medida duas vezes, corte uma vez" dos programadores.
Robert Harvey
13
Talvez seja a mesma reação que você teria ao código Java que foi escrito como FORTRAN: todo código em uma única classe, sem coleções, apenas matrizes de tamanho fixo, com intvariáveis separadas para acompanhar o tamanho real.
precisa
14
Se você escrever C ++ como Java, provavelmente terá muitas alocações de heap, o que fará com que seu programa tenha um desempenho pior do que poderia. Os idiomas tendem a ser projetados e otimizados para promover certos padrões e, se você os quebrar, as coisas tenderão a piorar para você.
Gort the Robot
5
Você postou o código on-line para obter alguma forma de ajuda. Sei que você não queria / esperava todo o feedback sobre o seu estilo, mas prefere não ter ajuda? Você toma o bem com o mau. Os programadores precisam procurar falhas no código; é o que fazemos.
JeffO 26/03

Respostas:

26

Sem ver o código em questão, existem algumas maneiras de escrever código Java em C ++, algumas piores que outras.

  1. Por um lado, há um layout de sua fonte como Java: tudo em um arquivo, tudo dentro da definição de classe, etc .:
    class HelloWorldApp {
    public:
        void main() {
            cout << "Hello World!" << endl;
        }
    };
    É assim que a fonte Java seria apresentada. É tecnicamente legal em C ++, mas colocar tudo no arquivo de cabeçalho e tudo em linha (definindo-o na declaração de classe) é um estilo terrível e prejudica seu desempenho de compilação. Não faça isso.
  2. Excessivamente OO - Para simplificar demais, em Java, é o Reino dos Substantivos , onde tudo é um objeto. Um bom código C ++ (idiomático) tem mais probabilidade de usar funções, modelos etc. gratuitos, em vez de tentar colocar tudo em um objeto.
  3. Não RAII - Você já mencionou isso - usando ponteiros e limpeza manual em vez de ponteiros inteligentes. O C ++ fornece ferramentas como RAII e ponteiros inteligentes; portanto, um código C ++ bom (ou seja, idiomático) usa essas ferramentas.
  4. Sem C ++ avançado - Os conceitos básicos de Java e C ++ são semelhantes o suficiente, mas depois que você entra em recursos mais avançados (modelos, biblioteca de algoritmos do C ++, etc.), eles começam a divergir.

Exceto o número 1, nenhum deles torna um programa C ++ um programa ruim, mas também não é o tipo de código que eu prefiro trabalhar como programador C ++. (Eu também não gostaria de trabalhar com Perl não idiomático ou de estilo C, Python não idiomático, etc.) Uma linguagem tem suas próprias ferramentas, expressões e filosofia, e um bom código usa essas ferramentas e expressões em vez de tentar usar o menor denominador comum ou tentando reproduzir a abordagem de outro idioma. Escrever código não-idiomático em um determinado idioma / domínio do problema / o que não faz de alguém um programador ruim, significa apenas que eles têm mais a aprender sobre esse idioma / domínio do problema / o que for. E não há nada de errado nisso; há uma lista muito longa de coisas que tenho mais a aprender e o C ++, em particular, tem uma tonelada absoluta de coisas para aprender.

Em relação à questão específica de escrever código propenso a erros com a intenção de limpá-lo mais tarde, não é preto e branco:

  • Se algum código de protótipo falhar em lidar com todas as exceções possíveis e todos os casos possíveis, então isso é esperado. Faça com que funcione e, em seguida, faça-o funcionar de maneira robusta. Sem problemas.
  • Se algum código de protótipo for escrito com o que é simplesmente um estilo ruim ou um design ruim (ruim para o idioma especificado e seus idiomas, um design fundamentalmente ruim para o problema etc.), a menos que você o escreva como descartável prova de conceito, você não está ganhando nada.

Para usar ponteiros brutos versus ponteiros inteligentes como exemplo, se você estiver trabalhando em C ++, usar RAII e ponteiros inteligentes é fundamental o suficiente para que seja mais rápido escrever código dessa maneira do que voltar e limpá-lo mais tarde. Novamente, deixar de fazer isso não significa que alguém seja um programador ruim, não profissional, etc., mas significa que há mais a aprender.

Josh Kelley
fonte
11
existe perl idiomático?
catraca aberração
21
@Onno Quando você pergunta "Como martelo este parafuso na parede sem que ele se dobre?" todos dirão para você não usar um martelo.
precisa
9
@Onno Em C ++, ponteiros e newsão considerados as ferramentas elétricas. O armazenamento automático é a ferramenta manual.
precisa
9
@Onno: Você precisa perceber que os cursos de programação em C ++ tendem a atrasar na adoção de idiomas modernos e o que é considerado bom em C ++ também evoluiu enormemente desde que o C ++ foi inventado.
Bart van Ingen Schenau 26/03
7
Devido à história do C ++, e ao grande número de codificadores que aprenderam o idioma antes que muitos dos recursos mais avançados do idioma aparecessem, há muitos C ++ ruins por aí ainda sendo escritos por pessoas que escrevem como escreveram uma década atrás. A delicadeza em relação a coisas como RAII é fazer com que todos usem os métodos modernos para que possamos parar de ver as mesmas falhas previsíveis.
Gort the Robot
42

Cada linguagem de programação possui um conjunto de idiomas e práticas recomendadas, que geralmente levam a um código elegante, correto e com bom desempenho. Aqui estão algumas das piores práticas perfeitamente bem em outro idioma:

  • Vou gritar se você escrever for ($i = 0; $i < 42; $i++) { … }em Perl, mas não em PHP
    (no Perl, as variáveis ​​devem ser declaradas e esses loops devem percorrer um intervalo)
  • Vou chorar se você escrever new Foo()em C ++ sem uma boa razão, mas não em Java
    (o C ++ não possui coleta de lixo, portanto, o RAII deve ser usado. Noobs vazarão memória caso contrário)
  • Vou me arrepiar se você declarar todas as suas variáveis ​​no topo de sua função, exceto em C89, Pascal ou JavaScript.
  • Vou enfrentar facepalm se você colocar todas as suas funções em uma classe em Python, mas não em Java
    (Python é uma linguagem de paradigma múltiplo, forçando "OOP" e suporta funções de nível superior)
  • Vou chorar se você estiver return nullem Scala, mas não em nenhum idioma semelhante ao C
    (porque Scala tem umOption tipo)
  • Vou reclamar se você escrever um algoritmo recursivo em Java, mas não no OCaml
    (porque a pilha do Java transborda rapidamente, enquanto o OCaml possui otimização de chamada de cauda)
  • ...

É fácil usar um novo idioma como se fosse algo que você conhece e, com sorte, até funcionará. "Você pode escrever o Fortran em qualquer idioma". Mas você realmente não deseja ignorar os recursos específicos que o idioma X oferece, porque há boas chances de o X oferecer alguma vantagem sobre o U.

Escolho o idioma a ser usado em termos de bibliotecas disponíveis e ambientes ideais de execução para o trabalho em questão ” - mas se esse idioma X é realmente melhor que o idioma U para o trabalho em mãos também depende de quão familiarizado com esse idioma, ou quanto tempo levará para se familiarizar o suficiente para usá-lo bem. Você não produziria uma motosserra pesada apenas porque corta a madeira mais rapidamente, quando você realmente quer sua velha caneta porque ela se encaixa perfeitamente na sua mão. A menos que você queira realmente derrubar uma árvore.

Mas sua pergunta é mais sobre uma questão cultural : aprender todas as melhores práticas leva muito tempo e os novatos fazem mais perguntas, enquanto os gurus as respondem. Mas o que é óbvio para um guru não é óbvio para um novato, e os gurus às vezes esquecem isso. Como um novato, a solução não é parar de fazer perguntas. No entanto, é possível mostrar uma abertura para aprender e aplicar as melhores práticas, por exemplo, tentando limpar o seu código o máximo possível antes de mostrá-lo a outras pessoas. A maioria dos idiomas possui algumas práticas recomendadas básicas fáceis de aprender, mesmo quando toda a curva de aprendizado é realmente muito longa.

Um problema comum é que as pessoas novas na programação desconsideram qualquer recuo ou outra formatação e ficam confusas porque o programa não funciona. Eu também ficaria confuso, e o primeiro passo para entender um programa é garantir que ele esteja perfeitamente estruturado. Então, erros simples, como uma cotação de fechamento esquecida ou uma vírgula ausente, tornam-se subitamente óbvios. Confio em que você já pratica boa formatação, e aqui está uma metáfora para outras práticas recomendadas: as práticas recomendadas evitam erros, as práticas recomendadas facilitam a localização de erros, a aplicação das práticas recomendadas ocorre antes de encontrar o problema .

É muito barato dizer "eu vou consertar isso mais tarde", quando consertá-lo agora teria resolvido seu problema (também, essa lendária "fase de limpeza" pode nunca vir, então a única opção responsável é fazê-lo da maneira correta. primeira vez). No mínimo, tentar tornar o seu código o melhor possível antes de pedir ajuda a outras pessoas facilita a discussão sobre o seu código, assim é a coisa mais educada a se fazer.

amon
fonte
Você está certo em alguns pontos que afirma, mas no final não acho que esteja atingindo a marca. Você está assumindo a obtenção de conhecimento antes de ter a experiência que obterá o conhecimento.
Onno 26/03
4
@Onno Meus pontos principais (que respondem às perguntas que você fez) são que você não pode manter hábitos de um idioma e assumir que é uma prática recomendada em outro, e que é preferível tentar limpar código desde o início do que limpar depois. A limpeza do código - da melhor maneira possível - é essencial antes de pedir ajuda a outras pessoas (consulte sscce.org para obter dicas sobre bons trechos de código). Despejar código de lixo no SO com um "por favor, conserte isso" é inaceitável, especialmente se você souber melhor.
amon
2
Mas com relação à pergunta que você está sugerindo: a resposta de jm666 contém um ponto-chave: o guru pensa: "por que você perguntaria sobre X se você não queria se tornar um X-guru?". . Uma maneira possível de neutralizar isso é mencionar que você ainda está no início da curva de aprendizado e analisará isso mais tarde, mas por enquanto tenha essa pergunta mais imediata em mãos. No entanto, isso é um problema de comunicação, não um problema de programação.
amon
6
C ++ e C # têm optional<T>e Nullable<T>respectivamente. Além disso, praticamente todo mundo vaza memória em C ++ sem RAII, noob ou não.
23414 DeadMG
Acho que declarar variáveis ​​no início de um bloco geralmente torna seu código mais fácil de ler na maioria dos idiomas. Dessa forma, você sabe exatamente onde procurar quando precisar de ajuda para lembrar quais tipos são todas as suas variáveis ​​e quais.
Aprecie
12

Eu não sou um desenvolvedor hardcore de C ++, mas ...

Por que seria uma prática ruim de programação usar mais código propenso a erros em situações de protótipo, se a refatoração o tornar mais robusto posteriormente?

Uma coisa a ter em mente é que um erro no C ++ geralmente significa "comportamento indefinido". Em um idioma seguro, o pior que pode acontecer é uma exceção que encerra seu programa imediatamente. No C ++, você tem sorte se receber um segfault. É perfeitamente possível que seu programa continue fazendo algo sutilmente errado. Ele também pode se comportar corretamente por um período de tempo e manifestar erros muito mais tarde, ou pode se comportar corretamente o tempo todo, mas eventualmente consome toda a sua memória.

De qualquer forma, basta um único erro para tirar a execução do programa completamente dos trilhos e entrar em território desconhecido. É provável que, para o desenvolvedor C ++ em período integral, o "caso base" signifique "nenhuma possibilidade de comportamento indefinido ou vazamento de memória".

Como o programa escrito em C ++ seria como se estivesse escrito em Java? O que o torna um programa ruim?

Não acho que haja uma resposta para isso que não seja amplamente especulativa e opinativa. Se você quiser que eu entenda, o Java tende a ter alguns antipadrões associados, como o fato de que tudo tem que ser um objeto. Onde em outros idiomas que você passar um ponteiro, functor ou função, em Java você costuma encontrar toneladas de vácuo e por pouco-útil ThingDoers, FooFactoriese IFrobnicatorsque são apenas funções disfarçados.

Da mesma forma, onde em outros idiomas você pode passar uma estrutura simples de tupla ou sem nome, em Java para agrupar apenas dois objetos em um contêiner de dados simples, é necessário predefinir uma classe NamedThing de mais de 30 linhas com setters, getters e Javadocs. A relativa falta de recursos do Java força os programadores a executar backflips duplos orientados a objetos para realizar as tarefas algumas vezes. O código resultante raramente é idiomático fora do Java.

Depois, há o fato de que em C ++ você precisa de um gráfico de objetos muito simplificado para gerenciar a memória manualmente; geralmente um objeto pertence a exatamente um outro objeto. Em Java, você não precisa seguir restrições tão rígidas, porque o coletor de lixo garante que as coisas sejam limpas quando não houver mais referências a elas. Portanto, há definitivamente um risco de gerenciamento de memória incorreto se você apenas transliterar o código de Java para C ++.

Finalmente, poderia ser apenas elitismo. Não vou fingir que eles são a maioria, mas definitivamente vi um sentimento de "não preciso de uma linguagem que segure minha mão e me impeça de fazer coisas estúpidas" entre alguns desenvolvedores de C ++. Na opinião deles, C ++ é uma linguagem "real" e, se você não consegue lidar com suas idiossincrasias, não é um "programador real".

Doval
fonte
1
Muito disso é aliviada com Java 8 - passeios lambdas para a maioria salvar o dia :-)
Martijn Verburg
@MartijnVerburg concordou, um grande passo à frente por lá. Mas os problemas tecnológicos são fáceis de resolver! Os velhos hábitos são difíceis de morrer e os estigmas, ainda mais difíceis. Heck, algumas pessoas chegam ao ponto de reclamar que o Java não precisa de nenhum desses "novos" recursos, e que está a caminho de se tornar o próximo C ++.
Doval 26/03
Sim, eu sempre balançar a cabeça naquele - Java irá deliberadamente sempre evoluir mais lentamente do que outras línguas, pois é um burro de carga de longo prazo. A JVM, no entanto, pode avançar aos trancos e barrancos um pouco mais rápido, o que permite que coisas como Lambdas acabem chegando ao idioma.
Martijn Verburg 27/03
6

Resposta levemente fora do tópico ...

Não se preocupe - esse é um "comportamento" comum em qualquer comunidade de especialistas. E seja honesto, se você é bom em qualquer idioma e encontra um código "estranho", provavelmente também o criticará. (porque, quero ensinar).

Estou no mundo perl - quando verá algo como:

$imax=$#array;
$str=""
for($i=0; $i<$imax; $i++) {
    $str = "$str" . $array[$i];
}

ao invés de:

my $str = join '', @array;

com certeza comentará - (leia: ensine o autor) sobre a joinfunção.

De qualquer forma, muitas críticas são contraproducentes e um dos melhores exemplos é o seguinte: (extraído de: http://perl-begin.org/humour/#How_can_I_switch_off_the_T.V..3F )

(Este bit foi postado anonimamente em um pastebot em 23 de março de 2011. Ele é colocado aqui para posteridade após algumas edições.) - também ligeiramente editado

Pergunta: como posso ligar minha TV?

O que o OP quer ouvir?

Por exemplo: Localize o botão liga / desliga do controle remoto da TV e pressione-o. O botão geralmente está vermelho e está localizado na linha superior do controle remoto.

Resposta do especialista #perl: Primeiro, o que você quer dizer com "ligar"? Defina primeiro. Experimente sua TV, controle remoto e a sala de estar também.

... depois de um nopaste:

Seu quarto é feio. E a TV parece terrível. Use Mr. Clean na tela e limpe sua sala primeiro. Use três esfregões de limpeza em vez de dois. Use HDMI e nunca use conectores Scart (?), A menos que você realmente queira. O controle remoto da sua TV possui botões ilegíveis, limpe primeiro. Você é iniciante, então leia:

http://experts.blog/how_to_design_a_future_3D_TV.html http://experts.blog/the_basics_of_tv_repairing.html http://experts.blog/viruses_in_living_room_short_essay.html http://experts.blog/global_chip_replacement_guide.html

Convidado no IRC: Mas, eu não quero ser um especialista em TV.

Resposta: Por que você deseja ligar a TV?

jm666
fonte
1
Esta resposta não está fora do tópico. Explica exatamente por que alguém criticaria o uso não convencional de um idioma e por que ocasionalmente essa crítica automática pode ir longe demais. Eu gosto disso.
Trichoplax
1

Por que seria uma prática ruim de programação usar mais código propenso a erros em situações de protótipo, se a refatoração o tornar mais robusto posteriormente?

Ao escrever rápido e sujo, com a mente de corrigir mais tarde, existe o perigo de esquecer algo que você precisa corrigir.

Como o programa escrito em C ++ seria como se estivesse escrito em Java? O que o torna um programa ruim (considerando que eu indiquei a intenção do estilo atual e o trabalho planejado para melhorar?)

No java, você não precisa pensar em quem possui um determinado objeto, basta passar a referência e esquecê-la como se não fosse nada. No entanto, em C ++, é necessário definir claramente quem é o proprietário do objeto e quem é responsável por limpá-lo.

Como eu seria um péssimo profissional se eu escolhesse usar uma construção usada em um certo paradigma de programação (por exemplo, OOP / DP)

Você não faria; O C ++ é uma linguagem com vários paradigmas, mas suporta OOP muito bem, mas também pode fazer muitas outras coisas. No entanto, a maior parte se resume ao uso da ferramenta correta para o trabalho, em vez de puxar o martelo toda vez que você precisa colocar um espigão pontudo em alguma madeira.

A razão pela qual você recebeu uma resposta ruim é que a maioria das pessoas no SO tende a julgar as habilidades pela idiomática que você pode codificar no idioma que está perguntando. As pessoas familiarizadas com o C ++ tendem a tremer de joelhos quando veem códigos ruins que parecem com algo que os havia mordido no passado.

catraca arrepiante
fonte
Percebo que o esquecimento de melhorar pode ser um problema para alguns, mas mantenho uma longa lista de tarefas e sou muito disciplinado em adicionar tags de tarefas para esse tipo de trabalho. (é por isso que eu gosto do VS, é muito bom em gerenciamento de trabalho). É o mesmo para a documentação. Não escrevo uma linha de código antes de escrever a documentação para ela. Quanto à questão da propriedade, por causa dos diagramas de sequência, acho que tenho uma boa idéia de quem tem links para quem.
Onno 26/03
1
@Onno: Francamente, ninguém sabe ou se importa com o quão bom você é pessoalmente em acompanhar essas coisas. A grande maioria das pessoas que escrevem C ++ que se parece com Java ou C, nem é tão meticuloso. É muito melhor para eles aprenderem a fazer as coisas certas da primeira vez do que escrever uma nota para voltar e corrigi-las mais tarde, porque a experiência mostra que elas praticamente nunca fazem isso de verdade.
cHao 26/03