Strona główna - poczytaj o JavaScript, jQuery, CSS i HTML5

Front-Trends 2010

Setki standardów, tysiące problemów i tylko jeden JavaScript

Przysłowiowa współpraca front-endu z back-endem nie zawsze jest usłana różami. Programiści z pierwszej frakcji są najczęściej bombardowani przez swoich „oponentów” narzekaniami na niemal wszystkie (w dodatku pomnożone przez siebie) wady JavaScriptu i kodu opartego o divy. Back-endowi zarzuca się z reguły to, dlaczego na stronie jest X, a nie Y, zgodnie z wcześniejszymi umowami. Abstrahując od celowej hiperbolizacji, warto tak naprawdę zastanowić się, czy między wierszami nie przemknęło nam czasem maleńkie ziarenko prawdy. Mianowicie, czy JavaScript, CSS i XHTML noszą na swoich plecach pokaźny garb wyraźnych niedociągnięć i problemów, które programistę server-side po prostu irytują i przyprawiają o śmiech politowania?

Jawa czy sen?

By podejść do tematu z lepszej strony, zobaczmy, jak (w dużym uproszczeniu) wygląda development w JAVA. Mamy kompilator. Mawia się, że najpierw był kompilator, a dopiero potem wszystko inne. Tak naprawdę jednak jest to wręcz niebagatelne przyspieszenie pracy. Większość błędów programisty wykrywa właśnie on, dlatego na ewentualny debug kodu poświęca się naprawdę mało czasu. Aplikacje po prostu działają.

Z kolei system wyjątków pomoże nam w tym, czego nie zrobi kompilator Możemy z łatwością wyłapać niestandardowe zachowania programu i stosownie je obsłużyć. Całość dopełnia fakt, że JAVA jest w pełni obiektowym językiem – rzadko zdarza się (wcale?), że kod napisany w jednym miejscu, nadpisuje inny. Hermetyzacja robi swoje.

Do skutecznego i łatwego deploymentu, szybkiego uruchamiania projektów, czy po prostu utrzymywania ich mamy takie narzędzia, jak choćby Maven, Ant , czy Log4J.

Domek z kart

Jeśli chodzi o CSS i XHTML, wspierane przez JavaScript, można odnieść wrażenie, że to klocki, z których możemy coś poskładać, aczkolwiek nie możemy być pewni, czy w przyszłości nie trafi się element, który zburzy nam mozolnie tworzoną budowlę.

O ile CSS i XHTML współpracują ze sobą dość dobrze, tak JavaScript sprawia wrażenie przyszywanego wujka. Przede wszystkim, w JS pokutuje prawie to samo, co w PHP – naciągana obiektowość. Teoretycznie JavaScript jest obiektowy, ale by osiągnąć dziedziczenie, czy też ścisłą kontrolę dostępu trzeba postarać się o naprawdę wymyślny kawałek kodu, który w znacznej mierze trąci zawodami w hakowaniu, bądź konkursem na długość przyrodzenia. Dość powiedzieć, że dziedziczenie można uzyskać niejedną metodą, a każda różni się dość znacznie od poprzedniczki. Mawiają, że z gówna bata nie ukręcisz, jednak w JavaScript udaje się to bez problemów. Nie będę nawet wspominał o tym, że deklaracja klasy odbywa się poprzez function.

„Skopaną” konstrukcję poznajemy po tym, że wystarczy uszkodzić jeden element, by całość legła w gruzach w mgnieniu oka. Podobnie jest z JS. Niedostatki obiektowości powodują, że nie mamy choćby kontroli typów, przez co mnożą się instrukcje warunkowe, wspomagane przez typeof.

Kompilator

Za kompilator robią tutaj z reguły konsola błędów oraz narzędzia typu Firebug. Co to jednak za pomoc, skoro w gruncie rzeczy sami musimy analizować kod i czaić się na potencjalne błędy, używając call stacków (polskie „czujki”).

Pierwszy z brzegu przykład:

W pierwszym wypadku kompilator JAVA zgłosi niezgodność typów. Natomiast JavaScript z łatwością przepuści taką operację. To tylko wierzchołek góry lodowej problemów, z którymi stykamy się na co dzień. Zapewne większość z Was nieraz wyrywała sobie włosy z głowy, przytłoczona poszukiwaniami pod tytułem “gdzie to cholerstwo schowało się w IE” lub “dlaczego pod Fx jest null, a gdzie indziej, powiedzmy, 31137“. Można rzec, że taka jest już cecha języków skryptowych – ewentualne błędy wychwycić można dopiero po uruchomieniu całego programu. Programiści najbardziej chwalą je ze względu na szybkość. W przypadku JavaScript nie jest to najtrafniejszy argument – już 300 tysięcy iteracji potrafi zawiesić przeglądarkę.

Istotną wadą JS jest jego permanentna zależność od czynników zewnętrznych. Jesteśmy narażeni na skutki niepoprawnej implementacji ECMAScript (i DOM) przez przeglądarki, a następnie na przydział zasobów systemowych dla nich.

Mimo że w JavaScript można zrobić naprawdę wielkie rzeczy, to język przypomina raczej prototyp niż finalną wersję. Razi też jego mała integracja z HTML (XML) jako takim. W końcu JavaScript to interpretacja ECMAScriptu w założeniach ściśle związana z webem. Dlaczego przeglądarka dopuszcza document.getElementById(‘foobar’), kiedy w dokumencie nie ma żadnego elementu o takim identyfikatorze? W gruncie rzeczy, powinniśmy być ostrzegani przed taką ewentualnością. W jaki sposób?

Kłania się potrzeba kompilatora lub czegoś w tym rodzaju. Najlepiej byłoby, gdyby tłumaczył on kod JS na inny, ściśle znany tylko przeglądarce. Tylko skompilowany program mógłby zostać użyty na stronach internetowych. W innym wypadku, dołączenie plików “przypominających” poprawny JS byłoby niemożliwe.

Na pewno uniknęlibyśmy wielu błędów. Z pewnością devlopment zostałby również przyspieszony. Podejrzewam też, że szybkość wykonania programów w JS (bo już nie skryptów) byłaby o wiele większa, niż jest ona obecnie. Z drugiej strony, kod zostałby zamknięty na zewnątrz.

Standaryzacja!

By sen się ziścił, potrzeba klarownych reguł języka. JavaScript musi stać się w pełni obiektowy. Również relacje z HTML powinny być o wiele bardziej zacieśnione. Nie ukrywajmy tego, skoro w JavaScript istnieje obsługa DOM, dlaczego jeszcze bardziej nie popchnąć języka w tę stronę? Przecież większość skryptów odnosi się do struktury dokumentów HTML!

Pisałem to już jakiś czas temu, napiszę jeszcze raz:

Ta jedyna w swoim rodzaju zależność języka od czynników zewnętrznych (przeglądarki) skazuje JavaScript na dość powolny i niejednostajny rozwój. Pozornie specyfikacja jest taka sama dla wszystkich, jednak szybkość działania diametralnie różna

JavaScript 2

Sytuację próbuje ratować JavaScript 2, bazujący na ECMAScript 4. Pojawiają się deklaracje klas, typizacja, specyfikatory dostępu i wszystko inne, czego dobry programista mógłby sobie zażyczyć. Niestety, i tutaj musiała znaleźć się łyżka dziegciu. JavaScript 2 ze względu na taką, a nie inną obiektowość, jest praktycznie niekompatybilny wstecz. Biorąc pod uwagę miażdżącą popularność JS 1.* w internecie, nie wyobrażam sobie wejścia na rynek JS 2 bez zgodności wstecznej. Na to z kolei dość krzywym okiem spoglądają producenci przeglądarek.

