Princípio KISS aplicado ao design da linguagem de programação?

14

O KISS ("mantenha as coisas simples, estúpidas" ou "mantenha as coisas simples, veja por exemplo aqui ) é um princípio importante no desenvolvimento de software, mesmo que aparentemente tenha se originado na engenharia. Citando o artigo da Wikipedia:

O princípio é melhor exemplificado pela história de Johnson entregando a uma equipe de engenheiros de projeto algumas ferramentas, com o desafio de que as aeronaves a jato que estavam projetando devem ser reparadas por um mecânico comum em campo sob condições de combate apenas com essas ferramentas. Portanto, o "estúpido" refere-se à relação entre a maneira como as coisas quebram e a sofisticação disponível para corrigi-las.

Se eu quisesse aplicar isso ao campo do desenvolvimento de software, substituiria "aviões a jato" por "software", "mecânico médio" por "desenvolvedor médio" e "em condições de combate" por "sob o desenvolvimento / manutenção de software esperado" condições "(prazos, restrições de tempo, reuniões / interrupções, ferramentas disponíveis etc.).

Portanto, é uma idéia comumente aceita que se deve tentar manter um software simples (ou estúpido , caso você omita a vírgula), para facilitar o trabalho mais tarde.

Mas o princípio KISS pode ser aplicado também ao design da linguagem de programação? Você conhece alguma linguagem de programação que foi projetada especificamente com esse princípio em mente, ou seja, para "permitir que um programador médio em condições de trabalho médias escreva e mantenha o máximo de código possível com o mínimo esforço cognitivo"?

Se você citar algum idioma específico, seria ótimo adicionar um link a algum documento no qual essa intenção seja claramente expressa pelos designers de idiomas. De qualquer forma, eu estaria interessado em aprender sobre as intenções (documentadas) dos designers, em vez de sua opinião pessoal sobre uma linguagem de programação específica.

Giorgio
fonte
4
Você já explorou a família básica de idiomas (ou pelo menos a intenção original por trás deles)?
4
BASIC e Pascal ... ambos projetados como idiomas instrucionais.
Michael Brown
1
O que você quer dizer com simples? A maioria dos idiomas é bem simples, pois não há muito para eles. Nada era menos complexo que o montador. As estruturas geralmente são complicadas, mas são projetadas para permitir "escrever e manter o máximo de código possível com o mínimo esforço cognitivo".
Pd4
7
O esquema (r) foi usado como linguagem de ensino por anos (décadas?) E foi desenvolvido simplificando o LISP e o Algol (e pode ser mais). O livro SICP leva muito menos tempo para ensinar o próprio idioma. Além disso, DSLs vêm à mente.
precisa saber é o seguinte
3
@Giorgio dê uma olhada em Haskell. Tem muito e quero dizer muito pouco bits embutidos. A maioria dos operadores são funções que estão na biblioteca principal, mas não necessárias para a própria linguagem, tem feito grandes esforços para remover todas as peças desnecessárias
Jimmy Hoffa

Respostas:

15

Quando penso em minimialismo, penso em Lisp and Go . Com o Lisp, tudo o que você tem são funções e listas, o mais simples possível (bem, há um pouco mais, mas o que for). No entanto, acho que o caso Go é mais interessante.

O Go foi projetado para ser simples (é uma leitura decente). O termo que eles usam é "ortogonalidade do recurso", o que significa que qualquer recurso só deve ser adicionado se fornecer algo verdadeiramente único. Isso parece ter origem no envolvimento dos autores ( Russ Cox e Rob Pike me vem à mente) com o Plan9 , que era uma reimaginação do UNIX com a simplicidade em mente. (Se você estiver interessado em design minimalista, o artigo de Rob Pike sobre um sistema de janelas simples é uma boa leitura.)

Aqui estão alguns exemplos simples da sintaxe:

Apenas uma construção em loop

Um loop pode se parecer com um dos seguintes:

Loop infinito

for {
}

Enquanto loop

for <conditional> {
}

Tradicional para loop

for i := 0; i < 10; i++ {
}

Foreach loop

// works for maps or arrays
for k, v := range arr {
}

Interruptor multiuso

switch {
    // cases must be evaluate to a boolean
}

switch <value> {
}

switch t := <value>; t {
    // can use t inside
}

Retorno múltiplo

return val1, val2, ...
  • Remove a necessidade de lançamento (passe o erro como último valor de retorno)
  • Remove a necessidade de parâmetros fora
  • Remove a necessidade de tuplas

Interfaces

type X interface {
    DoSomething()
    String() string
}
  • Resolve problemas semelhantes aos genéricos
  • Permite abstração

Incorporação

type A struct {
    Thing string
}

type B struct {
    A // embeds A in B, so B.Thing refers to A.Thing
}
  • Resolve o mesmo problema que a herança
  • Evita a necessidade de aulas

Canais

Pode ser usado para implementar semáforos

var c = make(chan bool, 1)
c<-true // semaphore lock
<-c // semaphore free

Usado para passagem de mensagens entre threads

func produce(c chan<- bool) {
    for {
        c <- true
    }
}
func consume(c <-chan bool) {
    for {
        <-c
    }
}

var c = make(chan bool)
go produce(c)
go consume(c)

Pode ser usado para manipular eventos assíncronos

func async() chan bool {
    var c = make(chan bool)
    go doSomethingAsync(c)
    return c
}

// wait for long async process to finish
c := async()
select {
    case _ = <-c:
}

Conclusão

Não vou entrar em todas as partes da sintaxe, mas espero que você possa ver o que o minimalismo pode fazer. O idioma é intrigante, não porque adiciona uma tonelada de novos recursos, mas porque usa os melhores recursos de outros idiomas sem nada extra.

Geralmente, existe uma "melhor" maneira de resolver um problema. Por exemplo, na lista de discussão, muitos usuários reclamam de não ter genéricos. Após a discussão, eles percebem que tudo o que querem fazer pode ser feito com interfaces. Leia sobre o uso eficaz de exemplos de sintaxe idiomática.

O benefício das linguagens KISS é que é possível escrever código idiomático, porque o estilo do código é restrito pela linguagem. Por exemplo, no Go, você não pode escrever algo como isto:

if <condition>
    statement;

Você precisa usar chaves:

if <condition> {
    statement;
}

Existem muitos outros exemplos disso na sintaxe, o que facilita a leitura do código de outras pessoas.

Benefícios do idioma KISS em relação aos idiomas avançados:

  • mais fácil entender o código dos outros
  • mais fácil para grok toda a linguagem (C ++ é notório por ser difícil de entender)
  • foco no algoritmo, não na sintaxe
beatgammit
fonte
5
Na minha humilde opinião, a sintaxe do loop for tradicional não é o KISS. É claro que isso é familiar para todo programador do tipo C, mas lembro da primeira vez que aprendi isso: fiquei muito confuso. BASIC é mais KISS for i=1 to 10for item in group
:,
3
@mouviciel - Eu quase nunca uso o loop for tradicional. O problema for i = 1 to 10é se ium dia será 10. Isso pode depender da linguagem (o bash inclui 10, o python não). O loop for tradicional é universal.
beatgammit
+1, especialmente para o resumo sobre os benefícios do minimalismo.
Giorgio
1
Ir como um estudo de caso é interessante porque não é considerado um idioma do KISS por seus detratores. De fato, o argumento é o seguinte: uma linguagem "simples" não leva ao código "simples" ou a um entendimento mais fácil. Às vezes, deve haver mais complexidade (por exemplo, um bom suporte de genéricos) para que o código seja mais fácil de entender.
Andres F.
13

Eu acho que o Zen do Python indicará por que o Python é uma linguagem simples muito melhor do que eu:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Editar em resposta a @Giorgio

Como afirma sua pergunta,

"Você conhece alguma linguagem de programação que foi projetada especificamente com esse princípio em mente, ou seja, para 'permitir que um programador comum, em condições normais de trabalho, escreva e mantenha o máximo de código possível com o mínimo esforço cognitivo'"

Python é, para mim, o que imediatamente vem à mente. O design do Python é uma resposta direta à metodologia de Perl, o famoso "Há mais de uma maneira de fazer isso". Embora isso seja ótimo, permitindo que os programadores escrevam código com muita facilidade, isso não ajuda na manutenção. Tendo antes gerenciado um programa (muito mal escrito, admito) escrito em Perl, agradeço ao Python forçar tanto as boas práticas de codificação quanto a linguagem concisa na garganta.

O Python também não força você a seguir uma metodologia específica ao escrever programas. Posso optar por seguir um estilo de programação estrito, orientado a objetos, ou escrever um script simples para executar sequencialmente. Como não é necessário inicializar uma classe, chame o main()método como você é forçado a fazer em Java é muito bom. (Além disso, imprimir em stdout no Python é maravilhoso, mas esse é um ponto nulo).

Por fim, a metodologia "Baterias incluídas" de incluir uma extensa biblioteca padrão com o idioma é maravilhosa. Em vez de procurar em algum repositório externo por pacotes, a maior parte do que eu preciso já está incluída no idioma. Também é bom ter esse repositório externo, mas não ter que cavá-lo para realizar uma operação básica é realmente útil.

Zach Dziura
fonte
3
Obrigado pela citação útil. Essa é a intenção oficial do (s) criador (es) do Python? Além disso, observe que nem todos os leitores podem concordar com sua opinião sobre o Python; portanto, talvez seja um pouco forte demais afirmar que "Python é uma linguagem simples" como um fato bem conhecido e aceito. Seria possível formulá-lo como "Python foi projetado com a simplicidade em mente"?
Giorgio
@Giorgio - É a experiência de muitos desenvolvedores por aqui que o python é realmente uma linguagem simples. Simples de aprender, simples de escrever e simples de ler. Sobre a citação, como python é "pilhas incluídas", você pode obtê-lo diretamente do idioma com import thiscomando
Mouviciel 22/03
1
O TCL também é uma boa resposta para isso e o IIRC também foi uma resposta à complexidade do PERL.
jk.
@mouviciel Depois de encontrar um código espaguete incrivelmente complicado do Python em vários lugares, não acho mais que o Python tenha sucesso em seus objetivos aqui. O Python não é melhor do que a maioria das linguagens quando se trata de simplicidade - pode ser muito bom em ofuscação acidental.
Izkata
1
Python é simples, desde que as pessoas fiquem longe da maioria das __magic_functions __ () e @decorators.
Weberc2
3

Uma chave importante para manter a "simplicidade" é reconhecer quando a complexidade será necessária e ter as partes do sistema que melhor podem lidar com isso. Ter um único tipo de referência de objeto que não faz distinção entre valores imutáveis, valores mutáveis ​​e entidades, torna o Java "simples", não elimina a necessidade de distinguir valores e entidades; apenas priva os programadores de ferramentas para ajudá-los a fazê-lo.

De maneira mais geral, se alguém está tentando ter uma linguagem de programação ou recurso de estrutura compatível com vários casos de uso, deve-se garantir que não haverá situações em que comportamentos diferentes sejam apropriados em casos de uso diferentes, mas o compilador não poderá informar eles separados. Adicionar mais tipos a uma linguagem ou estrutura pode parecer uma complicação, mas em muitos casos pode realmente facilitar as coisas.

Considere, por exemplo, a bagunça de regras que cercam tipos assinados e não assinados em C. A complexidade dessas regras decorre do fato de que algum código usa tipos inteiros não assinados para representar números, enquanto outro código os utiliza para representar membros de um anel algébrico final (especificamente, o conjunto de números inteiros mod 2ⁿ congruente). As regras de conversão de tipo se comportam de maneiras que às vezes são apropriadas para um uso e outras que são apropriadas para o outro. Ter tipos de quebra automática e não-quebra automática dobraria o número de tipos inteiros, mas poderia simplificar as regras associadas a eles:

  • Qualquer tipo inteiro sem anel de qualquer tamanho pode ser atribuído a um anel de qualquer tamanho; um anel pode ser atribuído apenas a um anel de tamanho igual ou menor .

  • Operações que não sejam operadores relacionais que envolvam um número inteiro sem anel e um anel converterão implicitamente o número inteiro no tipo de anel.

  • Os anéis podem ser expressamente convertidos em números ou em anéis maiores; o valor de um anel não assinado é o menor número inteiro não negativo que, quando adicionado ao zero do anel, produziria o valor do anel. O valor de um anel assinado é o número inteiro de menor magnitude que, quando adicionado ao zero do anel, produziria o valor do anel, sendo o valor negativo preferido em caso de empate.

  • Exceto como mencionado acima, os anéis são limitados a operações com anéis do mesmo tamanho ou menores.

  • Operações em números inteiros que não sejam de anel de tipos diferentes devem elevar os números para um tipo que possa acomodar todos os valores de qualquer operando ou devem ser rejeitadas pelo compilador se não existir um tipo adequado

Definir tipos de toque parece dobrar o número de tipos inteiros, mas simplificaria bastante a escrita de código portátil. O uso dos mesmos tipos não assinados para números e toques reduz o número de tipos, mas leva a regras complicadas que tornam quase impossível escrever código portátil eficiente.

supercat
fonte
+1 totalmente acordado. Uma linguagem "simples" (simples no sentido de ter uma pequena especificação) não leva necessariamente a um código simples ou a facilidade de raciocínio para o programador.
Andres F.
Ótimo comentário. A adição de complexidade deve ser vista em termos de custos e benefícios.
user1071847
2

Indiscutivelmente, o Tcl foi desenvolvido nesse sentido. O idioma inteiro pode ser descrito em apenas 12 regras em uma única página de manual . É notavelmente simples e consistente.

O criador do Tcl afirmou o seguinte como os objetivos originais:

  • O idioma deve ser extensível: deve ser muito fácil para cada aplicativo adicionar seus próprios recursos aos recursos básicos do idioma, e os recursos específicos do aplicativo devem parecer naturais, como se tivessem sido projetados no idioma desde o início.
  • O idioma deve ser muito simples e genérico, para que possa funcionar facilmente com muitos aplicativos diferentes e para não restringir os recursos que os aplicativos podem fornecer.
  • Como a maioria das funcionalidades interessantes virá do aplicativo, o principal objetivo do idioma é integrar ou "colar" as extensões. Assim, o idioma deve ter boas instalações para integração.

De " História do Tcl " - http://www.tcl.tk/about/history.html

Bryan Oakley
fonte
2

Se um idioma é fixo em seu design por causa do KISS, ele não pode crescer. Uma linguagem que não pode crescer morrerá.

No vídeo a seguir, Guy Steele explica de maneira inteligente que uma linguagem de programação deve crescer e por quê. Se você aplicar o KISS, como um idioma pode crescer porque, uma vez lançado, seu conjunto de ferramentas é fixo e nunca é permitido mudar.

A palestra de Guy Steele na conferência ACM OOPSLA de 1998 sobre "Crescendo uma linguagem" discute a importância e os problemas associados ao design de uma linguagem de programação que pode ser cultivada por seus usuários.

É um vídeo de uma hora, mas vale a pena assistir. Se você não sabe quem é Guy Steele, deveria realmente falar sobre design de linguagem.

Eu escolhi este vídeo como a resposta, porque acredito que a aplicação do KISS ao design de linguagem em geral está errada, e espero que ver um discurso de uma pessoa notável do design de idiomas ajude a expandir sua compreensão do futuro do design de idiomas.

Como você veio aqui para aprender sobre design de idiomas e eu lhe dei uma razão para não usar o KISS, é justo que eu aponte algo que eu acho útil no design de idiomas. Dimensões cognitivas das notações

EDITAR

Quando escrevi a resposta acima, ela foi baseada no raciocínio de: se um mecanismo pode ser mantido apenas com um conjunto fixo de ferramentas, minha reformulação desse significado em relação ao design de linguagem é que uma linguagem não pode mudar uma vez liberada. Os comentários estão indicando que não era para isso. Então, deixe-me apresentar esta resposta modificada que estará mais alinhada com o entendimento revisado.

Se observarmos as dimensões cognitivas das notações , aprenderemos que existem muitas dimensões concorrentes associadas ao design de linguagem do que apenas a simplicidade e se você se concentrar demais em uma delas, sofrerá em outras. Com a questão de focar bastante na simplicidade (KISS), bem como apoiada por pessoas notáveis ​​do design de linguagem, enviei o discurso de Guy Steele para mostrar que tentar manter um design apenas simples afetará outras dimensões. Mais importante, estou tentando transmitir que você precisa observar várias dimensões e pesar os prós e contras delas, não apenas a simplicidade.

Guy Coder
fonte
3
Então, o que acontece se o vídeo ficar indisponível? Ou se não estiver acessível em alguns países? Sua resposta deve ser completa e independente, atualize-a para pelo menos nos fornecer um breve resumo do vídeo, as respostas apenas por link não são realmente úteis e podem ser removidas a qualquer momento.
yannis
3
@AndreasScheinert O guia de respostas deixa claro que os links devem sempre ser acompanhados de resumos e / ou citações relevantes.
Thomas Owens
3
Não tenho certeza se posso concordar com sua avaliação. Tcl, por exemplo, é notavelmente simples. Durou anos, com apenas 11 regras que governavam seu uso. No entanto, por mais simples que seja, cresceu consideravelmente nos mais de 20 anos de sua existência. Agora, possui 12 regras, o que prova que não apenas sua biblioteca cresceu, mas também sua natureza fundamental foi autorizada a crescer, mantendo toda a sua simplicidade.
Bryan Oakley
1
"Se você aplica o KISS, como uma linguagem pode crescer porque, uma vez lançada, seu conjunto de ferramentas é fixo e nunca pode mudar.": Depende do que você quer dizer com simples e crescente. Você quer dizer adicionar novas bibliotecas (em inglês, adicionar novas palavras ao vocabulário) ou adicionar novas construções de idioma (em inglês, isso significaria adicionar, por exemplo, novos tempos verbais, novas preposições e assim por diante). As línguas naturais eventualmente param de adicionar novas regras gramaticais enquanto continuam adicionando novas palavras. Então, na minha intuição, simples se refere ao número de regras gramaticais, e não ao número de bibliotecas / palavras.
Giorgio
3
@ Buy Coder: Por outro lado, o vídeo para o qual você postou um link parece dizer algo diferente do que você diz no início de sua resposta, a saber, que um idioma deve fornecer certos recursos essenciais que permitem aos usuários (programadores) estenda o idioma (adicione novas bibliotecas). Não diz que a linguagem principal deva crescer indefinidamente.
Giorgio
1

Aqui está uma grande citação do Hardcore Visual Basic de Bruce McKinney , que por sua vez coloca as palavras na boca dos designers do BASIC, Kemeny e Kurtz . Enfatiza o meu.

Toda linguagem de computador tem seu próprio sentimento, sua própria atmosfera, seu próprio espírito. Você não pode realmente definir esse espírito, mas sabe o que é quando o vê. Penso no Basic como a antítese de uma afirmação atribuída a Albert Einstein:

Torne as coisas o mais simples possível - mas não mais simples.

Se essa citação tivesse sido escrita pelos designers originais da Basic, John Kemeny e Thomas Kurtz, teria sido simplificada ainda mais:

Simplifique as coisas.

Essa é a contradição que os programadores hardcore do Visual Basic vivem. Queremos que as coisas sejam simples, elegantes e intuitivas - mas não são. Queremos que nossos programas modelem a realidade - mas eles não. Queremos que nossa linguagem funcione da maneira que pensamos, não da maneira que os computadores ou sistemas operacionais querem que pensemos - mas não estamos dispostos a pagar o preço .

AakashM
fonte
Em uma nota relacionada, o fato de que uma construção de linguagem "pode" ser feita para atender a múltiplos propósitos não significa que esse design seja preferível a ter diferentes construções para esses diferentes propósitos. Por exemplo, C usa tipos não assinados para representar quantidades numéricas e para representar membros de um anel algébrico de quebra automática. Adicionar um número de qualquer tamanho ou assinatura a um anel deve render um membro do mesmo anel, enquanto adicionar dois números de qualquer tamanho e assinatura deve gerar um resultado grande o suficiente para manipular qualquer valor de qualquer operando. Usando tipos não assinados para os dois propósitos ... #
318
... significa que as regras de C às vezes as consideram como números e, às vezes, como membros do anel, de maneira que torna quase impossível escrever código portátil e limpo.
22714
1

Mas o princípio KISS pode ser aplicado também ao design da linguagem de programação? Você conhece alguma linguagem de programação que foi projetada especificamente com esse princípio em mente, ou seja, para "permitir que um programador médio em condições de trabalho médias escreva e mantenha o máximo de código possível com o mínimo esforço cognitivo"?

É bom que você tenha esclarecido o que você entende por "simples", porque, em minha opinião, uma linguagem de programação simples é aquela com sintaxe mínima e poucos recursos (Scheme, Forth, ML), que não se traduz diretamente em sua definição. Eu acho que você está realmente procurando por design de idiomas com o RAD (rápido desenvolvimento de aplicativos) em mente, e existem alguns deles. Consulte este encadeamento StackOverflow, por exemplo: /programming/66227/what-is-the-best-multi-platform-rad-language

Nemanja Trifunovic
fonte
"porque, em minha opinião, uma linguagem de programação simples é aquela com sintaxe mínima e poucos recursos (Scheme, Forth, ML)": Bem, na verdade eu copiei a definição da wikipedia, mas tendem a identificar as duas coisas. Por exemplo, o esquema pode ser aprendido muito rapidamente e, depois disso, posso me concentrar no problema a ser resolvido. Outras linguagens (como C ++, que eu uso no trabalho) continuam crescendo e você precisa aprender coisas novas o tempo todo. Além disso, o código se torna menos sustentável porque diferentes programadores tendem a usar diferentes subconjuntos da linguagem. Portanto, consideraria o SML e o Scheme "simples".
Giorgio
1

Surpreende-me que ninguém tenha mencionado C ainda, apesar de colocar a simplicidade em primeiro lugar de várias maneiras importantes, muitas vezes de maneira tão radical que os programadores não conseguem apreciar a simplicidade:

  • Não há mágica oculta. Se você escrevera + b em C, você tem a garantia de que ele será compilado em uma única instrução assembler.

    Mesmo em linguagens relativamente simples como Java, uma declaração simples como a + bpode levar vários microssegundos (se as variáveis ​​forem cadeias). Outras linguagens adicionam muito, muito mais a isso, com o exemplo extremo de C ++, em quea + b pode ser sobrecarregado para fazer com que os elefantes rosa apareçam. Não é assim em C: se não for uma chamada de função, não levará mais do que alguns nanossegundos. Essa previsibilidade de desempenho é um dos principais recursos do C e certamente é uma forma de simplicidade.

  • Os tipos de dados são tão simples quanto podem ser, enquanto descrevem todas as estruturas de dados interessantes que você pode criar na memória: Existem apenas os tipos fundamentais que uma CPU pode suportar + agregação ( struct) + repetição (matrizes) + referências (ponteiros )

    É verdade que as várias linguagens baseadas em lisp são muito mais simples que C nesse sentido. No entanto, eles não tentam permitir que o programador manipule livremente a memória como C faz.

  • Ortogonalidade dos recursos: você pode combinar livremente os recursos e eles funcionarão juntos conforme o esperado. Muitos idiomas falham nisso, permitindo que certas construções apareçam apenas em contextos definidos.

    Tomemos, por exemplo, matrizes de tamanho variável em C e C ++: C permite comprimentos de tempo de execução em todos os lugares, enquanto as solicitações mais liberais para expandir o padrão C ++ permitem apenas em certos contextos, como matrizes automáticas, e mesmo apenas na primeira dimensão. Isso permite que o C lide com matrizes multidimensionais verdadeiras com tamanhos conhecidos apenas em tempo de execução, enquanto os programadores do C ++ são reduzidos para gravardata[k + (j + i*lineLength)*lineCount] repetidamente.

    Outro exemplo disso é o ponteiro: um ponteiro de dados em C é realmente nada mais ou menos do que apenas uma variável contendo um endereço de memória de outra variável. Como o ponteiro é uma variável, o ponteiro duplo é uma coisa bem definida. Ou seja, dado o que inte int*são, fica claro o que int**deve ser. Compare isso com as referências C ++, onde você não tem absolutamente nenhuma idéia do que int&&é dado o significado de inte int&!)

