Que linguagem de programação gera menos erros difíceis de encontrar? [fechadas]

54

Qual idioma, na sua opinião, permite que o programador médio produza recursos com a menor quantidade de bugs difíceis de encontrar? Esta é, naturalmente, uma questão muito ampla, e estou interessado em respostas e sabotagens muito amplas e gerais.

Pessoalmente acho que passo muito pouco tempo procurando bugs estranhos em programas Java e C #, enquanto o código C ++ tem seu conjunto distinto de bugs recorrentes, e o Python / similar tem seu próprio conjunto de bugs comuns e bobos que seriam detectados pelo compilador em outras linguagens.

Também acho difícil considerar as linguagens funcionais a esse respeito, porque nunca vi um programa grande e complexo escrito em código totalmente funcional. Sua entrada por favor.

Editar: Esclarecimentos completamente arbitrários de erros difíceis de serem encontrados: Demora mais de 15 minutos para serem reproduzidos, ou mais de 1 hora para encontrar a causa e corrigir.

Perdoe-me se esta for uma duplicata, mas não encontrei nada sobre este tópico específico.

    
por Magnus Wolffelt 01.12.2010 / 17:20
fonte

12 respostas

59

Quanto mais poderoso for o sistema de tipos da linguagem, mais erros serão capturados no próprio tempo de compilação.

A figura a seguir compara algumas das linguagens de programação bem conhecidas em termos de potência, simplicidade e segurança de seus sistemas de tipos. [ Fonte ]

*Factoringnacapacidadedeusarconstruçõesinseguras.

C#getsstuffedintotheunsaferowbecauseofthe"unsafe" keyword and associated pointer machinery. But if you want to think of these as a kind of inline foreign function mechanism feel free to bump C# skyward.

I've marked Haskell '98 as pure but GHC Haskell as not pure due to the unsafe* family of functions. If you disable unsafe* then jump GHC Haskell up accordingly.

    
por 09.03.2015 / 20:13
fonte
20

Na minha opinião, Haskell ajuda a evitar algumas fontes comuns de erros:

  • é puramente funcional: as funções não podem ter efeitos colaterais (não intencionais) e isso torna a programação multicore mais fácil e menos propensa a erros
  • é strongmente digitado: você não pode, por exemplo, mistura acidentalmente valores bool, char, int e float
  • é estaticamente digitado: muitos erros de programação são detectados em tempo de compilação
  • null não faz parte das definições de tipo de valor: você evita o erro de bilhões de dólares
  • há muitas funções de ordem superior prontas que você pode reutilizar em vez de criar suas próprias implementações, possivelmente defeituosas
  • tem um coletor de lixo: erros de memória são quase eliminados (exceto por "vazamentos de espaço" devido à sua estratégia de avaliação lenta)
por 17.07.2016 / 03:46
fonte
18

Tradicionalmente, os erros mais difíceis de encontrar são condições de corrida em aplicações multi-threaded, como são

  • quase impossível de reproduzir
  • pode ser muito sutil

Por isso, você precisa de linguagens que administrem o paralelismo tanto quanto possível e sem intrusões. Estes ainda não são mainstream. Java faz alguns, mas deixa você com a parte difícil.

No meu entender, você precisa de uma linguagem funcional, já que o "sem efeitos colaterais" é o que, em primeiro lugar, faz com que os dois pontos sejam eliminados. Vi que o trabalho está em andamento, tornando o Haskell uma linguagem multi-thread eficiente, e acredito que o Fortress foi projetado desde o início para ser uma linguagem paralela eficiente.

Editar: em Java, Executors manipula ainda mais as partes duras. Você precisa fazer com que as tarefas individuais estejam de acordo com a interface Callable .

    
por 15.06.2011 / 14:58
fonte
13

A Ada é projetada para que, tanto quanto possível, seja capturado em tempo de compilação, em vez de em tempo de execução. O que isto significa é que muitas vezes leva 10x mais tempo para que um programa em Ada compile do que o equivalente em Java diria, mas quando ele compila você pode estar muito mais confiante de que classes inteiras de bugs não se manifestarão quando o programa executar.

    
por 01.12.2010 / 12:08
fonte
7

Primeiro, uma definição: um erro difícil de encontrar, pelo que entendi, é um bug que pode ser reproduzido, mas a causa é difícil de encontrar.

