English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

gość
1 / ?
powrót do lekcji

Programowanie w kodzie binarnym bezwzględnym

Pierwsi programiści pisali w kodzie binarnym bezwzględnym: każda instrukcja & każdy adres w surowych cyfrach binarnych. Pojedyncza instrukcja mogła wyglądać jak 01100101 00001010 — kod instrukcji & adres w pamięci w kodzie binarnym.

Problem kodu spaghetti

Gdy błąd wymagał wstawienia nowej instrukcji, programiści stanęli przed dylematem. Wstawienie na miejscu oznaczało, że każdy następny adres instrukcji przesunął się o jeden — wymagając od programisty aktualizacji każdego odwołania do adresu w całym programie. Katastrofalne.

Rozwiązanie: zastąpić instrukcję tuż przed punktem wstawienia skokiem do pustej pamięci. W tej pustej lokalizacji: napisać przesłonięta instrukcję, dodać nowe instrukcje, a następnie wrócić. Gdy błędy pojawiły się w poprawkach, zastosować tę samą sztuczkę ponownie, używając innej pustej pamięci.

Wynik: ścieżka wykonania przez program przeskoczyła na pozornie losowe lokalizacje. Hamming nazwał to 'puszką spaghetti'. Ścieżka przepływu kontroli, narysowana na papierze, wyglądała dokładnie jak splątane spaghetti.

Drogi wyjścia

Dwie bezpośrednie ulepszenia: notacja ósemkowa (grupowanie cyfr binarnych w zestawy po 3) i szesnastkowa (grupy po 4, używając A–F dla wartości powyżej 9). Te zmniejszyły błędy pisania, ale nie rozwiązały fundamentalnego problemu adresowania.

Asembler symboliczny (np. SAP firmy IBM — Symbolic Assembly Program — i SOAP — Symbolic Optimizing Assembly Program na IBM 650) umożliwił programistom pisanie nazw instrukcji (ADD, MOVE) i symbolicznych etykiet adresowych zamiast kodu binarnego. Asembler przetłumaczył na kod binarny w momencie wejścia, automatycznie zarządzając przypisywaniem adresów.

SOAP wykonał dodatkową optymalizację: układał instrukcje na obracającym się bębnie, aby następna instrukcja dotarła do głowicy odczytującej dokładnie wtedy, gdy poprzednia się zakończyła — kodowanie o minimalnym opóźnieniu. SOAP nawet kompilował się sam: program A przetwarzany jako dane wytwarzał B, a B uruchamiany na A mierzył, jak wiele samokopiacja go poprawiła.

Drzewo rozboru & Hierarchia języków

Biblioteki & Kod relokacyjny

Hamming zauważył, że idea oprogramowania do ponownego użytku (bibliotek matematycznych) pojawiła się bardzo wcześnie — Babbage to sobie wyobraził. Problem: biblioteka o adresach bezwzględnych wymagała, aby każda procedura zajmowała te same lokalizacje pamięci za każdym razem, gdy była używana. Gdy łączna biblioteka rosła zbyt duża, programy konkurowały o te same adresy.

Rozwiązanie: kod relokacyjny. Asembler generuje instrukcje, które odnoszą się do pamięci względnie — przesunięcia od adresu bazowego — zamiast adresów bezwzględnych. Konsolidator rozwiązuje ostateczne adresy w momencie załadowania.

Niepublikowane raporty Von Neumann'a (szeroko rozpowszechniane) opisywały niezbędne sztuczki programistyczne. Pierwsza opublikowana książka programistyczna (Wilkes, Wheeler & Gill, EDSAC, 1951) skodyfikowała te techniki.

Wyjaśnij, dlaczego biblioteki o adresach bezwzględnych stworzyły problem skalowalności i jak kod relokacyjny go rozwiązał. Jaka konkretna właściwość adresów bezwzględnych spowodowała kolizję i co technicznie oznacza 'relokacyjny'?

Rozwidlenie w projektowaniu języka

