Quali sono esempi di incoerenza e incompletezza in Unix / C?


20

Nel famoso saggio di Richard Gabriel, The Rise of Worse is Better , contrappone versioni caricate delle filosofie di design del MIT / Stanford (Lisp) e del New Jersey (C / Unix) lungo gli assi della semplicità, correttezza, coerenza e completezza. Fornisce l'esempio del "problema di perdita del PC" ( discusso altrove da Josh Haberman ) per sostenere che Unix privilegia la semplicità dell'implementazione piuttosto che la semplicità dell'interfaccia.

Un altro esempio che ho trovato sono i diversi approcci ai numeri. Lisp può rappresentare numeri arbitrariamente grandi (fino alla dimensione della memoria), mentre C limita i numeri a un numero fisso di bit (in genere 32-64). Penso che questo illustri l'asse di correttezza.

Quali sono alcuni esempi di coerenza e completezza? Ecco tutte le descrizioni di Gabriel (che ammette siano caricature):

L'approccio MIT / Stanford

  • Semplicità: il design deve essere semplice, sia nell'implementazione che nell'interfaccia. È più importante che l'interfaccia sia semplice rispetto all'implementazione.
  • Correttezza: il design deve essere corretto in tutti gli aspetti osservabili. L'errata correttezza non è semplicemente consentita.
  • Coerenza: il design non deve essere incoerente. Un design può essere leggermente meno semplice e meno completo per evitare incoerenze. La coerenza è importante quanto la correttezza.
  • Completezza: il progetto deve coprire tutte le situazioni importanti che è pratico. Tutti i casi ragionevolmente previsti devono essere coperti. La semplicità non può ridurre eccessivamente la completezza.

L'approccio del New Jersey

  • Semplicità: il design deve essere semplice, sia nella realizzazione che nell'interfaccia. È più importante che l'implementazione sia semplice dell'interfaccia. La semplicità è la considerazione più importante in un design.
  • Correttezza: il design deve essere corretto in tutti gli aspetti osservabili. È leggermente meglio essere semplici che corretti.
  • Coerenza: il design non deve essere eccessivamente incoerente. La coerenza può essere sacrificata per semplicità in alcuni casi, ma è meglio abbandonare quelle parti del progetto che affrontano circostanze meno comuni piuttosto che introdurre complessità implementativa o incoerenza.
  • Completezza: il progetto deve coprire tutte le situazioni importanti che è pratico. Tutti i casi ragionevolmente previsti dovrebbero essere coperti. La completezza può essere sacrificata a favore di qualsiasi altra qualità. In effetti, la completezza deve essere sacrificata ogni volta che viene compromessa la semplicità di implementazione. La coerenza può essere sacrificata per ottenere completezza se viene mantenuta la semplicità; particolarmente inutile è la coerenza dell'interfaccia.

Nota: non sto chiedendo se Gabriel abbia ragione (che non è una domanda appropriata per StackExchange) ma per esempi di ciò a cui si sarebbe potuto riferire.


6
Nel caso in cui tu sia curioso, questo non è un problema a casa. Io sono l'insegnante :-) A pensarci bene, forse questo fa di me i compiti.
Ellen Spertus,