Provavelmente, o aspecto mais importante é o que eu chamaria de estreiteza , ou seja, até onde um bug pode escapar, quão grande é o escopo que um bug pode potencialmente influenciar. Em idiomas como C, um bug, por exemplo um índice de array negativo ou ponteiro não inicializado pode afetar literalmente tudo em todo o programa, então, no pior dos casos, você precisa verificar tudo em qualquer lugar para encontrar a origem do problema.

Bons idiomas a esse respeito suportam modificadores de acesso e os aplicam de uma forma que torna difícil ou impossível contorná-los. Boas linguagens encorajam você a limitar o escopo de suas variáveis, em vez de tornar muito fácil ter variáveis globais (por exemplo, "tudo que não é explicitamente declarado é uma variável global com um tipo e valor padrão").

O segundo aspecto importante é a simultaneidade . As condições de corrida são geralmente difíceis de reproduzir e, portanto, difíceis de encontrar. Boas linguagens oferecem mecanismos de sincronização fáceis de usar e suas bibliotecas padrão são seguras para threads sempre que necessário.

Isso já completa minha lista; outras coisas, como digitar strong, ajudam a capturar bugs em tempo de compilação, mas esses bugs provavelmente não seriam difíceis de encontrar depois.

Considerando tudo isso, eu diria que Java e C #, e muitas outras linguagens no mundo da JVM e do .net, são adequadas para evitar erros difíceis de localizar.

    
por 01.12.2010 / 12:55
fonte
7

Como o Excel é a DSL mais amplamente utilizada, vou com o Excel. (excluindo o VBA, claro)

Ele se encaixa no projeto:

  • É sempre fácil reproduzir (aqui está uma planilha - não está funcionando)
  • É muito fácil encontrar o bug, já que é totalmente "funcional" - comece com a célula errada e rastreie todas as suas dependências.
por 02.12.2010 / 12:02
fonte
7

Essa é uma pergunta difícil, porque a maioria dos bugs não é culpa da própria linguagem - ao contrário, eles são responsáveis por desenvolvedores cometerem erros na maneira como usam a linguagem.

Acredito que há vários aspectos dos recursos de linguagem que afetam a probabilidade de erros:

  • Interatividade - linguagens dinâmicas com REPLs incentivam a interação / experimentação com programas em execução e ciclos de teste / código muito menores. Se você acredita que a iteração é uma boa maneira de descobrir soluções simples e limpas e detectar / eliminar bugs, isso tenderia a favorecer as linguagens interativas.

  • Expressividade - se o código for mais curto e tiver menos clichê / complexidade incidental, será mais fácil ver erros / erros lógicos.

  • Segurança de tipo - quanto mais verificação de tempo de compilação, mais erros serão detectados pelo compilador, portanto, em geral, a segurança de tipos é uma coisa boa. No entanto, estes geralmente não são difíceis de encontrar bugs - mesmo em uma linguagem totalmente dinâmica, o tipo errado em uma estrutura de dados geralmente causa um erro de execução muito óbvio, e o TDD quase sempre pega esses tipos de bugs .

  • Imutabilidade - muitos erros são devidos a interações complexas de estado mutável. Línguas que enfatizam a imutabilidade (Haskell, Clojure, Erlang) têm uma enorme vantagem ao evitar a mutabilidade

  • Programação funcional - abordagens funcionais para escrever código tendem a ser mais "comprovadamente corretas" do que o código orientado a objeto com sequências complexas de efeitos / interações. Minha experiência é que o PF ajuda a evitar bugs complicados - creio que há alguma pesquisa acadêmica em algum lugar que atualmente não posso encontrar que sustente isso.

  • Suporte de simultaneidade - problemas de simultaneidade são particularmente difíceis de detectar e depurar, e é por isso que isso é tão importante. Qualquer coisa que requeira bloqueio manual está fadada ao fracasso (e isso inclui praticamente todas as abordagens orientadas a objetos para a simultaneidade). A melhor linguagem que conheço nesse sentido é o Clojure - ele tem uma abordagem única para gerenciar a simultaneidade que combina a memória transacional de software com estruturas de dados imutáveis para obter uma estrutura de concorrência nova, confiável e composta. Consulte o link para obter mais informações

por 05.06.2015 / 07:53
fonte
5

