Literackie programowanie - Literate programming

Literate Programming autorstwa Donalda Knutha jest przełomową książką o piśmiennym programowaniu

Programowanie literat jest paradygmat programowania wprowadzony przez Donald Knuth w którym program komputerowy podaje się wyjaśnienie jego logiki w języku naturalnym , takich jak angielski, z przerwami fragmentów z makr i tradycyjnego kodu źródłowego , z którego compilable może zostać wygenerowany kod źródłowy. Podejście to jest rutynowo stosowane w obliczeniach naukowych i nauce o danych do powtarzalnych badań i celów otwartego dostępu . Literackie narzędzia programistyczne są dziś używane przez miliony programistów.

Paradygmat programowania piśmiennego, w rozumieniu Knutha, reprezentuje odejście od pisania programów komputerowych w sposób i porządek narzucony przez komputer, a zamiast tego umożliwia programistom tworzenie programów w porządku wymaganym przez logikę i przepływ ich myśli. Programy piśmienne są pisane jako nieprzerwana ekspozycja logiki w zwykłym ludzkim języku , podobnie jak tekst eseju , w którym zawarte są makra, aby ukryć abstrakcje i tradycyjny kod źródłowy .

Narzędzia piśmiennego programowania (LP) służą do uzyskania dwóch reprezentacji z piśmiennego pliku źródłowego: jednej odpowiedniej do dalszej kompilacji lub wykonania przez komputer, „zaplątanego” kodu i drugiej do przeglądania jako sformatowanej dokumentacji , o której mówi się, że jest „utkana”. " z piśmiennego źródła. Podczas gdy pierwsza generacja piśmiennych narzędzi programistycznych była specyficzna dla języka komputerowego , późniejsze są niezależne od języka i istnieją ponad językami programowania.

Historia i filozofia

Programowanie literackie zostało po raz pierwszy wprowadzone przez Knutha w 1984 roku. Główną intencją tego podejścia było traktowanie programu jako literatury zrozumiałej dla ludzi. Takie podejście zostało wdrożone na Uniwersytecie Stanforda w ramach badań nad algorytmami i typografią cyfrową . Ta implementacja została nazwana „ WEB ” przez Knutha, ponieważ uważał, że jest to jedno z niewielu trzyliterowych słów w języku angielskim, które nie zostały jeszcze zastosowane w informatyce. Jednak słusznie przypomina skomplikowaną naturę oprogramowania delikatnie poskładanego z prostych materiałów. W latach 2010-tych nastąpił znaczny powrót do praktyki programowania piśmiennego z wykorzystaniem notebooków, zwłaszcza w nauce o danych .

Pojęcie

Programowanie literackie to pisanie logiki programu w ludzkim języku z dołączonymi (oddzielonymi prymitywnymi znacznikami) fragmentami kodu i makrami. Makra w piśmiennym pliku źródłowym są po prostu podobnymi do tytułu lub objaśniającymi frazami w ludzkim języku, które opisują ludzkie abstrakcje utworzone podczas rozwiązywania problemu programistycznego i ukrywają fragmenty kodu lub makra niższego poziomu. Te makra są podobne do algorytmów w pseudokodzie zwykle używanych w nauczaniu informatyki . Te arbitralne frazy wyjaśniające stają się precyzyjnymi nowymi operatorami, tworzonymi w locie przez programistę, tworząc metajęzyk na wierzchu podstawowego języka programowania.

Preprocesora służy zastąpić dowolne hierarchie, albo raczej „połączone ze sobą«wstęgi»makr”, w celu uzyskania kodu źródłowego compilable z jednego polecenia ( „gąszczu”) oraz dokumentacji z innego ( „splot”). Preprocesor daje również możliwość wypisania zawartości makr i dodania do już utworzonych makr w dowolnym miejscu w tekście pliku źródłowego programu umiejącego czytać, eliminując tym samym konieczność pamiętania o ograniczeniach nałożonych przez tradycyjne języki programowania lub przerwać tok myśli.

Zalety