4
Faccio fatica a capire perché questa domanda non è su Unix e Linux (o forse sull'ingegneria del software ?). Puoi approfondire in che modo hai bisogno di una prospettiva CS in materia? Inoltre, chiarisci se desideri esempi positivi o negativi.
Raffaello

Questa domanda non è più adatta su programmers.stackexchange.com ?
Basile Starynkevitch,

L'ho pubblicato su CS perché considero il design del linguaggio come una delle aree profonde fondamentali dell'informatica, che comprende computabilità, complessità, architettura, usabilità, ecc. Avrei potuto pubblicarlo su Unix / Linux, anche se stavo cercando un più ampio Visualizza. Per quanto riguarda i programmatori, le persone sono quasi sempre ostili con me quando pubblico lì, anche quando penso di essere in argomento, quindi sto lontano da lì.
Ellen Spertus,

Risposte:


15

Il titolo della domanda suggerisce che alcune incongruenze di base dell'interfaccia utente potrebbero interessarti:

I comandi Unix non seguono alcuna sintassi particolare per specificare opzioni e flag. Ad esempio, la maggior parte dei comandi usa lettere singole precedute da '-' come flag:, cat -n some_filema eccezioni simili tar tf some_file.tared dd in=some_file out=some_other_file count=2esistono nei comandi di uso comune.

Unix e i suoi discendenti e parenti hanno più sintassi di espressioni regolari leggermente diverse. Le shell usano "*" dove altri programmi (grep, egrep, vi) usano '. *'. egrep ha '+' e '|' come operatori, grep no.

L'interfaccia di chiamata di sistema "tutto è un file" potrebbe essere vista come incompleta: read / write / seek / close non si adatta a tutti i dispositivi I / O. Le eccezioni gravemente necessarie vengono inglobate nelle chiamate "ioctl", ma i dispositivi come le schede audio non si adattano molto bene.


Bella risposta. Quando ho visto il titolo ho pensato subito a "ioctl" (e fcntl) ma ora non devo digitare una risposta.
Louis,

1
i pattern glob non sono regexs
jk.

8

Consistenza

Lisp ha una sintassi molto coerente, tutte le estensioni di lingua possono essere incorporate naturalmente tramite macro e simili. C, d'altra parte, ha una sintassi piuttosto di codice, che consente di prendere alcune "scorciatoie", quindi in alcuni casi il codice C sembra effettivamente più semplice.

Completezza

In Lisp, se non disponi di una funzione linguistica specifica di cui hai bisogno, puoi implementarla tu stesso con le macro. Anche C ha un preprocessore, ma è piuttosto sconcertante.


8

Le stringhe di C non possono contenere il carattere 0 e le sue funzioni di libreria non sono adatte per gestire i dati binari.

I nomi di file sui sistemi Unix non possono contenere il carattere 0 o il carattere 47 (la barra).

Nell'implementazione originale di Unix, i nomi dei file erano limitati a 14 caratteri. Le versioni successive hanno solo attenuato questa limitazione; non l'hanno eliminato.

Aggiunto : la E2BIGcondizione di errore di sistema, quando si tentava di execelencare un argomento con troppi argomenti o occupava troppa memoria o un ambiente troppo grande.

Unix è noto per questo tipo di limitazione arbitraria. Fino all'avvento di Perl nel 1987, la gestione di set di dati di grandi dimensioni o set di dati con record lunghi o dati binari era estremamente inaffidabile.


Non consentire /non è arbitrario, è necessario (?) Risolvere le ambiguità come /è il separatore di percorso. Ho appena creato un file 000, apparentemente quella specifica restrizione è andata ai tempi di un moderno GNU / Linux.
Raffaello

Non intendevo dire che il divieto di /era arbitrario, solo che i limiti di lunghezza della linea e dimensione del file erano arbitrari. Il punto, tuttavia, è che un design diverso avrebbe potuto consentire ai nomi di file di contenere barre, ma i progettisti di Unix non lo fecero consideralo importante.
Mark Dominus,

Sono sicuro che all'epoca quei limiti erano stati introdotti a causa di considerazioni sulle prestazioni; anche le tecniche non sviluppate possono giocare. Dal punto di vista di oggi, sembrano discutibili, questo è certo. Per quanto /mi riguarda , sono curioso: supponendo che un percorso debba essere codificato come stringa, come si fa senza un carattere riservato per la separazione del percorso?
Raffaello

Non capisco quale sia il tuo punto. La domanda chiede "esempi di incoerenza e incompletezza in Unix / C"; non menziona le prestazioni.
Mark Dominus,

1
@Raphael: ti sbarazzi dei problemi del separatore sciocco definendo un pathtipo di dati astratto e lo usi nelle tue interfacce invece di esporre una particolare implementazione (stringhe ASCII con terminazione nulla).
Wandering Logic,

4

IIRC il mio insegnante ha affermato che l'incapacità di usare le char *variabili nelle switchdichiarazioni in C è una questione di incoerenza, ma per me quella era una questione di generalità (completezza). Penso che sia meglio usare la "coerenza" solo nei tuoi algoritmi o nella progettazione del software non nel linguaggio di programmazione stesso (almeno non in linguaggi come C. forse un linguaggio difettoso ha problemi di coerenza), perché i linguaggi di programmazione hanno standard solidi che definiscono il dominio delle regole e funziona applicando input alle regole. Quindi, se qualcosa non è permesso nella lingua, ha pianificato di non essere permesso e non è incoerenza nella lingua, IMHO.


  1. Ho usato la generalità come completezza. penso che siano la stessa cosa. forse sto sbagliando.
  2. Questa non è una risposta. forse un suggerimento o la mia opinione.

3

Il miglior esempio che ho è il povero utente che aveva un file chiamato .. -re digitato rm *.

Che questa storia sia vera o no, è diventata un classico per chi odia Unix.

Vedi il Manuale di Unix-Haters , che ha un'introduzione dello stesso Dennis Ritchie, per molti di questi esempi.

Aggiungerò inoltre che evitare questo tipo di problemi è stata una forza importante nella progettazione di Microsoft Power Shell.


Ho letto il saggio di Richard Gabriel sul retro di The Unix-Haters Handbook. :-)
Ellen Spertus il

3
  • Certamente la miriade di significati delle stesse (brevi) bandiere sui comandi è un'incoerenza.
  • Ogni programma che utilizza espressioni regolari ha la propria sintassi per loro
  • I file di configurazione per i servizi sono tutti sintassi differenti (che possono essere perdonati in parte, il tuo demone mailer ha poco in comune con il tuo server web o l'avvio del sistema, ma comunque)
  • Ci sono diversi editor! Gli utenti usano shell diverse !! Perché ci sono così tanti ambienti desktop?!?

OTOH, il fatto che la shell espanda i globs, e non il programma, elimina molte incoerenze irritanti presenti in altri sistemi. Idem il fatto che è possibile utilizzare lo stesso comando per copiare un file da una posizione all'altra nel file system, su un dischetto o da un disco Zip su nastro.

Quindi sì, Unix è incoerente. Quindi sono gli altri sistemi, in modo diverso ;-)


2

LISP che supporta numeri di precisione infiniti rispetto a C che supporta solo numeri interi di macchine non è un esempio di "correttezza" del linguaggio. È una questione semplice derivante dal fatto che le lingue avevano obiettivi di progettazione molto diversi.

Il punto di C doveva essere un linguaggio vicino alla macchina che potesse essere usato per implementare sistemi operativi. Le macchine (principalmente) non supportano numeri decimali di precisione infinita. Le macchine (principalmente) hanno numeri interi di lunghezze di bit fisse.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.