Mamy tutaj dwa wyjścia – wprowadzić JS2 ze wsteczną kompatybilnością lub bez niej. Pierwsze wyjście może przypominać analogiczną sytuację z PHP4 i PHP5 – było niby świeżutkie i piękne PHP5, jednak proces migracji na nową platformę trwał latami. Boje się, że w przypadku JavaScriptu będzie podobnie – po co uczyć się nowej składni (a propos składni, wkrótce postaram się omówić nowe elementy JavaScript 2), skoro stara jest prosta i, co najważniejsze, działa?

Rewolucja pożera własne dzieci

Powyższa sytuacja obrazuje tak naprawdę, gdzie stoi dziś programowanie front-endu, a gdzie może być w przyszłości. Prawdopodobnie pomiędzy drugą a trzecią literką słowa web 2.0 zatraciliśmy, nie ukrywajmy, zdroworozsądkowy krytycyzm. Tworzymy standardy, propagujemy semantyczną sieć, jednak wydaje się, że reformować system powinniśmy od korzeni. Po co tworzyć 100 standardów, z których każdy mówi o zupełnie innym zagadnieniu. Robimy strony, używając w większości tych samych technologii – dlaczego z każdym rokiem nie konsolidujemy ich ze sobą, a wymyślamy ich nowe, niezależne definicje, które powodują 100 razy więcej problemów?

Komentarze

1

Ciekawy wpis. Próbowałem kilka razy zabrać się za javascript, ale za każdym razem przestawałem i odkładałem go na “półkę”. Przydałby się do niego kompilator, łatwiejsze by było chociażby szukanie błędów i testowanie. Może jak JS 2 stanie się popularny to wrócę do nauki ;]

2

Wszystko co piszesz jest prawdą. Może alternatywą jest Flex? Nie trzeba się babrać z ie3, ie4, ie5, ie5.5, ie6, ie7, ie8, ff2, ff3, ff3@linux, opera, chrome, konqueror, safari itp. GUI jest jedno wszędzie te same, a w backendzie może być pełna dowolność. Flash playera, każdy już teraz ma.

wowo
3

Artykuł całkiem dobrze się czytało. Porusza sporo ważnych aspektów. Częściowo się z Tobą zgadzam, ale nie we wszystkich kwestiach.

O ile CSS i XHTML współpracują ze sobą dość dobrze, tak JavaScript sprawia wrażenie przyszywanego wujka. Przede wszystkim, w JS pokutuje prawie to samo, co w PHP – naciągana obiektowość.

Tutaj nie zgadzam się o tyle, że JavaScript ma po prostu inne podejście do obiektowości. Wszystko jest oparte o prototypy. Ale większość patrzy na JavaScript przez pryzmat innych języków z obiektówką o składni zbliżonej do Javy. Także możemy tutaj mówić tylko o pewnym przyzwyczajeniu i nawet nie staramy się zrozumieć specyfiki tego języka. Przez wiele lat nikomu to nie przeszkadzało i JavaScript zyskał swoją popularność.

Niedostatki obiektowości powodują, że nie mamy choćby kontroli typów, przez co mnożą się instrukcje warunkowe, wspomagane przez typeof.

JavaScript ma dynamiczną typizację, jak wiele innych języków skryptowych. Jedni programiści wolą języki ze ścisłą typizacją, inni z dynamiczną. Także, uważam, że nie można tutaj mówić o wadach takiego rozwiązania, bo fakt ten ściśle wiąże się ze specyfiką tego typu języków i wybór zależy wyłącznie od upodobań programisty. Obydwa rozwiązania mają swoje wady i zalety.

Jak pisałeś, JavaScript 2 miał oferować pełną obiektowość znaną z innych języków. Nie twierdzę, że to złe, bo jednak przyzwyczajenia biorą górę i szkoda marnować czasu na niestandardowy w tym momencie model obiektowości. Uważam, że migracja na nową wersję języka miałaby szansę na szybkie zaistnienie, ale tylko pod warunkiem szybkiego wprowadzenia obsługi przez poszczególnych producentów przeglądarek. Oczywiście konieczna byłaby możliwość współistnienia obydwu wersji języka jednocześnie na stronie. Nie wszyscy przecież są programistami i będą korzystać z gotowych skryptów na swoich stronach. Raz trafią na skrypt “starej generacji”, drugi raz na skrypt napisany w JS2. A to znowu wiąże się z koniecznością utrzymywania dwóch silników JS w przeglądarkach… oj, kiepsko to wygląda. Rozsądnym rozwiązaniem wydaje się być ta wsteczna kompatybilność, ale jak sam napisałeś, nie wszyscy chcą się w to bawić.