FORTRAN (1957, IBM) i ALGOL (1958, międzynarodowy komitet) reprezentują dwie filozofie projektowania, które wyprodukowały radykalnie różne wyniki.

FORTRAN

John Backus kierował projektem FORTRAN (FORmula TRANslation) w IBM. Cel projektowania: ułatwić korzystanie z języka naukowcom & inżynierom. FORTRAN akceptował notację matematyczną, która wydawała się naturalna dla swoich użytkowników: A = B + C * D zamiast ADD B, C; STORE T; MULTIPLY T, D; STORE A.

FORTRAN przetrwał ponad 60 lat. Pozostaje w aktywnym użytkowaniu w obliczeniach naukowych, dynamice płynów, modelowaniu klimatu & fizyce obliczeniowej. Hamming zauważył tę trwałość jako dowód udanego projektowania.

ALGOL

ALGOL (ALGOrithmic Language) został zaprojektowany przez komitet logików & informatyków zmierzających do matematycznej rygorystyczności: logicznie czysty, formalnie definiowalny język. Notacja Backusa-Naura (BNF) do opisywania gramatyk została wynaleziona do specyfikacji ALGOL.

ALGOL zawiódł w praktyce. Pomimo jego logicznej elegancji & jego ogromnego wpływu na późniejsze projektowanie języka (Pascal, C, & prawie każdy współczesny język pochodzi z koncepcji gramatyki ALGOL), sam ALGOL nigdy nie został szeroko wdrożony. Werdykt Hamminga: logicznie zaprojektowany, humanistycznie niemożliwy w użyciu.

Hierarchia języków

Hamming opisał naturalną hierarchię od kodu maszynowego przez asembler, języki wyższego poziomu, & ostatecznie 'język zorientowany na problem' bliski temu, jak praktycy myślą o swojej domenie problemu. Każdy poziom dodaje czytelność dla człowieka kosztem efektywności maszyny.

Cztery kryteria projektowania języka Hamminga

Hamming zdystylizował lekcję z FORTRAN vs ALGOL do czterech kryteriów dla udanego języka programowania:

1. Łatwy do nauki — nowicjusz może szybko stać się produktywny

2. Łatwy w użyciu — rutynowe zadania wymagają minimalnej ceremonii

3. Łatwy do debugowania — błędy wytwarzają znaczące, lokalizowalne komunikaty

4. Łatwy w użyciu podprogramów — ponowne użycie & abstrakcja nie wymagają heroicznych wysiłków

Dodał obserwację strukturalną: język ludzki nosi około 60% redundancji; język pisany około 40%. Języki o niskiej redundancji (takie jak APL) wytwarzają eleganckie jednowiersze, które eksperci uważają za piękne & początkujących za niezrozumiałe — & które zawierają niewidoczne błędy, gdy pojedynczy znak zmienia znaczenie.

Implikacja: język zaprojektowany dla logicznej elegancji optymalizuje dla złego czytelnika. Programista jest człowiekiem; ludzie potrzebują redundancji, aby wychwycić błędy & wyjaśnić intencję.

Zastosuj cztery kryteria Hamminga do języka programowania, który znasz dobrze. Oceń każde kryterium na skali 1–5 (5=doskonały). Następnie zidentyfikuj, które kryterium, jeśli zostanie wzmocnione, będzie najbardziej poprawiać język — i wyjaśnij, jak wyglądałaby konkretna zmiana.

Psychologiczne vs logiczne projektowanie języka

Hamming powrócił do kontrastu FORTRAN/ALGOL jako lekcji z dynamiki instytucjonalnej & ludzkiej, a nie tylko projektowania języka.

FORTRAN był zaprojektowany psychologicznie — dla ludzi, którzy by go używali, konkretnie naukowców, którzy myśleli w notacji matematycznej. ALGOL był zaprojektowany logicznie — dla poprawności formalnej & eleganckiej teoretycznie.