É verdade que é justamente essa simplicidade que ganhou tanto ódio em C: a simplicidade da linguagem permite aos programadores mais liberdade do que é bom para eles, levando a muitos problemas com comportamento indefinido e indicadores mal direcionados. Especialmente a simplicidade da ortogonalidade que permite que um programador defina uma variável como int (*array[m])(struct foo* (*arg)[n])é do tipo que tende a causar dores de cabeça aos leitores porque coisas realmente complexas podem ser expressas de forma muito concisa pela combinação liberal de alguns recursos simples . Esse é o tipo de simplicidade em que C se destaca e que lhe confere a reputação de ser uma linguagem difícil de usar.

Além disso, a simplicidade da linguagem força o programador a escrever muito mais código do que linguagens mais ricas em recursos, fornecendo um terreno mais fértil para que os erros floresçam. No entanto, continua sendo a linguagem de alto nível possível mais simples se o seu objetivo principal é programar um computador real e não alguma máquina virtual.

cmaster - restabelece monica
fonte
O downvoter pode deixar uma mensagem explicando o motivo de seu voto?
Giorgio
C está uma bagunça. Tente descobrir o que obterá se adicionar um short assinado a um longo sem sinal e armazenar o resultado em um int. Mesmo sem "long long", ele possui oito tipos inteiros diferentes. Isso não é simples.
Simon B
@SimonB Você claramente não entendeu sobre o que é o meu post. A simplicidade sobre os tipos inteiros é a seguinte: Um tipo inteiro tem um tamanho (em bytes e bits) e pode ser assinado ou não assinado. Você pode usar qualquer combinação desses dois recursos ortogonais. É dessa ortogonalidade que estou falando. C possui todos os recursos necessários para explorar totalmente o hardware real e isso implica uma certa complexidade. No entanto, a maneira como C lida com essa complexidade é combinando conceitos simples de maneira ortogonal para permitir que o programador faça coisas complexas.
cmaster - restabelece monica
0