By sen się ziścił, potrzeba klarownych reguł języka. JavaScript musi stać się w pełni obiektowy. Również relacje z HTML powinny być o wiele bardziej zacieśnione. Nie ukrywajmy tego, skoro w JavaScript istnieje obsługa DOM, dlaczego jeszcze bardziej nie popchnąć języka w tę stronę? Przecież większość skryptów odnosi się do struktury dokumentów HTML!

Tutaj bym nieco uważał. Nie zapominaj proszę, że JavaScript nie jest wyłącznie językiem związanym z HTMLem. Język ten znajduje wiele innych zastosowań – nawet coraz szerzej wkrada się na stronę serwera. Czy tam jest potrzebna aż tak ścisła współpraca z HTMLem? Czy tej koniecznej współpracy nie spełniałby sam model DOM?

Poza tym, czy JavaScript nie posiada klarownych reguł w postaci specyfikacji ECMA-Scriptu? Czy na prawdę musi stać się językiem w pełni obiektowym z wyższej konieczności? Czy to tylko – jak już pisałem – nasze przyzwyczajenia?

Kłania się potrzeba kompilatora lub czegoś w tym rodzaju. Najlepiej byłoby, gdyby tłumaczył on kod JS na inny, ściśle znany tylko przeglądarce. Tylko skompilowany program mógłby zostać użyty na stronach internetowych. W innym wypadku, dołączenie plików “przypominających” poprawny JS byłoby niemożliwe.

Ta idea, moim zdaniem, odbiłaby się na dynamice i pewnej łatwości w tworzeniu aplikacji webowych. Obecnie wystarczy zasiąść za komputer, otworzyć notatnik i napisać skrypt. Wprowadzenie dodatkowego elementu wiązałoby się z koniecznością instalacji/posiadania dodatkowego oprogramowania. W tym momencie całe to oprogramowanie trzebaby nosić cały czas przy sobie, żeby cokolwiek napisać. Poza tym, co taki kompilator by dał? Byłby w zasadzie w stanie wyłapać błędy składniowe (co konsole błędów wbudowane w przeglądarki potrafią) i kontrolować typy danych (jeśli język stałby się ściśle typizowanym językiem). A reszta? Nie dałoby się wychwycić wielu rzeczy w procesie kompilacji, bo sam HTML, na którym nasze skrypty operują jest jedną wielką zmienną, która dynamicznie się zmienia. Tutaj uważam kompilator za całkiem zbyteczny element.

Mianowicie, czy JavaScript, CSS i XHTML noszą na swoich plecach pokaźny garb wyraźnych niedociągnięć i problemów, które programistę server-side po prostu irytują i przyprawiają o śmiech politowania?

Może i jest to faktem, ale programiści serwerowi mają o tyle ułatwioną sprawę, że mają na serwerze jedno oprogramowanie i wiedzą, co i jak mają pisać. Programiści aplikacji klienckich mają sprawę o tyle utrudnioną, że muszą borykać się z kilkoma silnikami przeglądarek, których producenci przyzwyczaili nas do wprowadzania własnych autorskich rozszerzeń, a nie dbają o kompletną i poprawną implementację tego co zostało zdefiniowane w standardach. Co więcej, większość z dzisiaj obowiązujących standardów nadawała się dobre kilka lat temu, dzisiaj niestety stają się powoli bezużyteczne. Świat idzie do przodu i te najważniejsze standardy powinny się rozwijać. A jak sam napisałeś, definiuje się coraz to nowsze standardy, które nie są implementowane i przez to są bezużyteczne. Za przykład weźmy XHTMLa. Tak, ma swoje zalety, ale po co to? Wystarczy przecież rozbudować i zaktualizować starego poczciwego HTMLa i wszystko będzie dobrze. Wydaje się, że częściowo deweloperzy to zrozumieli i opracowuje się obecnie “coś” zwane HTML5.

