Ponieważ języki programowania początkowo używały tylko wierszy kodu wykonywanych sekwencyjnie i ewoluowały w celu włączenia funkcji, które były jednym z pierwszych poziomów abstrakcji, a następnie stworzono klasy i obiekty, aby jeszcze bardziej ją wyodrębnić; jaki jest następny poziom abstrakcji?
Co jest jeszcze bardziej abstrakcyjne niż zajęcia lub czy są jeszcze jakieś?
programming-languages
object-oriented
language-agnostic
abstraction
Jordan Medlock
źródło
źródło
Odpowiedzi:
Myślę, że masz jakieś nieporozumienia na temat historii komputerów.
Pierwszą abstrakcją (w 1936 r.) Był w rzeczywistości Lambda Calculus Alonzo Church, który jest podstawą koncepcji funkcji wyższego rzędu i wszystkich późniejszych języków funkcjonalnych. To bezpośrednio zainspirowało Lisp (drugi najstarszy język programowania wysokiego poziomu, stworzony w 1959 r.), Który z kolei zainspirował wszystko, od ML po Haskell i Clojure.
Drugą abstrakcją było programowanie proceduralne. Wyszło z architektur komputerowych von Neumanna, w których pisano programy sekwencyjne, jedna instrukcja na raz. FORTRAN (najstarszy język programowania wysokiego poziomu, 1958) był pierwszym językiem wysokiego poziomu, który wyszedł z paradygmatu proceduralnego.
Trzecia abstrakcja była prawdopodobnie programowaniem deklaratywnym, najpierw zilustrowanym przez Absysa (1967), a następnie Prologa (1972). Jest to podstawa programowania logicznego, w którym wyrażenia są oceniane przez dopasowanie szeregu deklaracji lub reguł, zamiast wykonywania szeregu instrukcji.
Czwartą abstrakcją było wówczas programowanie obiektowe, które po raz pierwszy pojawiło się w programach Lisp w latach 60-tych, ale później zostało zilustrowane przez Smalltalk w 1972 r. (Chociaż wydaje się, że istnieje pewna debata na temat tego, czy styl przekazywania wiadomości przez Smalltalk obiektowa abstrakcja One True. Nie zamierzam tego dotykać.)
Wszystkie inne abstrakty, zwłaszcza dotyczące tradycyjnej architektury komputerowej von Neumanna, są odmianami tych czterech tematów. Nie jestem przekonany, że poza tymi czterema istnieje inna abstrakcja, która nie jest jedynie odmianą lub kombinacją ich.
Ale abstrakcja jest w istocie jedynie sposobem na modelowanie i opisywanie algorytmu. Algorytmy można opisać jako szereg dyskretnych kroków, jako zbiór reguł, których należy przestrzegać, jako zbiór funkcji matematycznych lub jako obiekty oddziałujące. Bardzo trudno jest wymyślić inny sposób opisywania lub modelowania algorytmów, a nawet jeśli tak, to nie jestem przekonany o jego przydatności.
Istnieje jednak model obliczeń kwantowych. W obliczeniach kwantowych konieczne są nowe abstrakcje do modelowania algorytmów kwantowych. Jako neofita w tej dziedzinie nie mogę tego komentować.
źródło
Dla wielu najczystszą formą abstrakcji kodu w obecnej erze programowania binarnego jest „funkcja wyższego rzędu”. Zasadniczo sama funkcja jest traktowana jako dane, a funkcje funkcji są zdefiniowane, tak jak można je zobaczyć w równaniach matematycznych z operatorami określającymi wynik ich operandów oraz z góry ustaloną kolejnością operacji definiujących „zagnieżdżanie” tych operacji. Matematyka ma bardzo mało „rozkazujących nakazów” w swojej strukturze; dwa przykłady, które mogę wymyślić, to: „niech x ma pewną wartość lub może być dowolną wartością zgodną z jakimś ograniczeniem”, oraz „częściowe funkcje”, w których dane wejściowe określają wyrażenie potrzebne do wygenerowania danych wyjściowych. Te konstrukcje są łatwo reprezentowalne jako ich własne funkcje; „funkcja” x zawsze zwraca 1, a „przeciążenie” funkcji definiuje się w kategoriach tego, co jest do nich przekazywane (które w przeciwieństwie do przeciążeń obiektowych można zdefiniować na podstawie wprowadzonych wartości), umożliwiając „częściową” ocenę nazwanej grupy funkcji, nawet pod względem samych siebie. Jako taki, program eliminuje pojęcie imperatywów na niskim poziomie i zamiast tego skupia się na „ocenieniu” danych wejściowych.
Te funkcje wyższego rzędu stanowią kręgosłup „języków funkcjonalnych”; to, co robi program, jest zdefiniowane w kategoriach „czystych funkcji” (jedno lub więcej danych wejściowych, jedno lub więcej danych wyjściowych, brak efektów ubocznych lub „ukryty stan”), które są zagnieżdżone w sobie i oceniane w razie potrzeby. W takich przypadkach większość „imperatywnej logiki” jest wyabstrahowana; środowisko wykonawcze obsługuje faktyczne wywoływanie funkcji i wszelkie warunki, w których jedno lub drugie przeciążenie funkcji może wymagać wywołania. W takim programie kod nie jest uważany za „robienie” czegoś, lecz za „bycie” czymś, a to, co dokładnie jest określane, jest uruchamiane przy początkowym wejściu programu.
Funkcje wyższego rzędu są teraz również podstawą wielu imperatywnych języków; Instrukcje lambda .NET w zasadzie pozwalają na „anonimowy” wkład funkcjonalny w inną „funkcję” (zaimplementowaną imperatywnie, ale teoretycznie nie musi tak być), umożliwiając w ten sposób wysoce konfigurowalne „łączenie” funkcji „ogólnego przeznaczenia” w celu osiągnięcia pożądany wynik.
Inną abstrakcją powszechnie spotykaną w najnowszej rundzie języków programowania jest dynamiczne pisanie zmiennych oparte na koncepcji „pisania kaczego”; jeśli wygląda jak kaczka, pływa jak kaczka, leci jak kaczka i kwakanie jak kaczka, można to nazwać kaczką. Nie ma znaczenia, czy to w rzeczywistości krzyżówka, czy płócienny obraz. Może to znaczenia, czy jest to rzeczywiście gęś lub łabędzia, ale potem znowu może to nie ważne, czy wszystko, co dbają o to, że pływa i muchy, a trochę wygląda jak kaczka. Jest to uważane za ostateczne dziedziczenie obiektu; nie obchodzi cię, co to jest , oprócz nadania mu nazwy; ważniejsze jest to, co robi. W takich językach są w zasadzie tylko dwa typy; „atom”, pojedynczy element informacji (jedna „wartość”; liczba, znak, funkcja, cokolwiek) oraz „krotka” złożona z atomu i „wskaźnika” na wszystko inne w krotce. Nie ma znaczenia, w jaki sposób te typy są implementowane w środowisku binarnym przez środowisko wykonawcze; Używając ich, możesz osiągnąć funkcjonalność praktycznie każdego rodzaju, o jakim możesz pomyśleć, od prostych typów wartości przez ciągi znaków po kolekcje (które, ponieważ wartości mogą być różnych „typów”, pozwalają na „typy złożone”, czyli „obiekty”).
źródło
Można rozważyć języki specyficzne dla domeny, takie jak SQL, jako wyższy stopień abstrakcji. SQL jest bardzo ukierunkowanym językiem, który wyodrębnia operacje takie jak przechowywanie i zapewnia funkcje wyższego poziomu oparte na teorii mnogości. Zastanów się także, ile obecnie języków głównego nurtu nie jest ukierunkowanych na określoną architekturę, ale raczej na maszynę wirtualną (taką jak JVM lub .NET CLR). Na przykład C # jest kompilowany do IL, która jest interpretowana (lub częściej JIT'd - Just In Time Compiled - do natywnej implementacji) przez natywny silnik wykonawczy.
Dużo hałasu wzbudziło pojęcie DSL-ów używanych do tworzenia bardzo wysokiego poziomu języków, których można używać bez dużego doświadczenia technicznego do tworzenia działającego programu. Pomyśl, czy ktoś był w stanie opisać swoje byty i interakcje w prawie zwykłym języku angielskim, a środowisko operacyjne poradziło sobie z wszystkim, od przedstawienia prostego interfejsu użytkownika, po przechowywanie danych w pewnego rodzaju bazie danych. Gdy operacje te zostaną wyabstrahowane, możesz sobie wyobrazić, jak łatwe może być programowanie.
Obecnie istnieją takie, jak JetBrains MPS (zestaw narzędzi do opisywania DSL lub generatora języka). Microsoft miał krótką próbę (i mogę dodać, że jest to bardzo obiecujące) w tej przestrzeni z językiem M (język M był tak kompletny, że język został zdefiniowany w języku M).
Krytycy tej koncepcji wskazują na wcześniejsze nieudane próby usunięcia programistów z pracy nad programowaniem, różnica w porównaniu ze stołami roboczymi DSL (jak je nazywa Fowler) polega na tym, że programiści nadal byliby zaangażowani w kodyfikację koncepcji, które Eksperci domeny mogliby wyrazić potrzeby ich domeny. Podobnie jak dostawcy systemów operacyjnych i języków tworzą narzędzia, których używamy do programowania, używamy DSL do dostarczania narzędzi dla użytkowników biznesowych. Można sobie wyobrazić DSL, które opisują dane i logikę, podczas gdy programiści tworzą interpretery, które przechowują i pobierają dane oraz stosują logikę wyrażoną w DSL.
źródło
Twierdziłbym, że meta-struktury, moduły, frameworki, platformy i usługi są grupami cech wyższego poziomu niż klasy. Moja hierarchia abstrakcji systemu programowania:
Meta-struktury, takie jak metaklasy , funkcje wyższego rzędu i generyczne wyraźnie dodają abstrakcję do podstawowych klas, funkcji, typów danych i instancji danych. Cechy, aspekty i dekoratory to nowsze mechanizmy łączenia funkcji kodu i podobnie „przyspieszające” inne klasy i funkcje.
Nawet języki poprzedzające obiekty miały moduły i pakiety, więc umieszczenie ich powyżej klas może być dyskusyjne. Bu zawierają te klasy i meta-struktury, więc oceniam je wyżej.
Frameworki to najsilniejsza odpowiedź - organizują wiele klas, meta-struktur, modułów, funkcji itp. W celu zapewnienia wyrafinowanych abstrakcji na wysokim poziomie. A jednak frameworki nadal działają prawie całkowicie w dziedzinie programowania.
Stosy rozwiązań lub platformy zazwyczaj łączą wiele środowisk, podsystemów lub komponentów w środowisko w celu rozwiązywania wielu problemów.
Wreszcie, istnieją usługi --often wdrożony jako WWW lub usług sieciowych. Są to architektury, frameworki, stosy rozwiązań lub możliwości aplikacji dostarczane jako kompletne pakiety. Ich elementy wewnętrzne są często nieprzejrzyste, przede wszystkim ujawniają interfejsy administratora, programowania i użytkownika. PaaS i SaaS są częstymi przykładami.
Teraz ten postęp może nie być w pełni satysfakcjonujący z kilku powodów. Po pierwsze, robi porządny postęp liniowy lub hierarchię rzeczy, które nie są idealnie liniowe lub hierarchiczne. Obejmuje niektóre abstrakcje, takie jak „stosy” i usługi, które nie są całkowicie kontrolowane przez programistów. I nie tworzy żadnego nowego magicznego pyłu pixie. (Spoiler: Nie ma magicznego pyłu pixie. )
Myślę, że błędem jest po prostu szukanie nowych poziomów abstrakcji . Wszystkie wymienione powyżej istniały od lat , nawet jeśli nie wszystkie były tak znane i popularne, jak teraz. Przez te lata poprawiono abstrakcje możliwe na każdym poziomie kodowania. Mamy teraz ogólne kolekcje ogólnego przeznaczenia, nie tylko tablice. Pętlujemy kolekcje, a nie tylko zakresy indeksów. Mamy zestawienia list oraz operacje filtrowania list i map. Wiele funkcji języka może mieć zmienną liczbę argumentów i / lub argumenty domyślne. I tak dalej. Zwiększamy poziom abstrakcji na każdym poziomie, więc dodanie kolejnych poziomów nie jest wymagane do zwiększenia ogólnego poziomu abstrakcji.
źródło
Następną abstrakcją po zajęciach są meta klasy . To takie proste ;)
źródło
Type
która daje możliwości refleksyjne, ale nie mutację (nie można dodać nowej metodyMyType
, mówiąctypeof(MyType).Methods += new Method ( "Foo", (int x)=>x*x )
jak można w CLOS)Dziwi mnie, że nikt nie wspomniał o teorii kategorii.
Najbardziej podstawową jednostką programowania jest funkcja oparta na typach. Funkcje są zwykle oznaczone jako f: A -> B, gdzie A i B są typami. Jeśli umieścisz te rzeczy, które nazywam typami i funkcjami, razem w odpowiedni sposób, otrzymasz coś, co nazywa się kategorią. W tym momencie nie musisz się zatrzymywać.
Weź te rzeczy, kategorie i zadaj sobie pytanie, jaki byłby właściwy sposób na powiązanie ich ze sobą. Jeśli zrobisz to dobrze, otrzymasz coś, co nazywa się funktorem, który przechodzi między dwiema kategoriami i jest zwykle oznaczony jako F: C -> B. Po raz kolejny nie musisz się zatrzymywać.
Możesz wziąć wszystkie funktory i złożyć je we właściwy sposób, a jeśli zrobisz to dobrze, zaczniesz zastanawiać się, jak powiązać dwa funktory ze sobą. W tym momencie otrzymujesz coś, co nazywa się naturalną transformacją, mu: F -> G, gdzie F i G są funktorami.
Moja wiedza w tym momencie staje się rozmyta, ale możesz kontynuować to i wspinać się po drabinie abstrakcji. Przedmioty i klasy nawet nie zbliżają się do opisania, jak wysoko można wspiąć się po drabinie abstrakcji. Istnieje wiele języków, które mogą wyrazić powyższe pojęcia obliczeniowo, a najbardziej znanym z nich jest Haskell. Więc jeśli naprawdę chcesz wiedzieć, na czym naprawdę polega abstrakcja, to idź nauczyć się Haskell, Agda, HOL lub ML.
źródło
Myślę, że brakuje modelu aktora na liście kandydatów.
Oto, co rozumiem przez aktorów:
Ten model jest czymś więcej niż deterministycznymi maszynami Turinga i jest bardziej zbliżony do naszego rzeczywistego sprzętu, gdy patrzymy na współbieżne programy. O ile nie zastosujesz dodatkowych (kosztownych) kroków synchronizacji, w dzisiejszych czasach, kiedy twój kod odbiera dane, ta wartość mogła już ulec zmianie po drugiej stronie tej samej kości, może nawet w tym samym rdzeniu.
Krótka dyskusja / wprowadzenie: http://youtube.com/watch?v=7erJ1DV_Tlo
źródło
Jeśli dobrze cię rozumiem, twoje „rosnące abstrakcje” można uznać za coraz większe enkapsulacje logiki, związane głównie z ponownym użyciem kodu.
Z konkretnych instrukcji wykonywanych jedna po drugiej przechodzimy do funkcji / podprogramów , które zawierają lub abstrakcyjnie logiczne grupowanie instrukcji w pojedynczy element. Następnie mamy obiekty lub moduły , które zawierają podprogramy odnoszące się do określonej jednostki logicznej lub kategorii, dzięki czemu mogę grupować wszystkie operacje na łańcuchach w ramach
String
klasy lub wszystkie typowe operacje matematyczne wMath
module (lub klasie statycznej, w językach takich jak C #) .Więc jeśli to nasz rozwój, co będzie dalej? Nie sądzę, że masz wyraźny następny krok. Jak odpowiedzieli inni, twój postęp dotyczy tylko stylów programowania imperatywnego / proceduralnego, a inne paradygmaty nie podzielają twoich koncepcji abstrakcji. Ale jeśli mam coś, co może logicznie rozszerzyć twoją metaforę, to są to usługi .
Usługa jest podobna do klasy w tym sensie, że jest bytem, który ujawnia funkcjonalność, ale implikuje o wiele bardziej rygorystyczne oddzielenie problemów niż w przód i w tył z obiektami, które sam tworzyłeś. Ujawniają ograniczony zestaw operacji, ukrywają wewnętrzną logikę i nawet niekoniecznie działają na tym samym komputerze.
Ponownie istnieje dobre rozróżnienie. W większości przypadków użyjesz obiektu, który działa jako serwer proxy dla usługi , a oba będą bardzo podobne, ale jako architektura oba są różne.
źródło
Nowe formy abstrakcji ukrywają przed tobą pracę na niskim poziomie. Nazwane procedury i funkcje ukrywają przed tobą adresy programów. Obiekty ukrywają dynamiczne zarządzanie pamięcią i niektóre zależne od typu „instrukcje if”.
Sugerowałbym, że następnym poziomem praktycznych abstrakcji, które będą ukrywać przed tobą nudy na niskim poziomie, są funkcjonalne programowanie reaktywne . Spójrz na „sygnały” w czymś takim jak http://elm-lang.org/, które ukrywają wywołania zwrotne i aktualizują zależności, które musicie jawnie zarządzać w javascript. FRP może ukryć dużą złożoność komunikacji między procesami i komunikacji między maszynami, która jest potrzebna w aplikacjach internetowych na dużą skalę, a także w wysokiej wydajności równoległości.
Jestem prawie pewien, że właśnie to nas ekscytuje w ciągu najbliższych 5 lat.
źródło
Teoria zbiorów - częściowo zaimplementowana w relacyjnych bazach danych, ale także w językach statystycznych takich jak SAS i R, zapewnia inny, ale prawdopodobnie wyższy poziom abstrakcji niż OO.
źródło