Java Wikipedia - embora não explicitamente declarada na Wikipedia, a simplificação é mencionada várias vezes e foi uma meta de design original, pois a única linguagem séria capaz de OO (termo usado vagamente) naqueles dias era C ++, que, como todos sabemos, é poderoso mas tem mais do que algumas armadilhas para os incautos.

A JVM foi projetada como uma maneira de simplificar o desenvolvimento de plataforma cruzada, e "Escreva uma vez execute em qualquer lugar" tornou-se um mantra Java por alguns anos - novamente, a intenção era que a estrutura fosse simples de implementar.

Eu acredito que o C # se enquadra nessa categoria de simplificação do idioma.

mattnz
fonte
Você quer dizer que o C # também foi inicialmente projetado como uma simplificação do C ++?
Giorgio
2
C ++ e OO? Alan Kay não pensa assim. C # Sinplyfication ???? Não sei o que você quer dizer com simples. Eu acho que seria melhor você dizer isso antes de declarar as coisas como tais. O LISP é simples, pois possui muito pouca sintaxe. C #, pelo contrário, tem toneladas de sintaxe e palavras-chave.
AndreasScheinert 6/12/12
A capacidade de simplificar o desenvolvimento de plataforma cruzada não significa que a linguagem em si seja simples. Algo pode ser multiplataforma, mas ainda não é simples por si só.
Bryan Oakley
@Bryan concordou - o design do Java levou em conta que os programas de plataforma cruzada (na época) não eram simples e, para criar programas simples, você precisava de uma linguagem simples e remover a complexidade de lidar com o código específico da plataforma no próprio programa.
mattnz
2
@Giorgio C # foi uma reinvenção do Java. O Java pretendia ser menos complexo que o C ++ (por exemplo, nenhuma herança múltipla) e algo muito maior (por exemplo, vasta biblioteca padrão, coleta de lixo).
22613 Sean McSomething
-2