Najlepiej byłoby zacząć wszystko od nowa, ale łatwo się mówi, gorzej wykonać. Nowy standard dzisiaj zdefiniować to banał, ale czekanie na implementację standardu w nieskończoność skutecznie zniechęca. Z dnia na dzień nie zmieni się całej sieci, więc niestety muszą wystarczyć półśrodki w postaci drobnych zmian aktualnie obowiązujących standardów.

rzadko zdarza się (wcale?), że kod napisany w jednym miejscu, nadpisuje inny. Hermetyzacja robi swoje.

Tak, tu się zgadzam. Wprowadzenie przestrzeni nazw skutecznie rozwiązałoby problem.

To chyba tyle chciałem przekazać. Jak sobie jeszcze coś przypomnę, to dopiszę.

4

@wowo: a czy na telefonie czy palmtopie też każdy ma Flash Playera? ;>

5

@Gucman: na noki 3310 nie, ale na G1 tak :-)
Wiem, wiem, flex nie nadaje się do wszystkiego, ale zrobić w nim specjalizowany panel administracyjny, to moim zdaniem całkiem dobry pomysł.

wowo
6

Flex? IMHO zły pomysł. Z Flashem wbrew pozorom jest jeszcze spooro problemów. Telefony komórkowe, linux (nie u wszystkich, ale mi np. średnio raz na godzinę/dwie flash zawiesi przeglądarkę), etc. Jednak JavaScript tutaj wygrywa (AFAIK nawet Opera Mini ma prymitywną, ale zawsze obsługe JS).

A co do dynamiczna typizacja vs ścisła typizacja – jedno i drugie ma zalety. W PHP mam dynamiczną, w C++ ścisłą i nie narzekam.

To tysiące standardów, to setki problemów, to jeden JavaScript, więc ugryź suchara ;)

PS. Co Wy, ludzie macie z JAVA-mi, UNIX-ami, LINUX-ami? niedługo będzie MICROSOFT WINDOWS…

7

@Rafał Kukawski

Tutaj nie zgadzam się o tyle, że JavaScript ma po prostu inne podejście do obiektowości. Wszystko jest oparte o prototypy. Ale większość patrzy na JavaScript przez pryzmat innych języków z obiektówką o składni zbliżonej do Javy.

Tak, obiektowka jest inna, ale o wiele bardziej niewygodna. O to glownie sie rozchodzilo, acz zrecznie pominales argumenty o tym mowiace ;-)

JavaScript ma dynamiczną typizację, jak wiele innych języków skryptowych. Jedni programiści wolą języki ze ścisłą typizacją, inni z dynamiczną. Także, uważam, że nie można tutaj mówić o wadach takiego rozwiązania, bo fakt ten ściśle wiąże się ze specyfiką tego typu języków i wybór zależy wyłącznie od upodobań programisty. Obydwa rozwiązania mają swoje wady i zalety.

Jesli chodzi o proste rozwiazania – dynamiczna typizacja to zbawienna cecha jezyka – szybko, prosto, latwo etc. Schody zaczynaja sie, kiedy trzeba utrzymywac duzy kod.

Tutaj bym nieco uważał. Nie zapominaj proszę, że JavaScript nie jest wyłącznie językiem związanym z HTMLem. Język ten znajduje wiele innych zastosowań – nawet coraz szerzej wkrada się na stronę serwera. Czy tam jest potrzebna aż tak ścisła współpraca z HTMLem? Czy tej koniecznej współpracy nie spełniałby sam model DOM?

Poza tym, czy JavaScript nie posiada klarownych reguł w postaci specyfikacji ECMA-Scriptu? Czy na prawdę musi stać się językiem w pełni obiektowym z wyższej konieczności? Czy to tylko – jak już pisałem – nasze przyzwyczajenia?

Popatrzcie na jedno – najpierw byl JS w kontekscie webu, dopiero potem powstaly jego ewolucje, inne zastosowania (vide dodatki do Fx itd.). Podobnie bylo z PHP – np. PHP GTK. W obydwu przypadkach mamy do czynienia z jezykami niedopracowanymi, nadajacymi sie do szybkich i prostych zastosowan. Kiedy jednak przychodzi co do czego, w kwestii duzych projektow, wychodza wszelkie wady tych jezykow.

Nie nalezy jednak przesadzac w druga strone – nie robic z JS kombajnu, w ktorym nie napiszemy szybko 2 linijek kodu jak dotychczas. Chodzi raczej o to, by rozwinac ten jezyk na tyle, by utrzymanie i DEBUG kodu byl o wiele przyjemniejszy. Mnie gimnastyka z Firebugiem srednio odpowiada.

Co do kompilatora – to taka moja abstrakcja – nie musi to byc kompilator w sensie stricte, ale jakze fajnym udogodnieniem byloby, gdyby cos sprawdzalo za nas wszelkie odniesienia do DOM, niezgodnosc typow, brak return false/preventDefault w onclickach itd. Zastosowan bylaby cala masa, moze pokusze sie kiedys o jakis manifest przedstawiajacy funkcje takiego rzekomego kompilatora.

W kazdym razie JS, co chcialem wyrazic generalnie w artykule, jest bardzo ciezkim w utrzymaniu jezykiem, majacym wiele wspolnych cech z PHP – a glowna jest masa problemow i niezgodnosci, ktore z latwoscia moglyby byc naprawione na rzecz szybszego i skuteczniejszego developmentu.

Pozdrawiam i dziekuje za tresciwy komentarz!

8

Co do kompilatora – to taka moja abstrakcja – nie musi to byc kompilator w sensie stricte, ale jakze fajnym udogodnieniem byloby, gdyby cos sprawdzalo za nas wszelkie odniesienia do DOM, niezgodnosc typow, brak return false/preventDefault w onclickach itd. Zastosowan bylaby cala masa, moze pokusze sie kiedys o jakis manifest przedstawiajacy funkcje takiego rzekomego kompilatora.

Napisz, jestem ciekawy. Bo o ile zgadzam się z Rafałem, to fakt faktem, że JS nie jest doskonały :).

Zastanawiam się tylko, ile można wycisnąć z języka czy „kompilatora” w sytuacji, gdy strony są tak dynamiczne jak obecnie. DOM jest żywym tworem i można go np. przewrócić do góry nogami, wstawiając dowolny string za pomocą innerHTML.

PS. Przydałoby się większe textarea lub opcja do rozciągania go – obecna wersja nie zachęca do pisania dłuższych komentarzy :).

9

brak kompatybilności wstecz w tym wypadku to nie wada!! Programiści php klną ile wlezie, że nowe wersje są kompatybilne wstecz, przez co język rozwija się wolniej niż powinien i przypomina chorą kobyłę bez ładu i składu. JS sam w sobie jest chory, jeśli chce się uleczyć pacjenta to koniecznie należy zrezygnować z kompatybilności wstecz.

Taką drogą poszedł Python, który zresztą w wersji 2.x jest świetnym językiem. Mimo to developerzy (słusznie!) uznali, że zmiany są na tyle istotne, by wersja 3.0 była niekompatybilna wstecz. A zmiany między Pythonem 2.6 a 3.0 nie są AŻ TAK ogromne, jak należałoby to zrobić między JS 1.x, a 2.x

10

Ja się zastanawiam, czemu zamiast języka, nie można by udokumentować API. Ot, ustalić jakiś model maszyny wirtualnej zintegrowanej w przeglądarką (i dodać uściślenie DOM). W rok-dwa mielibyśmy co najmniej pięć alternatywnych języków programowania, w tym może choć jeden porządny ;-)

To się zresztą dzieje, tylko w pokurczony sposób, przez generowanie JavaScriptu (GWT, Pyjamas, …)

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>