Niebezpieczne Java-Szkoły

From The Joel on Software Translation Project

Revision as of 11:19, 14 September 2009 by Immortal (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Leniwe dzieciaki.

Gdzie się podział kult ciężkiej pracy?

Niewątpliwą oznaką mojego starzenia się jest biadolenie i zrzędzenie, jaka to beznadziejna jest "ta dzisiejsza młodzież". Jeśli coś wymaga od nich wysiłku, to im się nie chce albo nie potrafią.


"Byłeś szczęściarzem. My to przez trzy miesiące musieliśmy mieszkać w pojemniku septycznym wyściełanym zwykłym kartonem. Musieliśmy wstawać o szóstej rano, czyścić karton, jeść twardy jak kamień chleb i gonić do pracy przy młynie, dzień w dzień, po czternaście godzin, a gdy wracaliśmy do domu, ojciec tulił nas do snu przy pomocy paska." — Latający Cyrk Monty Pythona, Four Yorkshiremen


Gdy ja byłem dzieckiem, uczyłem się programować na kartach perforowanych. Jeśli zdarzyło Ci się popełnić jakiś błąd, nie miałeś do dyspozycji żadnych nowoczesnych ficzerów, takich jak na przykład klawisz Backspace. Musiałeś wyrzucić kartę i zacząć od nowa.

Gdy w roku 1991 zaczynałem przeprowadzać rozmowy kwalifikacyjne z programistami, zazwyczaj pozwalałem im wybrać język programowania, w którym chcieliby rozwiązać postawiony przed nimi problem. 99% z nich wybierało język C.

W obecnych czasach wybierają Javę.

Nie zrozumcie mnie źle: Java, jako język stosowany w praktyce, jest całkiem w porządku.

Chwila, chciałbym inaczej sformułować tę myśl. Nie twierdzę wcale, w tym konkretnym artykule, że z Javą, jako językiem stosowanym w praktyce, jest coś nie tak. Z Javą wiele rzeczy jest nie w porządku, ale to musi poczekać na kolejny artykuł.

Twierdzę natomiast, że Java, generalnie, nie jest wystarczająco trudnym językiem, by móc go użyć do odróżnienia programisty przeciętnego od wybitnego. Być może jest to język, w którym wygodnie się pracuje, ale nie to jest dzisiejszym tematem. Mógłbym nawet pójść dalej i powiedzieć, że to, że Java jest stosunkowo łatwym językiem, to ficzer, a nie bug. Ale nie zmienia to faktu, że problem, o którym wspomniałem, wciąż istnieje.

Być możę zabrzmię trochę arogancko, ale moje skromne doświadczenie nauczyło mnie, że na uczelniach, na których wykłada się informatykę, tradycyjnie są dwa zagadnienia, ktorych wiele osób nigdy nie będzie w stanie w pełni pojąć: wskaźniki i rekurencja.

Na studiach dosyć szybko zaczynasz mieć do czynienia ze strukturami danych -- listami połączonymi, tablicami haszującymi itp. Bez wskaźników ani rusz. Tego typu przedmioty często służą do selekcji pierwszoroczniaków: są tak trudne, że każdy, kto nie jest w stanie podjąć umysłowego wyzwania, w końcu się poddaje. I dobrze. Jeśli sądzisz, że wskaźniki są trudne, poczekaj, aż przyjdzie Ci udowodnić coś w teorii punktu stałego.

Historia wielu dzieciaków, którym w liceum dobrze szło programowanie w BASICu kolejnych wersji Ponga, jest taka, że po pójściu do koledżu, zapisaniu się na przedmiot CompSci 101 (struktury danych) i zetknięciu ze wskaźnikami, ich mózgi zwyczajnie eksplodują. Nawet się nie spostrzeżesz, gdy okazuje się, że decydują się jednak skończyć nauki polityczne, bo ten kierunek wydaje im się lepszym pomysłem. Widziałem wiele statystyk pokazujących liczbę studentów, którzy rezygnują ze studiów informatycznych. Zazwyczaj oscylują one w granicach 40% - 70%. Uniwersytety mają skłonność do widzenia tego jako jakiejś straty; Ja z kolei uważam, że to po prostu niezbędny odsiew ludzi, którzy nie byliby szczęśliwi, bądź nie odnieśliby sukcesu, jako programiści.

Innym przedmiotem, sprawiającym wiele trudności młodym studentom informatyki, był ten przedmiot, na którym uczono programowania funkcjonalnego (również programowania rekurencyjnego). MIT postawiło wysoką poprzeczkę, tworząc obowiązkowy kurs (6.001) i wydając podręcznik (Structure and Interpretation of Computer Programs, Abelson & Sussman). Na wielu topowych uczelniach informatycznych używano ich jako de facto wprowadzenia do informatyki. (Masz możliwość, i powinieneś, obejrzeć online starszą wersję tych wykładów.)

Poziom trudności tych kursów jest zdumiewający. Na pierwszym wykładzie poznajesz właściwie wszystko na temat języka Scheme i przedstawiają Ci funkcję z punktem stałym, która na wejściu bierze inną funkcję. Gdy sam walczyłem z tym przedmiotem na Uniwersytecie w Pensylwanii, widziałem jak wielu, jeśli nie większość, studentów po prostu nie dawała rady. Materiał był za trudny. Napisałem wtedy długiego, rzewnego maila do profesora, w którym żaliłem się, że to Nie W Porządku. Ktoś na uniwersytecie musiał mnie posłuchać (albo jednego z innych narzekających), ponieważ teraz, przy prowadzeniu tego kursu, używa się Javy.

Żałuję, że posłuchali.


Myślisz, że się nadajesz? Sprawdź się!


W tym tkwi problem. Lata narzekań leniwych studentów wraz z zarzutami ze strony przemysłu, jak to mało jest absolwentów informatyki, dały się we znaki i w ostatniej dekadzie spora liczba dobrych uczelni całkowicie przerzuciła się na Javę. Super, rekruterom, którzy używają "grepa" do filtrowania życiorysów, to się podoba, i, co najlepsze, żaden aspekt Javy nie jest na tyle trudny, by można było odsiać tych programistów, którzy nie posiadają części mózgu odpowiadającej za wskaźniki i rekurencję, więc statystyki rezygnacji są niższe, a wydziały informatyki mają więcej studentów, wyższe budżety, i wszystko idzie dobrze.

Tym szczęściarzom z Java-Szkół nigdy nie będzie dane zobaczyć dziwnych segfaultów podczas próby implementacji tablic haszujących za pomocą wskaźników. Nigdy nie będą rwać sobie włosów z głowy podczas prób upakowania czegoś w jak najmniejszej liczbie bitów. Nigdy nie będą musieli wytężać swoich umysłow, aby zrozumieć jak to jest, że w czystym języku funkcjonalnym, wartość zmiennej nigdy się nie zmienia, a jednak zmienia się cały czas. Paradoks!

Nie potrzebują tej części mózgu, aby dostać 4 z obrony.

Czy nie jestem przypadkiem jednym z tych staroświeckich maruderów, jak w Four Yorkshiremen, przechwalających się, jakim to twardym trzeba było kiedyś być, żeby to wszystko przetrwać?

Cholera, w roku 1900 łacina i greka były obowiązkowe w koledżu, nie dlatego, że były do czegoś potrzebne, ale dlatego, że uważało się ich znajomość za całkiem oczywistą wśród wykształconych ludzi. W pewnym sensie moje argumenty nie róźnią się niczym od tych przedstawianych przez zwolenników łaciny (wszystkich czterech). "[Łacina] ćwiczy umysł. Ćwiczy pamięć. Rozszyfrowywanie łacińskich zdań jest doskonałym ćwiczeniem myślenia, prawdziwą intelektualną zagadką, oraz dobrym wprowadzeniem do logicznego myślenia.", pisze Scott Barker. W dzisiejszych czasach ciężko jednak znaleźć jakiś uniwersytet, na którym nauka łaciny byłaby wymagana. Czy wskaźniki i rekurencja są łaciną i greką informatyki?

Przyznaję, że programowanie z użyciem wskaźników nie jest potrzebne w 90% kodu pisanego w dzisiejszych czasach, byłoby to wręcz niebezpieczne w kodzie produkcyjnym. W porządku. A programowania funkcjonalnego nie używa się za wiele w praktyce. Zgoda.

Jednakże są to rzeczy ważne, gdy chce się brać udział w niektórych z najbardziej ekscytujących projektów programistycznych. Przykładowo, bez wskaźników nigdy nie będziesz w stanie pracować nad jądrem Linuksa. Nie zrozumiesz nawet jednego wiersza kodu Linuksa (ani żadnego innego systemu operacyjnego) bez dogłębnego zrozumienia wskaźników.

Bez zrozumienia programowania funkcjonalnego nie wymyślisz MapReduce, algorytmu, który sprawia, że infrastruktura Google jest tak skalowalna. Pojęcia Map i Reduce pochodzą od Lispa i ogólnie od programowania funkcjonalnego. Koncepcja MapReduce, patrząc z perspektywy czasu, powinna być trywialna dla każdego, kto ze studiów pamięta, że programy napisane w czystym języku funkcjonalnym nie mają efektów ubocznych i dzięki temu łatwo da się je zrównoleglić. Sam fakt, że to w Google, a nie w Microsofcie, wynaleziono MapReduce, po części tłumaczy, dlaczego Microsoft wciąż męczy się z implementacją najprostszych funkcjonalności dotyczących wyszukiwania, podczas gdy Google zajął się już kolejnym problemem: budową Skynetu^H^H^H^H^H^H - największego na świecie równoległego superkomputera. Sądzę, że Microsoft nie zdaje sobie sprawy, jak daleko jest w tyle.

Poza dostrzegalnym na pierwszy rzut oka znaczeniem wskaźników i rekurencji, ich prawdziwą wartością jest to, że sama nauka o nich daje Ci pewną elastyczność umysłową, niezbędną, aby budować duże, skomplikowane systemy; Wymagają tej mentalnej postawy, która sprawia, że udaje Ci się uniknąć odsiewu na pierwszym roku studiów. Wskaźniki i rekurencja wymagają umiejętności rozumowania, abstrakcyjnego myślenia oraz, co najważniejsze, spojrzenia na problem na wielu poziomach abstrakcji równocześnie. Tak więc zdolność rozumienia wskaźników i rekurencji jest bezpośrednio skorelowana ze zdolnością bycia ponadprzeciętnym programistą.

Fakt ukończenia Java-Szkoły nie ma w sobie nic, co pozwoliłoby od razu rozpoznać absolwentów, którym brakuje umysłowej zwinności pozwalającej zajmować się tymi koncepcjami. Jako pracodawca zauważyłem, że Java-Szkoły zaczynają produkować wielu absolwentów, którzy nie są na tyle bystrzy, by móc pracować w zawodzie programisty nad czymkolwiek bardziej skomplikowanym niż Kolejna Javowa Aplikacja Dla Księgowości, chociaż udało im się jakoś prześlizgnąć przez ten nowy, mocno uproszczony program studiów. Tym studentom nigdy nie udałoby się przetrwać kursu 6.001 na MIT czy CS 323 na Yale, i szczerze mówiąc, jest to jeden z powodów, dla którego ja, jako pracodawca, znacznie bardziej cenię dyplom z MIT czy Yale niż z Duke, które ostatnio całkowicie przerzuciło się na Javę, czy Penn, gdzie na kursie, który nieomal zabił mnie i moich znajomych (CSE121), języki Scheme i ML zastąpiono Javą. To nie tak, że nie chcę zatrudniać bystrzaków z Duke czy Penn -- chcę -- ale jest mi zdecydowanie trudniej ocenić, którzy to są. Kiedyś mogłem ich odróżnić, ponieważ Ci bystrzy potrafili przeanalizować rekurencyjny algorytm w kilka sekund albo zaimplementować funkcje operujące na listach połączonych tak szybko, jak tylko umieli pisać na tablicy. W przypadku absolwenta Java-Szkoły, nie wiem, czy nie radzi on sobie z tymi problemami dlatego, że jest niedoedukowany, czy też może dlatego, że nie posiada on tej wyjątkowej części mózgu, której potrzebuje, by móc ponadprzeciętnie wykonywać swoją pracę jako programista. Paul Graham nazywa ich Blub Programmers.

Fakt, że Java-Szkoły nie odsiewają tych studentów, którzy nigdy nie będą znakomitymi programistami, jest wystarczająco przygnębiający. Uczelnie mogą powiedzieć, że to nie ich problem. Przemysł, a przynajmniej rekruterzy, będący zwolennikami grepa, wydają się być zadowoleni z tego, że uczy się Javy.

Ale Java-Szkoły odnoszą także porażkę, nie ćwicząc umysłów studentów, by byli oni na tyle biegli, sprawni i elastyczni, by dobrze projektować oprogramowanie (i nie mam tutaj na myśli projektowania obiektowego, gdzie spędzasz niezliczone godziny na przepisywaniu kodu, aby przetasować hierarchię klas albo zamartwiasz się fałszywmi "problemami" w rodzaju has-a vs. is-a). Potrzebujesz treningu w myśleniu na wielu poziomach abstrakcji równocześnie, taki rodzaj treningu jest właśnie tym, co pozwoli Ci tworzyć znakomite architektury oprogramowania.

Być może zastanawiasz się, czy nauka programowania obiektowego (OOP - Object-Oriented Programming) jest w stanie zastąpić wskaźniki i rekurencję pod względem zdolności odsiewowej. Szybka odpowiedź: nie. Nie wdając się zbytnio w szczegóły, programowanie obiektowe nie jest wystarczająco trudne, aby odsiać przeciętnych programistów. Nauka programowania obiektowego w szkołach sprowadza się zazwyczaj do wkuwania pojęć w rodzaju "enkapsulacja" czy "dziedziczenie" i rozwiązywania testów wielokrotnego wyboru na temat różnic pomiędzy polimorfizmem i przeciążaniem. Będąc niewiele bardziej wymagającym niż zapamiętywanie znanych dat i nazwisk na lekcjach historii, programowanie obiektowe nie stanowi adekwatnego wyzwania umysłowego, aby odstraszyć pierwszoroczniaków. Gdy męczysz się z jakimś problemem z dziedziny programowania obiektowego, twój program ciągle działa, może jedynie być trudniejszy w utrzymaniu. Powiedzmy. Ale gdy walczysz ze wskaźnikami, a Twój program powoduje błąd segmentacji, nie masz pojęcia, czym to jest spowodowane, dopóki nie zatrzymasz się, nie weźmiesz głębokiego oddechu i naprawdę nie postarasz się zmusić swojego umysłu do pracy na dwóch różnych poziomach abstrakcji równocześnie.

A tak na marginesie, specjalnie ośmieszam tutaj rekruterów korzystających z grepa. Nie spotkałem nigdy nikogo, kto znałby Scheme, Haskella i C, a kto nie potrafiłby opanować Javy w dwa dni i tworzyć w niej lepszy kod niż ludzie z pięcioletnim doświadczeniem w Javie, ale spróbuj wytłumaczyć to przeciętnemu trutniowi z HR.

Co w takim razie z misją wydziałów informatyki? To nie są zawodówki! Ich celem nie powinno być nauczanie ludzi, jak pracować w przemyśle. To zadanie szkół pomaturalnych albo programów rządowych dla pracowników zmuszonych do przekwalifikowania się. Uczelnie powinny oferować studentom podstawowe narzędzia na całe życie, a nie przygotowywać ich do pracy przez kilka pierwszych tygodni. Prawda?

Cs1.png http://www.columbia.edu/acis/history/026.html

Informatyka to dowody (rekurencja), algorytmy (rekurencja), języki (rachunek lambda), systemy operacyjne (wskaźniki), kompilatory (rachunek lambda) -- chodzi mi o to, że taka Java-Szkoła, na której nie wykłada się C ani Scheme, tak naprawdę nie uczy również informatyki. Jakkolwiek bezużyteczne w prawdziwym świecie może wydawać się pojęcie rozwijania funkcji (ang. function currying), to jego znajomość powinna być oczywistym wymogiem dla absolwentów informatyki. Nie mogę zrozumieć, dlaczego profesorzy, którzy biorą udział w ustalaniu programu studiów, zgodzili się na takie uproszczenia, które w rezultacie sprawiają, że uczelnie nie są w stanie produkować programistów zdolnych do wykonywania swojego zawodu. Co więcej, nie są nawet w stanie wyprodukować absolwentów, którzy podejmą studia doktoranckie a w przyszłości powalczą o tytuły profesorskie. Chwila. Nieważne. Może jednak rozumiem.

Właściwie to jeśli cofnąć się w czasie i przyjrzeć dyskusjom toczonym w środowiskach akademickich podczas Wielkiego Przewrotu Javowego, można zauważyć, że największym zmartwieniem było to, czy Java jest wystarczająco prostym językiem, aby używać go w celach dydaktycznych.

Mój Boże, pomyślałem, oni chcą pójść jeszcze dalej z tym upraszczaniem programu studiów! Może powinniśmy podawać studentom wszystko na tacy? Niech asystenci zdają za nich egzaminy. Jak ktokolwiek ma się czegoś nauczyć, jeśli program studiów został starannie zaprojektowany w taki sposób, aby uczynić wszystko łatwiejszym niż jest? Zdaje się, że w planach jest nawet utworzenie specjalnej grupy zadaniowej, której celem miałoby być opracowanie podzbioru Javy, którego używano by do nauczania studentów i stworzenie dokumentacji ukrywającej cały ten bajzel EJB/J2EE przed ich wrażliwymi umysłami, dzięki czemu nie musieliby zaprzątać swoich małych główek tymi wszystkim klasami, niepotrzebnymi do rozwiązania i tak coraz łatwiejszych zadań informatycznych.

Najzabawniejszym wytłumaczeniem, dlaczego wydziały informatyki są tak skłonne do upraszczania swoich programów nauczania, jest to, że dzięki temu mają więcej czasu na naukę naprawdę istotnych koncepcji informatycznych, że nie muszą marnować dwóch wykładów na wyjaśnianie studentom różnicy między javowym słowem kluczowym int a klasą Integer. Cóż, jeśli istotnie tak jest, to kurs 6.001 ma dla nich idealną odpowiedź: Scheme, dydaktyczny język tak prosty, że bystrym studentom można wyłożyć go w ciągu 10 minut; potem cały semestr można poświęcić na teorię punktu stałego.

Heh.

Wracam do zer i jedynek.

(Miałeś jedynki? Szczęściarz z ciebie! My mieliśmy tylko zera.)

Personal tools