Hum ... esta é realmente uma pergunta difícil de responder 'positivamente', porque quando penso na simplicidade no design da linguagem de programação (e no que é mais fácil de trabalhar), penso imediatamente em:

  1. "Legibilidade" do código - quão bem a linguagem encapsula objetos, métodos etc.
  2. A consistência das APIs e interfaces de idioma.

Existem várias línguas que fazem essas coisas bem - mas o que me vem à cabeça é uma língua que não faz bem as coisas 'como linguagem de programação': PHP.

[Isenção de responsabilidade - eu escrevi PHP e PHP ainda é o meu 'ir para a linguagem' para projetos simples da web. Isso é uma crítica ao amor ...]

Primeiro, o PHP se sai bem no ambiente em que normalmente é executado nos servidores da Web. É fácil de configurar, fácil de manter etc.

Onde eu luto com o PHP: quando você quer fazer algo "incomum" - algo que você normalmente não faz regularmente (no caso, eu estou pensando que estava consumindo um serviço da web SOAP - não algo que eu muito feito com PHP), você se depara com duas opções:

1) Várias extensões de código aberto para PHP. O modelo de objeto PHP é bastante flexível, onde o design da interface também não é muito consistente de biblioteca para biblioteca, de desenvolvedor para desenvolvedor. Quando confrontado com um conjunto de códigos em que alguém usou uma biblioteca da qual você nunca ouviu falar, gasta muito tempo descobrindo 'o que diabos isso faz' porque a linguagem permite a criação de API / biblioteca.

2) As funções "internas" - das quais existem muitas . Passei por alguns buracos de coelho para encontrar outra biblioteca ou implementar um pouco de funcionalidade para, de alguma forma, mais tarde, tropeçar emimpossiblyfound_basefunction()

Na minha opinião, simplicidade é consistência.

Chad Thompson
fonte
-3

Agora, a abordagem do KISS às linguagens de programação é uma noção engraçada, pelo menos se você considerar as linguagens de programação uma camada de abstração do conjunto de instruções de uma CPU, etc. Se você não definir "KISS" mais de perto. Só estou dizendo aqui que um carro de boi é o KISS aplicado ao carro ao máximo.

Agora, outra interpretação do KISS poderia ser algo como "feito de maneira inteligente, sem ornamentos desnecessários e não muito complicado". Especialmente, alguém poderia argumentar que não deve haver muitos casos específicos para coisas semelhantes etc. Geralmente, a matemática é muito boa para resumir as coisas à sua essência, e - o que é surpreendente - os matemáticos passaram algum tempo pensando em programação e computadores também .

Para programação, existem 2 modelos abstratos bastante famosos:

  • Uma é a máquina de turing, que define uma máquina e um modelo instrucional simples, capaz de calcular tudo o que um computador poderia fazer.
  • O outro é o Lambda-Calculus de Church et. al. isso é equivalente em poder

