W słynnym eseju Richarda Gabriela The Rise of Worse is Better kontrastuje karykaturalne wersje filozofii projektowych MIT / Stanford (Lisp) i New Jersey (C / Unix) wzdłuż osi prostoty, poprawności, spójności i kompletności. Podaje przykład „problemu utraty komputera” ( omówionego gdzie indziej przez Josha Habermana ), aby argumentować, że Unix przedkłada prostotę wdrożenia nad prostotę interfejsu.
Innym przykładem, jaki wymyśliłem, są różne podejścia do liczb. Lisp może reprezentować dowolnie duże liczby (do wielkości pamięci), podczas gdy C ogranicza liczby do stałej liczby bitów (zwykle 32-64). Myślę, że to ilustruje oś poprawności.
Jakie są przykłady spójności i kompletności? Oto wszystkie opisy Gabriela (które, jak przyznaje, są karykaturami):
Podejście MIT / Stanford
- Prostota - projekt musi być prosty, zarówno pod względem implementacji, jak i interfejsu. Ważniejsze jest, aby interfejs był prosty niż implementacja.
- Prawidłowość - projekt musi być poprawny we wszystkich możliwych do zaobserwowania aspektach. Niepoprawność jest po prostu niedozwolona.
- Spójność - projekt nie może być niespójny. Projekt może być nieco mniej prosty i mniej kompletny, aby uniknąć niespójności. Spójność jest równie ważna jak poprawność.
- Kompletność - projekt musi obejmować tyle ważnych sytuacji, ile jest praktycznych. Wszystkie uzasadnione spodziewane przypadki muszą zostać uwzględnione. Prostota nie może nadmiernie zmniejszać kompletności.
Podejście New Jersey
- Prostota - projekt musi być prosty, zarówno pod względem implementacji, jak i interfejsu. Ważniejsze jest, aby implementacja była prosta niż interfejs. Prostota jest najważniejszym czynnikiem przy projektowaniu.
- Prawidłowość - projekt musi być poprawny we wszystkich możliwych do zaobserwowania aspektach. Nieco lepiej jest być prostszym niż poprawnym.
- Spójność - konstrukcja nie może być nadmiernie niespójna. W niektórych przypadkach spójność można poświęcić dla uproszczenia, ale lepiej jest porzucić te części projektu, które dotyczą mniej powszechnych okoliczności, niż wprowadzić złożoność implementacyjną lub niespójność.
- Kompletność - projekt musi obejmować tyle ważnych sytuacji, ile jest praktycznych. Należy uwzględnić wszystkie uzasadnione spodziewane przypadki. Kompletność można poświęcić na rzecz jakiejkolwiek innej jakości. W rzeczywistości należy poświęcić kompletność za każdym razem, gdy zagrożona jest prostota implementacji. Aby zachować kompletność, można zachować konsekwencję, jeśli zachowana zostanie prostota; szczególnie bezwartościowa jest spójność interfejsu.
Pamiętaj, że nie pytam, czy Gabriel ma rację (co jest pytaniem nieodpowiednim dla StackExchange), ale o przykłady tego, do czego mógł się odnosić.
źródło
Odpowiedzi:
Tytuł pytania sugeruje, że niektóre podstawowe niespójności interfejsu użytkownika mogą Cię zainteresować:
Polecenia uniksowe nie stosują żadnej określonej składni do określania opcji i flag. Na przykład większość poleceń używa pojedynczych liter poprzedzonych przez „-” jako flagę
cat -n some_file
, ale wyjątki są podobnetar tf some_file.tar
idd in=some_file out=some_other_file count=2
występują w powszechnie używanych poleceniach.Unix, jego potomkowie i krewni mają wiele nieco różnych składni wyrażeń regularnych. Powłoki używają „*”, gdy inne programy (grep, egrep, vi) używają „. *”. egrep ma „+” i „|” jako operatorzy grep nie.
Podstawowy interfejs wywołania systemowego „wszystko jest plikiem” może być postrzegany jako niekompletny: odczyt / zapis / wyszukiwanie / zamknięcie nie pasuje do każdego urządzenia we / wy. Niezwykle potrzebne wyjątki łączą się w połączenia „ioctl”, ale urządzenia takie jak karty dźwiękowe nawet nie pasują tak dobrze.
źródło
Konsystencja
Lisp ma bardzo spójną składnię, wszystkie rozszerzenia językowe można osadzać naturalnie za pomocą makr i tym podobne. Z drugiej strony C ma raczej składnię kodu, co pozwala na skorzystanie z niektórych „skrótów”, więc w niektórych przypadkach kod C wygląda na prostszy.
Kompletność
W Lisp, jeśli nie masz konkretnej funkcji językowej, której potrzebujesz, możesz ją zaimplementować samodzielnie za pomocą makr. C też ma preprocesor, ale jest raczej kłopotliwy.
źródło
Ciągi C nie mogą zawierać znaku 0, a jego funkcje biblioteczne są nieodpowiednie do obsługi danych binarnych.
Nazwy plików w systemach uniksowych nie mogą zawierać znaku 0 ani znaku 47 (ukośnik).
W oryginalnej implementacji Uniksa nazwy plików były ograniczone do 14 znaków. Późniejsze wersje złagodziły to ograniczenie; nie wyeliminowali tego.
Dodano :
E2BIG
warunek błędu systemu, gdy ktoś próbowałexec
z listą argumentów, która zawierała zbyt wiele argumentów lub zajmowała zbyt dużo pamięci lub środowisko było zbyt duże.Unix jest znany z tego rodzaju arbitralnych ograniczeń. Do czasu pojawienia się Perla w 1987 r. Obsługa dużych zestawów danych lub zestawów danych z długimi rekordami lub danymi binarnymi była wyjątkowo niewiarygodna.
źródło
/
nie jest arbitralne, konieczne jest (?) Rozwiązanie niejasności, tak jak/
separator ścieżki. Właśnie utworzyłem plik000
, najwyraźniej że w czasach współczesnego GNU / Linuksa nie ma określonych ograniczeń./
był arbitralny, jedynie ograniczenia dotyczące długości linii i rozmiaru pliku były arbitralne. Chodzi jednak o to, że inny projekt mógł zawierać nazwy plików zawierające ukośniki, ale projektanci Unixa nie uważaj to za ważne./
mnie, jestem ciekawy: zakładając, że ścieżka powinna być zakodowana jako ciąg znaków, jak to zrobić bez zastrzeżonego znaku do rozdzielenia ścieżki?path
abstrakcyjny typ danych i wykorzystując go w swoich interfejsach zamiast ujawniania konkretnej implementacji (łańcuchy ascii zakończone zerem).IIRC mój nauczyciel powiedział, że niemożność użycia
char *
zmiennych wswitch
instrukcjach w C jest kwestią niespójności, ale dla mnie była to kwestia ogólności (kompletności). Myślę, że lepiej jest używać „spójności” tylko w swoich algorytmach lub projektowaniu oprogramowania, a nie w samym języku programowania (przynajmniej nie w językach takich jak C. być może błędny język ma problem ze spójnością), ponieważ języki programowania mają solidne standardy, które definiują dziedzinę reguł i pracuj, stosując dane wejściowe do reguł. Więc jeśli coś jest niedozwolone w języku, planowane jest, aby nie było dozwolone i nie jest niezgodne w języku, IMHO.źródło
Najlepszy przykład, jaki mam, to biedny użytkownik, który miał plik o nazwie
.. -r
i wpisanyrm *
.Niezależnie od tego, czy ta historia jest prawdziwa, czy nie, stała się klasyką hejtera uniksowego.
Zobacz The Unix-Haters Handbook , który zawiera wprowadzenie samego Dennisa Ritchiego, dla wielu takich przykładów.
Dodam ponadto, że unikanie tego typu problemów było główną siłą w projektowaniu Microsoft Power Shell.
źródło
OTOH, fakt, że powłoka rozszerza globusy, a nie progam, eliminuje wiele irytujących niekonsekwencji obecnych w innych systemach. To samo dotyczy faktu, że możesz użyć tego samego polecenia do skopiowania pliku z jednego miejsca do drugiego w pliku, na dyskietce lub z dysku Zip na taśmę.
Tak więc, Unix jest niespójny. Podobnie jak inne systemy, po prostu inaczej ;-)
źródło
LISP obsługujący nieskończone liczby precyzji w porównaniu do C obsługujący tylko liczby całkowite maszynowe nie jest przykładem „poprawności” języka. Jest to prosta kwestia wynikająca z faktu, że języki miały bardzo różne cele projektowe.
Punkt C miał być językiem zbliżonym do maszyny, który mógłby zostać wykorzystany do wdrożenia systemów operacyjnych. Maszyny (głównie) nie obsługują liczb dziesiętnych o nieskończonej precyzji. Maszyny (głównie) mają liczby całkowite o stałej długości bitów.
źródło