Pięć pytań dotyczących projektowania języków programowania

Pięć pytań dotyczących projektowania języków programowania

Przewodnia filozofia

1. Języki programowania dla ludzi

Języki programowania to sposób, w jaki ludzie rozmawiają z komputerami. Komputer chętnie porozmawia w każdym języku, który nie będzie dwuznaczny. Powodem, dla którego mamy języki wyższego poziomu, jest to, że ludzie nie potrafią radzić sobie z językiem maszynowym. Istota języków programowania polega na tym, by chronić nasze delikatne ludzkie umysły przed przeciążeniem masą szczegółów.

Architekci wiedzą, że niektóre problemy projektowe są bardziej przyziemne od innych. Jednym z najbardziej przejrzystych i abstrakcyjnych problemów projektowych jest budowa mostów. W tym przypadku Twoim zadaniem jest pokrycie wymaganego dystansu przy jak najmniejszym zużyciu materiału. Na drugim końcu spektrum znajduje się projektowanie krzeseł. Projektanci krzeseł muszą poświęcić swój czas na rozmyślanie o ludzkich pośladkach.

Rozwój oprogramowania wykazuje podobne różnice. Projektowanie algorytmów do routowania danych przez sieć to dobra, abstrakcyjna kwestia, podobnie jak projektowanie mostów. Natomiast projektowanie języków programowania przypomina projektowanie krzeseł: musisz radzić sobie z ludzkimi słabościami.

Większości z nas trudno to dostrzec. Projektowanie eleganckich systemów matematycznych brzmi dla większości z nas znacznie bardziej kusząco niż ustępowanie ludzkim słabościom. Rola matematycznej elegancji polega na tym, że pewien stopień elegancji sprawia, że programy są łatwiejsze do zrozumienia. Jednak elegancja to nie wszystko.

Kiedy mówię, że języki powinny być projektowane z uwzględnieniem ludzkich słabości, nie mam na myśli, że języki powinny być projektowane dla złych programistów. W rzeczywistości powinieneś projektować oprogramowanie dla najlepszych programistów, ale nawet najlepsi programiści mają swoje ograniczenia. Nie sądzę, żeby ktokolwiek lubił programować w języku, w którym wszystkie zmienne byłyby oznaczone literą „x” z całkowitymi indeksami.

2. Projektuj dla siebie i swoich przyjaciół

Jeśli spojrzysz na historię języków programowania, większość z najlepszych języków została zaprojektowana do użytku przez ich autorów, a większość najgorszych — zaprojektowana dla innych ludzi.

Kiedy języki są projektowane dla innych ludzi, zawsze jest to jakaś konkretna grupa: ludzie nie są tak inteligentni jak twórcy języka. Tak więc otrzymujesz język, który mówi do ciebie z wyższością. Cobol jest najbardziej oczywistym przykładem, ale większość języków przenika ten duch.

To nie ma nic wspólnego z tym, jak wysoko poziomowy jest język. C jest dość niskopoziomowy, ale został stworzony do użytku przez jego autorów, dlatego hakerzy go uwielbiają.

Argument za projektowaniem języków dla słabych programistów polega na tym, że słabych programistów jest więcej niż dobrych. To prawdopodobnie prawda. Ale niewielka liczba dobrych programistów pisze niewspółmiernie więcej oprogramowania.

Interesuje mnie pytanie, jak stworzyć język, który przypadnie do gustu najlepszym hakerom? Uważam, że to pytanie jest równoważne pytaniu, jak stworzyć dobry język programowania, ale nawet jeśli tak nie jest, to przynajmniej jest to interesujące pytanie.

3. Daj programiście tyle kontroli, ile to możliwe

Wiele języków (szczególnie tych zaprojektowanych dla innych ludzi) zachowuje się jak nianie: starają się ostrzec cię przed rzeczami, które, ich zdaniem, będą ci nieprzydatne. Ja mam odwrotne zdanie: daj programiście tyle kontroli, ile możesz.