O interessante é que, embora a máquina de turing seja bastante simples em seu layout, não é um sistema fácil de manusear e não acho que se qualifique para "smart KISS". Mas o Lambda Calculus tem mais a ver com as linguagens de programação que conhecemos - e com os recursos pioneiros do Lisp and Scheme do cálculo lambda, ele chegou a muitas linguagens.

Lisp e Scheme são REALMENTE simples, pelo menos em termos de sintaxe. A sintaxe é um grande problema com linguagens de programação (que é provavelmente o motivo pelo qual elas são reinventadas o tempo todo). No caso do C ++, é quase impraticável para o cérebro humano prever como algumas linhas de origem são interpretadas pelo compilador.)

Lisps estão reduzindo completamente a complexidade sintática, introduzindo um formulário comum para comandos:

(command param1 param2 ...)

Pode ser uma chamada de método, como

(max 1 2 3 4)

bem como um ramo if, loop etc.

(if (< 1 2) 
    (write 4)
    (write 5))

(todo o código aqui é independente de pseudo-Lisp / Dialeto)

A forma

(command param1 param2 ...)

também pode ser interpretado como uma lista

(item1 item2 item3)

E essa é a base da simplicidade e beleza dos Lisps. Como as listas aninhadas (como no ifexemplo da instrução) constituem árvores e podem ser facilmente entendidas pela máquina e pelo humano na frente da máquina.