Według Knutha, piśmienne programowanie zapewnia programy wyższej jakości, ponieważ zmusza programistów do wyraźnego określenia myśli kryjących się za programem, czyniąc słabo przemyślane decyzje projektowe bardziej oczywistymi. Knuth twierdzi również, że piśmienne programowanie zapewnia pierwszorzędny system dokumentacji, który nie jest dodatkiem, ale rozwija się naturalnie w procesie eksponowania własnych myśli podczas tworzenia programu. Powstała dokumentacja pozwala autorowi na ponowne rozpoczęcie własnych procesów myślowych w dowolnym późniejszym czasie, a innym programistom ułatwia zrozumienie konstrukcji programu. Różni się to od tradycyjnej dokumentacji, w której programista otrzymuje kod źródłowy zgodny z kolejnością narzuconą przez kompilator i musi odszyfrować proces myślowy stojący za programem na podstawie kodu i powiązanych z nim komentarzy. Uznaje się również, że metajęzykowe możliwości piśmiennego programowania ułatwiają myślenie, dając lepszy „widok z lotu ptaka” na kod i zwiększając liczbę pojęć, które umysł może z powodzeniem zachować i przetworzyć. Przydatność tej koncepcji do programowania na dużą skalę, do programów klasy komercyjnej, potwierdza edycja kodu TeX jako programu piśmiennego.

Knuth twierdzi również, że piśmienne programowanie może prowadzić do łatwego przenoszenia oprogramowania do wielu środowisk, a nawet przytacza implementację TeXa jako przykład.

Kontrast z generowaniem dokumentacji

Programowanie literackie jest bardzo często błędnie rozumiane jako odniesienie tylko do sformatowanej dokumentacji utworzonej ze wspólnego pliku z kodem źródłowym i komentarzami – co właściwie nazywa się generowaniem dokumentacji – lub do obszernych komentarzy dołączonych do kodu. Jest to odwrotność programowania piśmiennego: dobrze udokumentowany kod lub dokumentacja wyodrębniona z kodu jest zgodna ze strukturą kodu, z dokumentacją osadzoną w kodzie; podczas gdy w programowaniu piśmiennym kod jest osadzony w dokumentacji, przy czym kod jest zgodny ze strukturą dokumentacji.

To błędne przekonanie doprowadziło do twierdzenia, że ​​narzędzia do ekstrakcji komentarzy, takie jak systemy Perl Plain Old Documentation lub Java Javadoc , są „narzędziami programistycznymi piśmiennymi”. Ponieważ jednak narzędzia te nie realizują „sieci abstrakcyjnych pojęć” kryjącej się za systemem makr języka naturalnego, ani nie dają możliwości zmiany kolejności kodu źródłowego z sekwencji narzuconej maszynowo na wygodną dla ludzkiego umysłu , nie można ich właściwie nazwać piśmiennymi narzędziami programistycznymi w sensie zamierzonym przez Knutha.

Krytyka

W 1986 roku Jon Bentley poprosił Knutha o zademonstrowanie koncepcji programowania piśmiennego w swojej kolumnie Perły Programowania w Communications of the ACM , poprzez napisanie programu w sieci WWW. Knuth wysłał mu program do problemu omówionego wcześniej w kolumnie (z próbkowaniem M liczb losowych z zakresu 1.. N ), a także poprosił o „przypisanie”. Bentley zadał mu problem ze znalezieniem najczęściej używanych słów w K z pliku tekstowego, dla którego Knuth napisał program WEBowy, który został opublikowany wraz z recenzją Douglasa McIlroya z Bell Labs. McIlroy pochwalił zawiłość rozwiązania Knutha, wybór struktury danych (wariant skrótu Franka M. Lianga ) oraz prezentację. Skrytykował pewne kwestie związane ze stylem, takie jak fakt, że główna idea została opisana pod koniec artykułu, użycie magicznych stałych oraz brak diagramu towarzyszącego wyjaśnieniu struktury danych. McIlroy, znany z potoków uniksowych , również wykorzystał recenzję do krytyki samego zadania programistycznego, wskazując, że w Unixie (opracowanym w Bell Labs) napisano wcześniej narzędzia do przetwarzania tekstu ( tr , sort , uniq i sed ), które były „ staples”, a rozwiązanie, które było łatwe do wdrożenia, debugowania i ponownego użycia, można było uzyskać, łącząc te narzędzia w sześciowierszowy skrypt powłoki . W odpowiedzi Bentley napisał, że:

[McIlroy] podziwia wykonanie rozwiązania, ale obarcza problem względami inżynierskimi. (Oczywiście moja odpowiedzialność jako osoby przypisującej problem; Knuth rozwiązał otrzymany problem na podstawie ważnych dla większości inżynierów — wypłat zapewnianych przez osoby przypisujące problemy).

McIlroy przyznał później, że jego krytyka była niesprawiedliwa, ponieważ krytykował program Knutha z powodów inżynierskich, podczas gdy celem Knutha było jedynie zademonstrowanie techniki programowania piśmiennego. W 1987 roku Communications of the ACM opublikował artykuł, który ilustrował piśmienne programowanie za pomocą programu C, który łączył artystyczne podejście Knutha z inżynierskim podejściem McIlroya, z krytyką Johna Gilberta.

Przepływ pracy

Implementacja zaawansowanego programowania składa się z dwóch kroków:

  1. Tkanie: Generowanie kompleksowego dokumentu na temat programu i jego obsługi.
  2. Tangling: generowanie kodu wykonywalnego maszyny

Tkanie i plątanie odbywa się na tym samym źródle, aby były ze sobą spójne.

Przykład

Klasycznym przykładem piśmiennego programowania jest piśmienna implementacja standardowego programu do liczenia słów w systemie Unix wc . Knuth przedstawił wersję CWEB tego przykładu w rozdziale 12 swojej książki Literate Programming . Ten sam przykład został później przepisany dla narzędzia do programowania piśmiennego noweb . Ten przykład stanowi dobrą ilustrację podstawowych elementów programowania umiejącego czytać i pisać.

Tworzenie makr

Poniższy fragment programu dla tych, którzy wcpotrafią czytać, pokazuje, w jaki sposób arbitralne frazy opisowe w języku naturalnym są używane w programie dla tych, którzy potrafią czytać, do tworzenia makr, które działają jako nowe „operatory” w tym języku i ukrywają fragmenty kodu lub inne makra. Notacja znaczników składa się z podwójnych nawiasów ostrych (" <<...>>"), które wskazują makra, @symbolu " ", który wskazuje koniec sekcji kodu w pliku noweb. Symbol „ <<*>>” oznacza „root”, najwyższy węzeł, z którego narzędzie do programowania piśmiennego zacznie rozszerzać sieć makr. Właściwie, napisanie rozszerzonego kodu źródłowego może być wykonane z dowolnej sekcji lub podsekcji (tj. fragmentu kodu oznaczonego jako „ <<name of the chunk>>=”, ze znakiem równości), więc jeden plik programu piśmiennego może zawierać kilka plików z maszynowym kodem źródłowym.

The purpose of wc is to count lines, words, and/or characters in a list of files. The
number of lines in a file is ......../more explanations/

Here, then, is an overview of the file wc.c that is defined by the noweb program wc.nw:
    <<*>>=
    <<Header files to include>>
    <<Definitions>>
    <<Global variables>>
    <<Functions>>
    <<The main program>>
    @

We must include the standard I/O definitions, since we want to send formatted output
to stdout and stderr.
    <<Header files to include>>=
    #include <stdio.h>
    @

Rozplątanie fragmentów można przeprowadzić w dowolnym miejscu w tekstowym pliku programu umiejącego czytać i pisać, niekoniecznie w kolejności, w jakiej są one uporządkowane w otaczającej części, ale zgodnie z wymogami logiki odzwierciedlonej w tekście wyjaśniającym, który otacza cały program.

Program jako sieć — makra to nie tylko nazwy sekcji

Makra to nie to samo, co „nazwy sekcji” w standardowej dokumentacji. Literackie makra programistyczne mogą ukrywać za sobą dowolny fragment kodu i mogą być używane w dowolnych operatorach języka maszynowego niskiego poziomu, często w operatorach logicznych, takich jak „ if”, „ while” lub „ case”. Ilustruje to następujący fragment wcprogramu piśmiennego.