Kiedy po raz pierwszy uczyłem się Lispa, najbardziej spodobało mi się to, że rozmawialiśmy na równych prawach. W innych językach, które wtedy poznałem, był język oraz mój program w tym języku, które istniały dość oddzielnie. Ale w Lispie funkcje i makra, które pisałem, były tak samo ważne jak sam język. Mogłem przepisać sam język, jeśli bym chciał. Miał on tę samą atrakcyjność co oprogramowanie open source.

4. Zwięzłość jest siostrą talentu

Krótkość jest niedoceniana, a nawet wzgardzona. Ale jeśli przyjrzysz się sercom hakerów, zobaczysz, że bardzo cenią oni krótkość. Ile razy słyszałeś, jak hakerzy z miłością mówią o tym, że na przykład w APL mogą robić niesamowite rzeczy za pomocą zaledwie kilku linijek kodu? Uważam, że naprawdę mądrzy ludzie zwracają na to uwagę.

Uważam, że niemal wszystko, co pozwala skrócić programy, jest dobre. Powinno być mnóstwo funkcji bibliotecznych, wszystko, co może być niejawne, powinno takie być; składnia powinna być w większym stopniu zwięzła; nawet nazwy bytów powinny być krótkie.

I nie tylko programy powinny być krótkie. Podręczniki również powinny być krótkie. Duża część podręczników jest wypełniona wyjaśnieniami, zastrzeżeniami, ostrzeżeniami i szczególnymi przypadkami. Jeśli musisz skrócić podręcznik, najlepszym rozwiązaniem jest poprawienie języka, który wymaga tak wielu wyjaśnień.

5. Uznaj, czym jest hakerstwo

Wielu ludzi chciałoby, aby hakerstwo było matematyką lub przynajmniej czymś przypominającym nauki przyrodnicze. Myślę, że hakerstwo bardziej przypomina architekturę. Architektura ma związek z fizyką w tym sensie, że architekt musi zaprojektować budynek, który się nie zawali, ale prawdziwym celem architekta jest stworzenie wielkiego budynku, a nie dokonanie odkryć w dziedzinie statyki.

Co hakerzy kochają, to tworzenie wielkich programów. I myślę, że przynajmniej w naszych własnych myślach powinniśmy pamiętać, że pisanie znakomitych programów jest wspaniałe, nawet gdy ta praca nie przekłada się łatwo na zwykłą intelektualną walutę prac naukowych. Z intelektualnego punktu widzenia, równie ważne jest zarówno opracowanie języka, który programiści pokochają, jak i stworzenie czegoś okropnego, materializującego pomysł, o którym można opublikować artykuł.

Otwarte problemy

1. Jak zorganizować duże biblioteki?

Biblioteki stają się ważną częścią języków programowania. Stają się na tyle duże, że może to być niebezpieczne. Jeśli szukanie funkcji w bibliotece, która robi to, czego potrzebujesz, zajmuje więcej czasu niż napisanie tej funkcji samodzielnie, cały kod nic nie robi, a tylko powiększa twój podręcznik. (Przewodniki Symbolics były tego przykładem.) Musimy więc rozwiązać problem organizacji bibliotek. Idealnie byłoby je zaprojektować w taki sposób, żeby programista mógł zgadnąć, która funkcja biblioteki będzie odpowiednia.

2. Czy ludzie naprawdę boją się składni prefiksowej?

To otwarty problem w tym sensie, że myślałem o tym przez kilka lat i wciąż nie znam odpowiedzi. Składnia prefiksowa wydaje mi się absolutnie naturalna, może poza jej używaniem w matematyce. Ale może tak jest, że większość niepopularności Lispów wynika po prostu z nieznajomości składni… Czy warto coś z tym zrobić, jeśli to prawda, to inna kwestia.

3. Czego potrzebujesz do oprogramowania serwerowego?

Myślę, że większość aplikacji, które będą napisane w ciągu następnych dwudziestu lat, będą aplikacjami internetowymi, w tym sensie, że programy będą umieszczone na serwerze i będą komunikować się z tobą przez przeglądarkę internetową. A do napisania takich aplikacji potrzebujemy nowych rzeczy.