Quanto menos poderosa for a linguagem, menos opções você terá para fotografar seu próprio pé.

Linguagens de alto nível como Java e C # produzirão menos bugs do que linguagens de baixo nível como C ++.

Dito isto, acredito que o Java é mais seguro que o C #. Java é artificialmente limitado para que um programador médio sem conhecimento avançado possa dominá-lo e produzir programas estáveis.

    
por 01.12.2010 / 14:55
fonte
3

What language, in your opinion, allows the average programmer to output features with the least amount of hard-to-find bugs?

Na minha opinião, Delphi. Sendo baseado em Pascal, a linguagem é simples e intuitiva o suficiente para o programador médio (ou mesmo inexperiente). codificadores) para pegar facilmente, e seu rico suporte a ferramentas e bibliotecas tornam a maioria dos bugs fáceis de encontrar.

  • Digitação strong e um compilador estrito que detecta muitos erros comuns.
  • Sintaxe intuitiva que não incentiva erros comuns. ("O último erro do mundo", if (alert = RED) {LaunchNukes;} , não irá compilar, por exemplo).
  • Um modelo de objeto bem projetado que elimina muitos dos erros OOP comuns do C ++.
  • Verificação de limites e verificação de intervalo integrados ao idioma, reduzindo drasticamente as chances de segurança problemas.
  • Provavelmente o compilador mais rápido conhecido pelo homem, o que aumenta sua produtividade e torna mais difícil perder sua linha de pensamento enquanto espera por uma compilação.
  • O depurador do Visual Studio do depurador quer ser como quando crescer.
  • Rastreamento de vazamentos embutido diretamente no gerenciador de memória, tornando trivial a localização e a correção de vazamentos de memória.
  • Uma biblioteca padrão grande e madura que oferece maneiras pré-criadas e pré-testadas para realizar tarefas comuns sem precisar criar suas próprias implementações possivelmente com bugs.
  • É fornecido com ferramentas úteis, como um poderoso sistema de registro em log e um criador de perfil, para facilitar o rastreamento de problemas.
  • strong suporte da comunidade para problemas comuns que não estão na biblioteca padrão, incluindo uma poderosa biblioteca de concorrência de terceiros
por 01.12.2010 / 14:49
fonte
2

Uma coisa a ter em conta é a volta do tempo.

Nos últimos cinco anos, desenvolvi principalmente aplicações web em java (JSF, Seam, etc.). Recentemente, consegui um novo emprego e estamos usando o Perl (com o Catalyst e o Moose).

Sou muito mais produtivo em Perl do que em Java.

Não precisar compilar e implantar (quente) é um dos motivos. Eu também acho que escrever casos de uso é mais fácil, como pode ser feito de uma maneira mais iterativa. E os frameworks em Java parecem ser desnecessariamente complexos, pelo menos para os projetos em que estou envolvido.

Eu acho que o número de bugs no meu código Perl é mais ou menos o mesmo que o número de bugs no meu código Java, pode até ser maior. Mas acho mais fácil e rápido encontrar e corrigir esses erros.

    
por 02.12.2010 / 10:12
fonte
1

Talvez o levantamento do número de ferramentas disponíveis para análise de código estático e dinâmico para cada linguagem de programação possa dar uma ideia. Quanto mais ferramentas para uma linguagem, é mais provável que a linguagem seja muito popular entre os usuários ou muito popular na geração de bugs difíceis de encontrar. Mas não consigo fazer com que o Google me aponte para nenhum estudo sobre esse assunto. Também deve ser notado que algumas linguagens, como C, podem ser usadas para contornar os bugs de hardware subjacentes, bem como contornar o desgaste do hardware à medida que envelhece.

    
por 01.12.2010 / 12:41
fonte
1

Em vez de falar sobre idiomas, que tal falar sobre recursos de linguagem

    O
  • java obriga você a pensar em exceções (lança ...) e deve publicar ou manipular essas exceções. Isso realmente me impede de esquecer situações de erro ou estou usando mais exceções que são derivadas de SystemException que não precisam dessa manipulação?
  • e o "design por contrato" (http://en.wikipedia.org/wiki/Design_by_contract) que me obriga a pensar em pré e pós-condições. Eu li que agora é possível com c # -4.0.
por 03.12.2010 / 12:25
fonte