The present chunk, which does the counting, was actually one of
the simplest to write. We look at each character and change state if it begins or ends
a word.

    <<Scan file>>=
    while (1) {
      <<Fill buffer if it is empty; break at end of file>>
      c = *ptr++;
      if (c > ' ' && c < 0177) {
        /* visible ASCII codes */
        if (!in_word) {
          word_count++;
          in_word = 1;
        }
        continue;
      }
      if (c == '\n') line_count++;
      else if (c != ' ' && c != '\t') continue;
      in_word = 0;
        /* c is newline, space, or tab */
    }
    @

W rzeczywistości makra mogą oznaczać dowolny fragment kodu lub inne makra, a zatem są bardziej ogólne niż „fragmentowanie” z góry na dół lub „od dołu” lub podsekcje. Knuth mówi, że kiedy zdał sobie z tego sprawę, zaczął myśleć o programie jako o sieci różnych części.

Porządek ludzkiej logiki, a nie kompilatora

W programach piśmiennych nowyb oprócz swobodnej kolejności ich prezentacji, fragmenty za makrami, raz wprowadzone za pomocą " <<...>>=", mogą być później powiększane w dowolnym miejscu w pliku, po prostu pisząc " <<name of the chunk>>=" i dodając do niego więcej treści, jak w poniższym fragmencie ilustruje („plus” jest dodawany przez program formatujący dokument dla czytelności i nie ma go w kodzie).

 The grand totals must be initialized to zero at the beginning of the program.
If we made these variables local to main, we would have to do this  initialization
explicitly; however, C globals are automatically zeroed. (Or rather,``statically
zeroed.'' (Get it?)

    <<Global variables>>+=
    long tot_word_count, tot_line_count,
         tot_char_count;
      /* total number of words, lines, chars */
    @

Zapis toku myśli

Dokumentacja programu piśmiennego jest tworzona jako część pisania programu. Zamiast komentarzy dołączanych jako uwagi do kodu źródłowego program piśmienny zawiera wyjaśnienie pojęć na każdym poziomie, przy czym pojęcia niższego poziomu są odsunięte na odpowiednie miejsce, co pozwala na lepszą komunikację myśli. Fragmenty wcpowyższego piśmiennego pokazują, w jaki sposób przeplatają się objaśnienia programu i jego kodu źródłowego. Taka ekspozycja idei tworzy przepływ myśli, który jest jak dzieło literackie. Knuth napisał „powieść”, która wyjaśnia kod interaktywnej gry fabularnej Colossal Cave Adventure .

Niezwykłe przykłady

  • Axiom , który wyewoluował z notatnika, systemu algebry komputerowej opracowanego przez IBM. Obecnie jest rozwijany przez Tima Daly'ego, jednego z twórców notatnika, Axiom jest całkowicie napisany jako program piśmienny.

Literackie praktyki programistyczne

Pierwszym opublikowanym literackim środowiskiem programistycznym był WEB , wprowadzony przez Knutha w 1981 roku dla jego systemu składu TeX ; używa Pascala jako podstawowego języka programowania i TeXa do składu dokumentacji. Kompletny kod źródłowy TeXa z komentarzem został opublikowany w TeX -ie Knutha : Program , tom B jego 5-tomowego Computers and Typesetting . Knuth korzystał prywatnie z systemu programowania o nazwie DOC już w 1979 roku. Zainspirowały go pomysły Pierre-Arnoula de Marneffe . Darmowy CWEB , napisany przez Knutha i Silvio Levy'ego, jest WEB dostosowany do C i C++ , działa na większości systemów operacyjnych i może tworzyć dokumentację TeX i PDF .

Istnieją różne inne implementacje koncepcji programowania piśmiennego (niektóre z nich nie mają makr, a zatem naruszają porządek ludzkiej logiki ):

Nazwa Obsługiwane języki Napisane w Język znaczników Uwagi
Zauważalny JavaScript JavaScript , TypeScript TeX ( KaTeX ), HTML Przechowywane w chmurze z interfejsem internetowym. Treści można publikować jako strony internetowe. Kontrolowana wersja; platforma definiuje własne operacje kontroli wersji. Komórki kodu mogą być zorganizowane poza kolejnością ; obserwowalne notatniki automatycznie konstruują wykres wykonania ( DAG ). Bogata standardowa biblioteka zaimplementowana z nowoczesnymi funkcjami JavaScript . Komórki z różnych obserwowalnych notatników mogą odwoływać się do siebie. Biblioteki Npm można importować na bieżąco.
SIEĆ Pascal Pascal TeX Pierwsze opublikowane środowisko programistyczne umiejące czytać i pisać.
CWEB C++ i C C TeX Czy WEB jest przystosowany do C i C++ .
NoWEB Każdy C , AWK i Icon LaTeX , TeX , HTML i troff Jest dobrze znany ze swojej prostoty i pozwala na formatowanie tekstu w HTML zamiast przechodzenia przez system TeX.
Piśmienny Każdy D Obniżka cen Obsługuje równania TeX. Kompatybilny z Vimem ( literate.vim )
FunnelWeb Każdy C HTML i TeX Ma bardziej skomplikowane znaczniki, ale ma wiele bardziej elastycznych opcji
NuWEB Każdy C++ Lateks Może przetłumaczyć pojedyncze źródło LP na dowolną liczbę plików kodu. Czyni to w jednym wezwaniu; nie ma oddzielnych poleceń splotu i plątaniny. Nie ma rozszerzalności jak noweb
pyWeb Każdy Pyton Tekst zrestrukturyzowany Respektuje wcięcia, dzięki czemu można go używać w językach takich jak Python , chociaż można go używać w dowolnym języku programowania.
Pedał Każdy Perl HTML Ma na celu unowocześnienie i skalowanie za pomocą „składania HTML” i „wirtualnych widoków” kodu. Używa znaczników "noweb" dla piśmiennych plików źródłowych.
Codnar Rubin Jest to odwrotne narzędzie programistyczne, dostępne jako Ruby Gem. Zamiast odczytywalnego maszynowo kodu źródłowego wyodrębnianego z piśmiennych źródeł dokumentacji, piśmienna dokumentacja jest wyodrębniana z normalnych plików kodu źródłowego do odczytu maszynowego.
Tryb organizacji Emacsa Każdy Emacs Lisp Zwykły tekst Wymaga Babel, który umożliwia osadzanie bloków kodu źródłowego z wielu języków programowania w jednym dokumencie tekstowym. Bloki kodu mogą dzielić się danymi, wyświetlać obrazy w tekście lub być parsowane do czystego kodu źródłowego przy użyciu składni referencyjnej nowyb .
CoffeeScript CoffeeScript CoffeeScript , JavaScript Obniżka cen CoffeeScript obsługuje tryb „literate”, który umożliwia kompilację programów z dokumentu źródłowego napisanego w Markdown z wciętymi blokami kodu.
Arkusze klonowe Klon (oprogramowanie) XML Arkusze Maple to niezależne od platformy środowisko programowania, które łączy tekst i grafikę z kodem na żywo do obliczeń symbolicznych. "Klonowe Arkusze Robocze" . www.maplesoft.com . Źródło 2020-05-30 .
Notatniki Wolfram Język Wolfram Język Wolfram Notatniki Wolframniezależną od platformy, piśmienną metodą programowania, która łączy tekst i grafikę z kodem na żywo.
Place zabaw Swift (język programowania) Zapewnia interaktywne środowisko programowania, które ocenia każdą instrukcję i wyświetla wyniki na żywo podczas edycji kodu. Place zabaw umożliwiają również użytkownikowi dodanie języka znaczników wraz z kodem, który zapewnia nagłówki, wbudowane formatowanie i obrazy.
Notatnik Jupyter , dawniej Notatnik IPython Python i każdy z jądrem Jupyter HTML Pracuje w formacie zeszytów, które łączą nagłówki, tekst (w tym LaTeX), wykresy itp. z pisanym kodem.
nbdev Notatnik Pythona i Jupytera nbdev to biblioteka, która pozwala rozwijać bibliotekę Pythona w Jupyter Notebooks, umieszczając cały kod, testy i dokumentację w jednym miejscu.
Julia (język programowania) Obsługuje tryb rozwoju iJulia, który został zainspirowany przez iPythona.
Agda (język programowania) Obsługuje ograniczoną formę programowania piśmiennego po wyjęciu z pudełka.
Ewa język programowania Programy to przede wszystkim proza. Eve łączy warianty Datalog i Markdown z graficznym środowiskiem programistycznym na żywo.
Notatniki R Markdown (lub Notatniki R) R , Python , Julia i SQL PDF , Microsoft Word , LibreOffice i formaty prezentacji lub pokazów slajdów oraz formaty interaktywne, takie jak widżety HTML
Sweave r PDF
Dzianina r LaTeX , PDF , LyX , HTML , Markdown , AsciiDoc i reStructuredText
Oplot kodowy Pandoc , Rdza , Julia , Python , R , Bash
Splot Pyton PDF

Inne przydatne narzędzia to

  • Edytor tekstu Leo jest przedstawiającym w zarysie edytor, który obsługuje opcjonalny temat Noweb i CWEB znaczników. Autor Leo łączy dwa różne podejścia: po pierwsze Leo jest edytorem konspektu, który pomaga w zarządzaniu dużymi tekstami; po drugie, Leo zawiera pewne idee piśmiennego programowania, które w czystej postaci (tj. sposób, w jaki jest używane przez narzędzie Knuth Web lub narzędzia typu „noweb”) jest możliwe tylko przy pewnym stopniu pomysłowości i użyciu edytora w sposób nie do końca przewidziany przez jego autora (w zmodyfikowanych węzłach @root). Jednak to i inne rozszerzenia (@węzły plików) sprawiają, że programowanie konspektu i zarządzanie tekstem jest skuteczne i łatwe, a pod pewnymi względami przypomina programowanie piśmienne.
  • Język programowania Haskell ma natywną obsługę programowania półpiśmiennego. Kompilator/interpreter obsługuje dwa rozszerzenia nazw plików: .hsi .lhs; ten ostatni oznacza piśmienny Haskell.
Skrypty literackie mogą być pełnym tekstem źródłowym LaTeX, jednocześnie mogą być skompilowane, bez zmian, ponieważ interpreter kompiluje tekst tylko w środowisku kodowym, na przykład
% here text describing the function:
\begin{code}
fact 0 = 1
fact (n+1) = (n+1) * fact n
\end{code}
here more text
Kod można również oznaczyć w stylu Richarda Birda, zaczynając każdy wiersz symbolem większe niż i spacją, poprzedzając i kończąc fragment kodu pustymi wierszami.
listingsPakiet LaTeX zapewnia lstlistingśrodowisko, które można wykorzystać do upiększenia kodu źródłowego. Może być użyty do zdefiniowania codeśrodowiska używanego w Haskell do drukowania symboli, takich jak:
\newenvironment{code}{\lstlistings[language=Haskell]}{\endlstlistings}

\begin{code}
comp :: (beta -> gamma) -> (alpha -> beta) -> (alpha -> gamma)
(g `comp` f) x = g(f x)
\end{code}
można skonfigurować tak, aby uzyskać coś takiego:
Chociaż pakiet nie zapewnia środków do organizowania fragmentów kodu, można podzielić kod źródłowy LaTeX na różne pliki. Zobacz podręcznik aukcji dla przeglądu.
  • System Web 68 Literate Programming wykorzystywał Algol 68 jako podstawowy język programowania, chociaż w preprocesorze nie było nic, co mogłoby wymusić użycie tego języka.
  • Mechanizm dostosowywania Text Encoding Initiative, który umożliwia ograniczanie, modyfikację lub rozszerzenie schematu TEI , umożliwia użytkownikom mieszanie dokumentacji prozy z fragmentami specyfikacji schematu w formacie One Document do wszystkiego . Z tej dokumentacji prozy można generować schematy i potoki modeli przetwarzania, a paradygmat Literate Programming Knutha jest cytowany jako inspiracja dla tego sposobu pracy.

Zobacz też

  • Generator dokumentacji – odwrotność programowania piśmiennego, w którym dokumentacja jest osadzona i generowana z kodu źródłowego
  • Interfejs notebooka – wirtualne środowisko notebooka używane do programowania piśmiennego
  • Sweave and Knitr – przykłady użycia narzędzia Literate Programming w języku R w stylu „noweb” do tworzenia dynamicznych raportów statystycznych
  • Kod samodokumentującykod źródłowy, który można łatwo zrozumieć bez dokumentacji

Bibliografia

Dalsza lektura

Zewnętrzne linki