Jedną z takich rzeczy jest wsparcie dla nowego sposobu wydawania aplikacji serwerowych. Zamiast jednego lub dwóch dużych wydania w roku, jak oprogramowanie desktopowe, oprogramowanie serwerowe będzie wydawane jako seria drobnych zmian. Możesz mieć pięć lub dziesięć wydań dziennie. I wszyscy zawsze będą mieli najnowszą wersję.

Czy wiesz, jak projektować programy, aby były łatwe do utrzymania? Oprogramowanie serwerowe musi być zaprojektowane w sposób umożliwiający zmiany. Musisz mieć możliwość łatwego ich modyfikowania lub przynajmniej wiedzieć, co oznacza drobna zmiana, a co jest istotne.

Jeszcze jedna rzecz, która może być przydatna w oprogramowaniu serwerowym, to, nagle, ciągłość dostarczania. W aplikacji internetowej możesz używać czegoś w rodzaju CPS, aby uzyskać efekt podprogramów w stateless świecie sesji internetowych. Może ciągłość dostarczania jest tego warta, jeśli ta możliwość nie będzie zbyt kosztowna.

4. Jakie nowe abstrakcje pozostały do odkrycia?

Nie jestem pewien, jak rozsądna jest taka nadzieja, ale osobiście bardzo chciałbym odkryć nową abstrakcję – coś, co mogłoby mieć taką samą wagę, jak funkcje pierwszego rzędu czy rekursja, albo przynajmniej parametry domyślne. Może to nieosiągalne marzenie. Takie rzeczy rzadko są odkrywane. Ale nie tracę nadziei.

Mało znane tajemnice

1. Możesz używać dowolnego języka, który zechcesz

Kiedyś tworzenie aplikacji oznaczało tworzenie oprogramowania na komputer stacjonarny. A w oprogramowaniu desktopowym jest silny nacisk na pisanie aplikacji w tym samym języku, co system operacyjny. Tak więc dziesięć lat temu pisanie oprogramowania generalnie oznaczało pisanie go w języku C. W końcu tradycja ewoluowała: aplikacje nie muszą być pisane w nietypowych językach. Ta tradycja rozwijała się na tyle długo, że nawet nietechniczne osoby, takie jak menedżerowie i inwestorzy venture capital, również to zrozumiały.

Oprogramowanie serwerowe całkowicie niszczy ten model. W oprogramowaniu serwerowym możesz używać dowolnego języka, który zechcesz. Prawie nikt jeszcze tego nie rozumie (szczególnie menedżerowie i inwestorzy venture capital). Ale niektórzy hakerzy to rozumieją, dlatego słyszeliśmy o takich językach jak Perl i Python. Nie słyszymy o Perlu i Pythonie, ponieważ ludzie używają ich do pisania aplikacji na Windows.

Co to oznacza dla nas, ludzi zainteresowanych projektowaniem języków programowania, to to, że istnieje potencjalna publiczność dla naszej pracy.

2. Szybkość pochodzi z profilerów

Twórcy języków lub przynajmniej ich implementatorzy uwielbiają pisać kompilatory, które generują szybki kod. Ale myślę, że to nie to sprawia, że języki są szybkie dla użytkowników. Knuth dawno zauważył, że szybkość zależy od kilku wąskich gardeł. I każdy, kto próbował przyspieszyć program, wie, że nie da się zgadnąć, gdzie jest wąskie gardło. Profiler jest odpowiedzią na to.

Programiści języka rozwiązują niewłaściwy problem. Użytkownicy nie potrzebują, aby benchmarki działały szybko. Potrzebują języka, który pokaże, które części ich programów powinny zostać przepisane. W tym momencie prędkość jest istotna w praktyce. Może więc lepiej byłoby, gdyby realizatorzy języka poświęcili pół czasu, który przeznaczają na optymalizację kompilatora, aby napisać dobrego profilera.

3. Potrzebujesz aplikacji, która zmusza twój język do rozwoju