Outro recurso do Lisps são as macros. Não vou entrar nos detalhes sujos aqui, mas como não há diferença sintática entre chamadas de funções normais e "Sintaxe (ovo para loops, declaração de variáveis ​​etc.), tudo o que o analisador precisa manipular em outros linguagens de programação), você pode criar sua própria sintaxe: as macros são essencialmente manipulações da árvore que constituem o seu programa.

Eu acho que Lisp tem um beijo na programação. O fato de você poder manipular a sintaxe usando macros levou a um fenômeno que o Lisp evoluiu bastante dinamicamente. Precisa de um novo recurso de idioma como - digamos, orientação a objetos - basta escrever um sistema OOP com macros!

Enquanto C foi estendido pela rotunda 2 vezes com recursos OOP (C ++, Obj. C), o Lisp foi estendido várias vezes, no final houve um vencedor.

Essa é outra peculiaridade sobre o Lisp: ele evolui (consulte Clojure e Clojurescript para uma nova e interessante mutação do lisp).

Por suas propriedades do KISS, o Lisps é favorecido como ensino de idiomas por alguns. Como Fogus descreve em sua planta de uma linguagem educacional ( http://blog.fogus.me/2013/01/21/enfield-a-programming-language-designed-for-pedagogy/ )

Para começar, acredito firmemente que, ao aprender tópicos novos e, às vezes, complexos, é totalmente prejudicial sobrecarregar os alunos com regras de sintaxe frívolas. Portanto, o Enfield é projetado com regras mínimas de sintaxe e o que é mais mínimo que uma sintaxe do Lisp.
wirrbel
fonte
2
O OP define o KISS para o contexto desta questão de maneira bastante clara: "permita que um programador médio, em condições de trabalho médias, escreva e mantenha o máximo de código possível com o mínimo esforço cognitivo" . O OP também menciona "interessados ​​em aprender sobre as intenções (documentadas) dos designers, em vez de sua opinião pessoal sobre uma linguagem de programação específica"
gnat