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.
Respostas:
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
Enquanto loop
Tradicional para loop
Foreach loop
Interruptor multiuso
Retorno múltiplo
Interfaces
Incorporação
Canais
Pode ser usado para implementar semáforos
Usado para passagem de mensagens entre threads
Pode ser usado para manipular eventos assíncronos
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:
Você precisa usar chaves:
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:
fonte
for i=1 to 10
for item in group
for i = 1 to 10
é sei
um dia será 10. Isso pode depender da linguagem (o bash inclui 10, o python não). O loop for tradicional é universal.Eu acho que o Zen do Python indicará por que o Python é uma linguagem simples muito melhor do que eu:
Editar em resposta a @Giorgio
Como afirma sua pergunta,
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.
fonte
import this
comandoUma 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.
fonte
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:
De " História do Tcl " - http://www.tcl.tk/about/history.html
fonte
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.
É 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.
fonte
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.
fonte
É 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
fonte
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ê escrever
a + 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 + b
pode 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 gravar
data[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
int
eint*
são, fica claro o queint**
deve ser. Compare isso com as referências C ++, onde você não tem absolutamente nenhuma idéia do queint&&
é dado o significado deint
eint&
!)É 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.
fonte
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.
fonte
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:
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 em
impossiblyfound_basefunction()
Na minha opinião, simplicidade é consistência.
fonte
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:
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:
Pode ser uma chamada de método, como
bem como um ramo if, loop etc.
(todo o código aqui é independente de pseudo-Lisp / Dialeto)
A forma
também pode ser interpretado como uma lista
E essa é a base da simplicidade e beleza dos Lisps. Como as listas aninhadas (como no
if
exemplo 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/ )
fonte