Paradoks, który zidentyfikował Hamming: język logicznie poprawny, któremu ludzie się opierają, zawodzi; język pragmatycznie zaprojektowany, który ludzie przyjmują, odnosi sukces, nawet jeśli jest logicznie bardziej chaotyczny.

Przytoczył APL jako skrajny przypadek: logicznie elegancki, wyrażalny w jednowierszach, z własnym zestawem specjalnych znaków. Eksperci go kochali. Zwykli programiści uważali go za nieczytelny. Pojedyncza zmiana znaku mogła cicho przekształcić znaczenie programu. APL ma małą oddaną społeczność & prawie zero użytku w głównym nurcie.

Argument redundancji ludzkiej: mowa ~60% redundantna (powtórzone kontekst, wyjaśniające słowa, przewidywalna struktura). Język pisany ~40% redundantny. Ta redundancja służy wykrywaniu błędów — ludzie są zawodnicy, więc język ewoluował, aby nosić wystarczającą ilość powtórzonych informacji, aby wychwycić & poprawić błędy. Język o niskiej redundancji usuwa tę sieć bezpieczeństwa.

Hierarchia kompilatora

Hamming opisał warstwy kompilator/interpreter: program może czytać w języku wyższego poziomu & tłumaczyć go na język niższego poziomu. Stosy te warstwy — każda tłumaczy jeden poziom niżej. Na szczycie: język specjalizowany dla domeny, w której eksperci w dziedzinie (biologia, finanse, fizyka) piszą naturalnie. Na dnie: kod maszynowy. Każde przejście to kompilator lub interpreter.

Przewidywanie przetrwania języka

Do 1993 roku Hamming obserwował, że wiele języków odniosło sukces & zawiodło. FORTRAN (1957) przetrwał. ALGOL (1958) zawiódł. COBOL (1959) przetrwał dziesięciolecia w obliczeniach biznesowych. LISP (1958) przetrwał w badaniach AI. PL/I (1964) próbował ujednolicić wszystko & zawiódł.

Używając rozróżnienia Hamminga między projektowaniem psychologicznym a logicznym i jego czterech kryteriów, wyjaśnij, dlaczego jeden znany Ci język rozwijał się & jeden zawiódł (lub się zawodzi). Twoje wyjaśnienie powinno identyfikować konkretne czynniki ludzkie, które doprowadziły do przyjęcia lub odrzucenia — nie tylko właściwości techniczne.

Powtarzający się wzór

Rozdział historii oprogramowania Hamminga zawiera powtarzającą się strukturę:

1. Istnieje bolesne ograniczenie (adresy bezwzględne, notacja binarna, niemająca do utrzymania kod)

2. Ktoś wynalazł warstwę abstrakcji, która ukrywa ograniczenie

3. Abstrakcja umożliwia nową skalę, która tworzy nowe bolesne ograniczenia

4. Powtórz

Binarny → ósemkowy/szesnastkowy → asembler symboliczny → FORTRAN → programowanie strukturalne → języki obiektowe → języki specjalizowane dla domeny. Każda warstwa rozwiązuje najbardziej ostry ból poprzednika, zamiast wprowadzać nową klasę problemu.

Problem kodu spaghetti (adresy bezwzględne) prowadził do asemblera symbolicznego. Duże programy asemblerowe doprowadziły do FORTRAN. Duże programy FORTRAN doprowadziły do programowania strukturalnego & później do orientacji obiektowej. Wykład Hamminga skończył się przed tymi późniejszymi przejściami, ale wzór się kontynuuje.

Jego lekcja dla inżynierów: zawsze rozwiązujesz ból ujawniony przez poprzednią abstrakcję. Zrozumienie warstwy, na której się znajdujesz, wymaga wiedzy o tym, dlaczego warstwa poniżej istnieje.

Zidentyfikuj warstwę abstrakcji oprogramowania, z którą regularnie pracujesz. Jakie bolesne ograniczenie w warstwie poniżej niej ukrywa? I jaką nową klasę problemów wprowadza Twoja obecna warstwa — jaki ból będzie musiał rozwiązać następna warstwa powyżej?