No famoso ensaio de Richard Gabriel, The Rise of Worse is Better , ele contrasta versões caricaturadas das filosofias de design do MIT / Stanford (Lisp) e Nova Jersey (C / Unix) ao longo dos eixos da simplicidade, correção, consistência e perfeição. Ele dá o exemplo do "problema de perdedor de PC" ( discutido em outro lugar por Josh Haberman ) para argumentar que o Unix prioriza a simplicidade de implementação em detrimento da simplicidade de interface.
Outro exemplo que inventei são as diferentes abordagens dos números. O Lisp pode representar números arbitrariamente grandes (até o tamanho da memória), enquanto C limita os números a um número fixo de bits (geralmente 32 a 64). Eu acho que isso ilustra o eixo de correção.
Quais são alguns exemplos de consistência e integridade? Aqui estão todas as descrições de Gabriel (que ele admite serem caricaturas):
A abordagem do MIT / Stanford
- Simplicidade - o design deve ser simples, tanto na implementação quanto na interface. É mais importante que a interface seja simples que a implementação.
- Correção - o projeto deve estar correto em todos os aspectos observáveis. Incorretividade simplesmente não é permitida.
- Consistência - o design não deve ser inconsistente. É permitido que um design seja um pouco menos simples e menos completo para evitar inconsistências. A consistência é tão importante quanto a correção.
- Completude - o design deve abranger o maior número possível de situações importantes. Todos os casos razoavelmente esperados devem ser cobertos. A simplicidade não pode reduzir excessivamente a integridade.
A abordagem de Nova Jersey
- Simplicidade - o design deve ser simples, tanto na implementação quanto na interface. É mais importante que a implementação seja simples que a interface. Simplicidade é a consideração mais importante em um design.
- Correção - o projeto deve estar correto em todos os aspectos observáveis. É um pouco melhor ser simples do que correto.
- Consistência - o design não deve ser excessivamente inconsistente. A consistência pode ser sacrificada pela simplicidade em alguns casos, mas é melhor descartar as partes do design que lidam com circunstâncias menos comuns do que introduzir complexidade ou inconsistência na implementação.
- Completude - o design deve abranger o maior número possível de situações importantes. Todos os casos razoavelmente esperados devem ser cobertos. A integridade pode ser sacrificada em favor de qualquer outra qualidade. De fato, a integridade deve ser sacrificada sempre que a simplicidade da implementação é comprometida. A consistência pode ser sacrificada para alcançar a integridade se a simplicidade for mantida; especialmente inútil é a consistência da interface.
Observe que não estou perguntando se Gabriel está certo (que é uma pergunta não apropriada para o StackExchange), mas para exemplos do que ele pode estar se referindo.
fonte
Respostas:
O título da pergunta sugere que algumas inconsistências básicas da interface do usuário podem lhe interessar:
Os comandos Unix não seguem nenhuma sintaxe específica para especificar opções e sinalizadores. Por exemplo, a maioria dos comandos usa letras únicas precedidas por '-' como sinalizador
cat -n some_file
:, mas exceções comotar tf some_file.tar
edd in=some_file out=some_other_file count=2
existem nos comandos comumente usados.O Unix e seus descendentes e parentes têm várias sintaxes de expressão regular ligeiramente diferentes. Os shells usam "*" onde outros programas (grep, egrep, vi) usam '. *'. O egrep possui '+' e '|' como operadores, o grep não.
A interface básica de chamada do sistema "tudo é um arquivo" pode ser vista como incompleta: leitura / gravação / busca / fechamento não se encaixa em todos os dispositivos de E / S. As exceções muito necessárias são agrupadas nas chamadas "ioctl", mas dispositivos como placas de som nem se encaixam muito bem.
fonte
Consistência
O Lisp tem uma sintaxe muito consistente, todas as extensões de idioma podem ser incorporadas naturalmente via macros e tal. C, por outro lado, possui uma sintaxe de código, que permite a utilização de alguns "atalhos"; portanto, em alguns casos, o código C parece realmente mais simples.
Completude
No Lisp, se você não possui um recurso específico de idioma, precisa implementá-lo com macros. C também possui pré-processador, mas é bastante desconcertante.
fonte
As strings de C não podem conter o caractere 0 e suas funções de biblioteca não são adequadas para lidar com dados binários.
Os nomes de arquivos nos sistemas Unix não podem conter o caractere 0 ou 47 (a barra).
Na implementação original do Unix, os nomes de arquivos eram limitados a 14 caracteres. Versões posteriores apenas relaxaram essa limitação; eles não o eliminaram.
Adicionado : a
E2BIG
condição de erro do sistema, quando alguém tentavaexec
com uma lista de argumentos com muitos argumentos ou ocupava muita memória ou um ambiente muito grande.O Unix é notório por esse tipo de limitação arbitrária. Até o advento do Perl, em 1987, o manuseio de grandes conjuntos de dados, ou conjuntos de dados com registros longos ou dados binários, era extremamente confiável.
fonte
/
não é arbitrário, é necessário (?) Resolver ambiguidades como/
é o separador de caminho. Acabei de criar um arquivo000
, aparentemente essa restrição específica desapareceu nos dias de um GNU / Linux moderno./
era arbitrária, apenas que o comprimento da linha e os limites de tamanho do arquivo eram arbitrários. O ponto, no entanto, é que um design diferente poderia ter permitido que os nomes de arquivos contivessem barras, mas os designers do Unix não considere importante./
, estou curioso: assumindo que um caminho deve ser codificado como string, como você faz isso sem um caractere reservado para a separação de caminhos?path
tipo de dados abstratos e usa-o em suas interfaces em vez de expor uma implementação específica (seqüências ascii terminadas em nulo).IIRC meu professor disse que a incapacidade de usar
char *
variáveis nasswitch
declarações em C é uma questão de inconsistência, mas para mim isso foi questão de generalidade (completude). Eu acho que é melhor usar "consistência" apenas nos seus algoritmos ou design de software, não na própria linguagem de programação (pelo menos não em linguagens como C. talvez uma linguagem de buggy tenha problema de consistência), porque as linguagens de programação têm padrões sólidos que definem o domínio das regras e trabalhe aplicando informações às regras. Portanto, se algo não é permitido na linguagem, planejou não ser permitido e não é inconsistência na linguagem, IMHO.fonte
O melhor exemplo que tenho é o usuário pobre que teve um arquivo nomeado
.. -r
e digitadorm *
.Se essa história é verdadeira ou não, tornou-se o clássico de um odiador do Unix.
Veja The Unix-Haters Handbook , que tem uma introdução do próprio Dennis Ritchie, para muitos desses exemplos.
Acrescentarei ainda que evitar esse tipo de problema foi uma força importante no design do Power Shell da Microsoft.
fonte
OTOH, o fato de o shell expandir os globs, e não o programa, elimina muitas inconsistências irritantes presentes em outros sistemas. Ademais, é possível usar o mesmo comando para copiar um arquivo de um lugar para outro no arquivo de arquivo, para um disquete ou de um disco Zip para fita.
Então, sim, o Unix é inconsistente. Assim como os outros sistemas, apenas de forma diferente ;-)
fonte
O LISP que suporta números de precisão infinitos versus C que suporta apenas números inteiros da máquina não é um exemplo de 'correção' da linguagem. É uma questão simples decorrente do fato de as linguagens terem objetivos de design muito diferentes.
O objetivo de C era ser uma linguagem próxima à máquina que pudesse ser usada para implementar sistemas operacionais. Máquinas (principalmente) não suportam números decimais de precisão infinita. Máquinas (principalmente) possuem números inteiros de comprimentos de bits fixos.
fonte