Może to nie jest ostateczna prawda, ale wydaje się, że najlepsze języki rozwijały się wraz z aplikacjami, w których były używane. C został stworzony przez ludzi, którzy potrzebowali programowania systemowego. Lisp został częściowo opracowany do symbolicznego różniczkowania, a McCarthy był tak niecierpliwy, że zaczął pisać programy do różniczkowania już w pierwszym dokumencie o Lispie w 1960 roku.

Jest to szczególnie korzystne, jeśli twoja aplikacja rozwiązaniu nowe problemy. To zmusza twój język do posiadania nowych możliwości, które są potrzebne programistom. Osobiście interesuje mnie pisanie języka, który będzie dobry dla aplikacji serwerowych.

[Podczas dyskusji, Guy Steele również wyraził tę myśl, dodając, że aplikacja nie powinna składać się z napisania kompilatora dla twojego języka, chyba że twój język jest przeznaczony do pisania kompilatorów.]

4. Język powinien być odpowiedni do pisania programów jednorazowych.

Wiesz, co oznacza program jednorazowy: to wtedy, gdy musisz szybko rozwiązać jakieś ograniczone zadanie. Uważam, że jeśli rozejrzysz się dokoła, znajdziesz wiele poważnych programów, które zaczynały jako jednorazowe. Nie zdziwiłbym się, gdyby większość programów zaczynała jako jednorazowe. Tak więc, jeśli chcesz stworzyć język, który będzie odpowiedni do pisania oprogramowania w ogóle, to musi on również pasować do pisania programów jednorazowych, ponieważ to jest początkowy etap wielu programów.

5. Składnia związana jest z semantyką

Tradycyjnie uważa się, że składnia i semantyka to rzeczy mocno różniące się. Może to zabrzmieć szokująco, ale tak nie jest. Uważam, że to, co chcesz osiągnąć w swoim programie, jest związane z tym, jak to wyrażasz.

Niedawno rozmawiałem z Robertem Morrisem, który zauważył, że przeciążenie operatorów jest dużym atutem w językach z infiksową składnią. W językach z prefiksową składnią każda definicja funkcji praktycznie jest operatorem. Jeśli chcesz zdefiniować nowy typ liczby, który wymyśliłeś, możesz po prostu zdefiniować nową funkcję do jej dodawania. Jeśli zrobisz to w języku z infiksową składnią, zauważysz, że istnieje duża różnica między użyciem przeciążonego operatora a wywołaniem funkcji.

Idee, które wracają z czasem

1. Nowe języki programowania

Wspominając lata 70., była moda na rozwój nowych języków programowania. Teraz jest inaczej. Ale sądzę, że oprogramowanie serwerowe znów przywróci modę na tworzenie nowych języków. Dzięki oprogramowaniu serwerowemu możesz używać dowolnego języka, który chcesz, więc jeśli ktoś stworzy język, który wydaje się lepszy od innych, znajdą się ludzie, którzy zdecydują się go używać.

2. Podział czasu

Richard Kelsey przedstawił tę ideę, która znowu nadeszła, i w pełni ją popieram. Moje przypuszczenie (i Microsoft również) jest takie, że wiele obliczeń przeniesie się z komputerów stacjonarnych na zdalne serwery. Innymi słowy, podział czasu wrócił. Myślę, że będzie potrzebne wsparcie na poziomie języka. Na przykład Richard i Jonathan Reeves wykonali wiele pracy nad wprowadzeniem planowania procesów w Scheme 48.

3. Efektywność

Niedawno wydawało się, że komputery są już wystarczająco szybkie. Coraz częściej słyszymy o kodzie bajtowym, co przynajmniej dla mnie oznacza, że mamy zapas mocy obliczeniowej. Ale myślę, że w przypadku oprogramowania serwerowego nie mamy go. Ktoś będzie musiał zapłacić za serwery, na których działa oprogramowanie, a liczba użytkowników, których serwer może obsłużyć w przeliczeniu na jedną maszynę, będzie dzielnikiem ich kosztów kapitałowych.

Uważam, że efektywność będzie miała znaczenie, przynajmniej w wąskich gardłach obliczeń. Szczególnie ważne będzie to dla operacji wejścia/wyjścia, ponieważ aplikacje serwerowe generują wiele takich operacji.

W końcu może okazać się, że bajt-kod nie jest rozwiązaniem. Sun i Microsoft w tej chwili zdają się stawać twarzą w twarz w dziedzinie bajt-kodu. Robią to, ponieważ bajt-kod to wygodne miejsce na wkomponowanie się w proces, a nie dlatego, że sam bajt-kod jest dobrym pomysłem. Może się zdarzyć, że cała ta bitwa przejdzie bez echa. To by było zabawne.

Pułapki i sidła

1. Klienci

To tylko spekulacja, ale polega ona na tym, że wygrają tylko te aplikacje, które będą całkowicie serwerowe. Projektowanie oprogramowania zakładającego, że każdy będzie miał twojego klienta, przypomina tworzenie społeczeństwa opartego na założeniu, że wszyscy będą uczciwi. To by było zdecydowanie wygodne, ale musisz założyć, że to nigdy się nie zdarzy.

Myślę, że będzie szybki wzrost liczby urządzeń z dostępem do sieci, a można założyć, że będą wspierać podstawowy HTML i formularze. Masz przeglądarkę w swoim telefonie? Czy telefon będzie w twoim PalmPilocie? Czy twój Blackberry będzie miał większy ekran? Czy będziesz mógł wyjść w sieć z Gameboya? Z zegarka? Nie wiem. I nie muszę tego wiedzieć, jeśli założę, że wszystko będzie na serwerze. Po prostu znacznie bezpieczniej jest mieć wszystkie zasoby na serwerze.

2. Programowanie obiektowe

Rozumiem, że to kontrowersyjne stwierdzenie, ale nie uważam, że OOP jest czymś ważnym. Myślę, że to odpowiednia paradigma dla konkretnych aplikacji, które potrzebują specyficznych struktur danych, takich jak systemy okienkowe, symulacje, systemy CAD. Ale nie rozumiem, dlaczego powinna być odpowiednia dla wszystkich programów.

Myślę, że ludzie w dużych firmach lubią OOP, częściowo ponieważ daje wiele z tego, co wygląda na pracę. To, co naturalnie można przedstawiać jako na przykład listę liczb całkowitych, może teraz być przedstawiane jako klasa z wszelkimi rodzajami konstrukcji, z hałasem i zgiełkiem.

Inną atrakcyjną cechą OOP jest to, że metody dają ci pewien efekt funkcji pierwszej klasy. Ale to nie jest nowość dla programistów w Lispie. Kiedy masz prawdziwe funkcje pierwszej klasy, możesz je używać w każdym sposób, który odpowiada postawionemu zadaniu, zamiast wciskać wszystko w szablon klas i metod.

Myślę, że oznacza to, że w projektowaniu języków nie powinniśmy zbyt głęboko integrować OOP. Może odpowiedzią jest oferowanie bardziej ogólnych, podstawowych rzeczy i pozwolenie ludziom na projektowanie dowolnych systemów obiektowych jako bibliotek.

3. Projektowanie przez komitet

Jeśli twój język jest projektowany przez komitet, to jesteś w pułapce, i to nie tylko z powodów dobrze znanych. Wszyscy wiedzą, że komitety mają tendencję do tworzenia złożonego, niespójnego projektu języka. Ale myślę, że większym zagrożeniem jest to, że nie podejmują ryzyka. Kiedy na czoło wychodzi jedna osoba, to ona podejmuje ryzyka, na które komitet nigdy nie zgodzi się.

Czy trzeba ryzykować, aby stworzyć dobry język? Wiele osób może podejrzewać, że projektowanie języka to dziedzina, w której należy trzymać się blisko tradycyjnej mądrości. Mogę się spierać, że tak nie jest. W każdym innym aspekcie, który dotyczy ludzi, nagroda jest proporcjonalna do ryzyka. Dlaczego więc w projektowaniu języków miałoby być inaczej?

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster