Najgorszy wróg kodu

Code's Worst Enemy

Jestem programistą, i to na wakacjach. I zgadnijcie, co robię? Bardzo chciałbym Wam powiedzieć, że popijam Mai Tai na Bahamach, ale w rzeczywistości to, czym zajmuję się w trakcie urlopu to programowanie.

Są to więc wakacje w sensie HR-owym - wziąłem oficjalnie wolne w pracy, by dać sobie trochę czasu na postawienie mojej gry komputerowej na nogi. To gra, którą zacząłem pisać około 10 lat temu i spędziłem jakieś 7 lat na jej rozwijaniu. Nie była dostępna w sieci przez jakiś czas i muszę ją przywrócić - częściowo po to, żeby gracze wreszcie przestali mnie nawiedzać. Zajmie to przynajmniej tydzień pracy dzień w dzień, więc musiałem wziąć wolne.

Dlaczego moja gra trafiła w tryb offline? Nie ze względu na brak popularności. To całkiem udana gra jak na wysiłek jednej osoby na pół gwizdka. Uzyskałem ponad ćwierć miliona użytkowników, którzy ją wypróbowali (a przynajmniej dotarli do etapu tworzenia postaci) i dziesiątki tysięcy ludzi, którzy spędzili niezliczone godziny na graniu w nią przez lata. Gra zdobyła kilka nagród i została przedstawiona w kilku magazynach; przykuła uwagę portali dla graczy, potencjalnych inwestorów i całych rzeszy dzieciaków.

Tak, dzieciaków. To miała być gra dla studentów, a stała się całkiem popularna wśród nastolatków czy nawet młodszych, po których spodziewałbyś się że będą raczej grali w coś trójwymiarowego na konsolę lub coś podobnego. Ale napisałem ją dla siebie i najwyraźniej jest wystarczająco dużo ludzi, którzy lubią gry podobne co ja, aby stworzyć trwałą społeczność.

Ściągnąłem grę z wszelkiego rodzaju przyziemnych powodów - potrzebowała kilku modernizacji, w pracy zrobiło się dość intensywnie, nie cierpiałem na nadmiar czasu w nocy, itd. Ale przyziemne powody sprowadzają się do jednego, głębszego problemu: ilość kodu jest zbyt duża dla jednej osoby.

Spędziłem prawie 10 lat mojego życia na budowaniu czegoś, co jest za duże.

Sporo nad tym myślałem - więcej, niż prawdopodobnie byście przypuszczali. Zajęło to sporą część mojego technicznego umysłu przez ostatnie cztery czy pięć lat, i pomogło w kształtowaniu wszystkiego co w tym czasie napisałem - zarówno na blogach, jak i w kodzie.

Przez dalszą część mojej małej tyrady będę zakładał, że jesteś młodym, inteligentnym uczniem w wieku licealnym (lub trochę starszym), który jest zainteresowany byciem lepszym - a może nawet wspaniałym - programistą.

(Nie myśl, proszę, że próbuję powiedzieć, że jestem wspaniałym programistą. Stronię od tego. Jestem programistą, który przez dekady dopuszczał się strasznych programistycznych okrucieństw, w trakcie których dostałem kilka lekcji, które przekazuję Tobie, z nadzieją, że pomogę Ci w Twoim dążeniu do stania się wspaniałym programistą).

Muszę założyć, że jesteś młody, żebym był w stanie przekazać, to co chcę. Jeśli założę, że przemawiam do “doświadczonych” programistów, skoczy mi ciśnienie i nie będę w stanie skupić się na tyle długo, żeby skończyć swoją przemowę. Zobaczysz za chwilę, dlaczego.

Szczęśliwie dla mnie, jesteś młody i chętny do nauki, więc mogę Ci powiedzieć, jak naprawdę mają się sprawy. Po prostu miej oczy otwarte przez następne kilka lat i sprawdź, czy mam rację.

Widok z perspektywy mniejszości

Tak się składa, że podzielam ciężko zdobytą opinię mniejszości na temat kodu. Konkretniej wierzę - mógłbym dodać, że całkiem zagorzale - że najgorsza rzecz, która może się przydarzyć bazie kodu, to jest rozmiar.

Mówię “rozmiar”, mając na myśli odpowiednio dobrze uformowaną myśl, dla której brakuje mi lepszego słowa w moim słowniku. Będę musiał odrobinę wokół niej pokrążyć zanim zobaczysz, co mam na myśli; być może będziesz w stanie zasugerować lepsze sformułowanie. Słówko “wzdęcie” mogłoby być bardziej odpowiednie, jako że wszyscy wiedzą, że “wzdęcie” jest złe; niestety, większość tak zwanych doświadczonych programistów nie wie, jak wykrywać wzdęcia, i wskażą dość poważnie nabrzmiałe kawałki kodu twierdząc, że są chudziutkie jak osa.

Dobrze, że z nimi nie rozmawiamy, nie?

Twierdzę, że moja opinia jest jedną z ciężko zdobytych, jako że ludzie nie rozmawiają zbyt wiele o ilości kodu; nie jest to powszechnie rozpoznawany problem. W rzeczywistości powszechnie uważa się, że to nie jest problem. To znaczy, że ktokolwiek podzielający moją opinię mniejszości jest uważany za skrajnego szaleńca - bo czy ktokolwiek rozsądny perorowałby przeciwko nie-problemowi?

Ludzie z branży bardzo ekscytują się różnymi pomysłami, które nominalnie pomagają w rozwiązywaniu problemów związanych z dużymi bazami kodu - jak na przykład IDE, które mogą manipulować kodem jak “strukturami algebraicznymi”, indeksami przyspieszającymi przeszukiwanie, i tak dalej. Ci ludzie mają tendencję do patrzenia na kod w sposób, w jaki robotnicy budowlani patrzą na ziemię: chcą wspaniałych, wielkich maszyn, które pozbędą się urobku w taki a taki sposób. Zasada zachowania urobku: nie możesz go skompresować (nie bardzo), więc ich zbiór rozwiązań składa się z rozmaitych sposobów przerzucania go w te i we wte. Są nawet takie pytania podczas rozmów kwalifikacyjnych - z pewnością metaforyczne - dotyczące tego, jak przerzucić całą górę ziemi, i to jedną ciężarówką na raz.

Programiści przemysłowi ekscytują się rozwiązaniami wielkiego nie-problemu. To po prostu wielka góra ziemi, a Ty tylko potrzebujesz dużych narzędzi, by ją przesunąć. Narzędzia są fascynujące, ziemia - nie.

Moja “opinia mniejszości” jest taka: góra kodu to najgorsza rzecz, jaka może się przytrafić osobie, zespołowi, firmie. Wierzę, że ciężar kodu niszczy projekty i firmy, wymusza przepisywanie po osiągnięciu pewnego rozmiaru, a mądre zespoły zrobią wszystko co w ich mocy, by ich baza kodu nie stała się górą. Narzędzia lub ich brak. W to wierzę.

Okazuje się, że musi Ci się przytrafić coś złego zanim zaczniesz podzielać moją opinię. Zła rzecz, która mi się przytrafiła to to, że napisałem piękną grę w brzydkim języku, a rezultat był cudowny zewnętrznie i raczej przerażający wewnętrznie. Przeciętny programista przemysłowy nie znalazłby zbyt wiele błędów w mojej bazie kodu, poza brakiem testów jednostkowych (czego teraz żałuję) które, niestety, podwoiłyby rozmiar już teraz sporej, 500 000-linijkowej bazy kodu. Tym samym, głównym problemem, który by wskazali, jest to, że nie jest ona dostatecznie duża. Gdybym zrobił wszystko idealnie, zgodnie z aktualną modą, znalazłbym się w gorszej sytuacji, niż teraz.

Niektórzy mnie z pewnością nie zrozumieją, więc objaśnię: myślę, że testowanie jednostkowe jest wspaniałe. W istocie uważam że jest kluczowe i bardzo żałuję, że nie mam testów jednostkowych dla mojej gry. Chodzi mi jednak o to, że napisałem ją w sposób, w jaki większość doświadczonych programistów poleciłaby dla tego rodzaju systemów, a teraz jest to obrzydliwie nieogarnialna baza kodu. Gdybym postąpił “dobrze” w kontekście testów jednostkowych, byłoby podwójnie obrzydliwie! Oczywisty paradoks, który tutaj otrzymujemy, jest kluczowy do zrozumienia dlaczego obstaję przy swojej “opinii mniejszości” odnośnie wielkości bazy kodu.

Większości programistów nigdy nie przytrafiło się coś naprawdę złego. W rzadkich przypadkach, gdy zdarza się coś złego, zwykle nie jest to traktowane jako problem większy, niż taki, jaki ma robotnik budowlany z ziemią. Na każdej budowie jest pewna ilość ziemi, a Ty musisz sobie jakoś z nią poradzić. To nie jest “problem”, tylko wyzwanie taktyczne.

Wiele firm zostaje postawionych przed obliczem wielu milionów linii kodu i traktuje to jako zwykły problem narzędzia, nic więcej: mnóstwo ziemi, którą trzeba od czasu do czasu przesunąć.

Większość ludzi nigdy nie musiała opiekować się pół milionem linii kodu samodzielnie; ich spojrzenie może się więc różnić od mojego. Miejmy nadzieję że Ty, będąc młodym, chętnym do nauki osobnikiem, uświadomisz sobie, że jedynymi osobami prawdziwie uprawnionymi do wyrażania opinii w tej kwestii to te osoby, które zajmowały się (i pomagały tworzyć) naprawdę wielkimi bazami kodu.

W odpowiedzi na moją małą przemowę możesz usłyszeć swoiste wycie oraz mnóstwo wypowiedzi w stylu “on po prostu nie rozumie”. Ja twierdzę, że goście, którzy szafują tego rodzaju zapewnieniami, nigdy nie byli pociągnięci do odpowiedzialności za bajzel, który zrobili.

Kiedy napiszesz swoje własne pół miliona linii kodu, nie będziesz w stanie uniknąć odpowiedzialności. Nie mogę winić nikogo poza siebie samym, a to mi pozwoliło uzyskać nową perspektywę - i zakwalifikowało do mniejszości.

To nie tylko wnioski z mojej gry. Ten jeden przypadek mógłby nie dać mi tej lekcji. W ciągu 20 lat spędzonych w przemyśle, ciskałem się przeciwko największym bazom kodu, jakie sobie kiedykolwiek wyobrażałeś, i czyniąc to, nauczyłem się kilku rzeczy, jakich nie większość ludzi się nigdy nie nauczy w ciągu całej swojej kariery. Nie proszę Cię o ukształtowanie swojej opinii w poruszanej przeze mnie sprawie już dzisiaj. Mam po prostu nadzieję, że będziesz miał oczy i uszy otwarte w trakcie kodowania przez następne kilka lat.

Niewidocze wzdęcie

Spróbuję zdefiniować wzdęcie. Wiem, że polegnę; nie mniej jednak mam nadzieję, że naszkicowanie problemu wskaże kilka wzorców.

Są pewne rzeczy, które mogą pójść źle z tymi bazami kodu, które mają ku temu pociąg, i nie trudno większości ludzi zgodzić się, że są “złe”.

Jedną z takich rzecz jest złożoność. Nikt nie lubi skomplikowanej bazy kodu. Jednym ze sposobów mierzenia złożoności jest “złożoność cyklometryczna”, która szacuje możliwe ścieżki wykonania danej funkcji za pomocą statycznej analizy jej struktury.

Jestem całkiem pewien, że nie lubię złożonych baz kodu, ale nie jestem przekonany, żeby złożoność cyklometryczna pomogła w tej kwestii. By uzyskać dobry wynik złożoności cyklometrycznej, musisz po prostu podzielić swój kod na mniejsze funkcje. Dzielenie kodu na mniejsze funkcje było jedną z podstaw “dobrego designu” przez co najmniej 10 lat, w dużej mierze dzięki książce “Refaktoring” Martina Fowlera.

Problem z Refaktoringiem zastosowanym do języków takich jak Java, i jest do dość znaczące dla mojej dzisiejszej tezy, jest taki, że zwiększa on bazę kodu. Szacuję że mniej niż 5% standardowych refaktoringów wspieranych przez IDE powodują, że baza kodu się zmniejsza. Refaktoring to jak sprzątanie Twojej szafy bez wyrzucania czegokolwiek. Jeśli dostaniesz większą szafę i włożysz wszystko do ładnie etykietowanych pudełek, to Twoja szafa będzie niewątpliwie lepiej zorganizowana. Programiści wykazują jednak pewną skłonność do niezauważania, że wiosenne porządki działają najlepiej, gdy chcesz wyrzucić rzeczy, których już nie potrzebujesz.

To prowadzi do drugiej oczywisto-brzydkiej rzeczy, jaka może się przydarzyć bazie kodu: kopiuj-wklej. Nie potrzeba wiele czasu, żeby programista się tego nauczył. To raczej będzie blizna, której się nabawisz, aniżeli zasada do zapamiętania - czy Ci się to podoba, czy nie. Komputery powodują, że kopiuj-wklej jest naprawdę łatwe, więc każdy programista wpada w tą pułapkę raz na jakiś czas. To, czego się nauczysz, to to, że kod zawsze się zmienia, zawsze zawsze zawsze, i jak tylko będziesz musiał zmienić coś w N miejscach, gdzie N jest większe od 1, zyskasz swoją bliznę.

Kopiuj-wklej jest jednak dużo bardziej zdradzieckie, niż większość programistów przemysłowych kiedykolwiek podejrzewało. Podstawowym problemem jest duplikacja, i niestety są wzorce duplikacji, które nie mogą zostać wytępione z kodu w Javie. Te wzorce powtarzają się w Javie wszędzie; są wszechobecne, ale programiści Javy szybko tracą zdolność do ich spostrzegania.

Programiści Javy często zastanawiają się, dlaczego Marting Fowler “opuścił” Javę na rzecz Ruby. Co prawda nie znam Martina, ale myślę że bezpiecznie będzie przypuszczać, że “coś złego” przydarzyło mu się, gdy korzystał z Javy. Wesoło (dla wszystkich za wyjątkiem prawdopodobnie Martina). Myślę że jego “coś złego” mogło być właśnie aktem tworzenia książki Refaktoring, która pokazała programistom Javy jak powiększyć ich szafy i uczynić bardziej zorganizowanymi, podczas gdy Martin nauczył się, że naprawdę chciał pokazać więcej rzeczy w wygodnej szafie o rozmiarze szafy.

Mylę się, Martin?

Tak jak podejrzewałem, nie zdefiniowałem jeszcze wzdęcia konkretniej niż za pomocą niejasnych pojęć. Dlaczego moja baza kodu ma pół miliona linii? Co ten kod naprawdę robi?

Wzorce projektowe nie są atutami

Inną znaczącą książką w projektowaniu oprogramowania były Wzorce Projektowe, które zostawiły uśmiech na twarzy każdego programisty na świecie (zakładając, że świat składa się wyłącznie z programistów Javy i C++).

Wzorce Projektowe to książka ze środka lat dziewięćdziesiątych, która dostarczyła dwudziestu trzech atrakcyjnych pudełek do zorganizowania Twojej szafy oraz mechanizmu rozszerzania do tworzenia nowych pudełek. To była wspaniała sprawa dla tych z nas, którzy próbowali zorganizować swoje upakowane szafy nie mając pudełek, toreb, półek i szuflad. Wszystko, co musieliśmy zrobić to przemodelować nasze domy tak, by nasze szafy mogły być cztery razy większe. I nagle mogliśmy mieć je tak czyste, jak regały wystawowe Nordstrom.

Interesujące było to, że sprzedawcy nigdy nie dali się zafascynować wzorcami projektowymi. Menedżerowie projektów też nie, goście z marketingu także nie, menedżerowie-programiści też nie. Jedynymi ludźmi, którzy ekscytują się Wzorcami Projektowymi są programiści, którzy korzystają z pewnych języków programowania. Programiści Perla nie byli specjalnie pod wrażeniem wzorców projektowych. Jednocześnie programiści Javy źle to oceniali; wnioski były takie, że programiści Perla to niechlujni, kiepscy licencjaci którzy układają stosy ciuchów w ich szafach, aż do samego sufitu.

To jest już oczywiste, czyż nie? Wzorzec projektowy nie jest atutem. Fabryka nie jest atutem; nie jest nim też Delegat, Proxy czy Most. One “umożliwiają” korzystanie z atutów w pewnym bardzo luźnym znaczeniu, dostarczając ładnych pudełek do ich trzymania. Jednakże pudełka, torby i półki zajmują miejsce. Wzorce projektowe - a przynajmniej większość tych przedstawionych w książce “Gang of Four” - powodują, że bazy kodu robią się większe. Tragicznie, większość wzorców z GoF które mogą pomóc zmniejszyć bazę kodu (Interpreter), jest całkowicie ignorowana przez programistów mających nazwy wzorców wytatuowane na różnych częściach ciała.

Wstrzykiwanie zależności jest przykładem nowego, popularnego wzorca projektowego w Javie, o którym programiści Ruby, Pythona, Perla czy JavaScriptu nigdy prawdopodobnie nie słyszeli. A nawet jeśli słyszeli, to prawdopodobnie (i prawidłowo) doszli do wniosku, że go nie potrzebują. Wstrzykiwanie zależności jest niesamowicie rozwlekłą infrastrukturą do uczynienia Javy bardziej dynamiczną na kilka sposobów, które są częścią języków wyższego poziomu. I - zgadłeś - Wstrzykiwanie zależności powiększa Twoją javową bazę kodu.

“Większy” jest czymś, z czym musisz żyć w Javie. Wzrost jest faktem. Java jest jakby jednym z wariantów gry w Tetris, w którym żaden z elementów nie może uzupełnić dziur stworzonych przez inne elementy, a wszystko co możesz zrobić, to układać je bez końca w stos.

Miliony linii kodu

Miałem niedawno okazję oglądać prezentację pewnego programisty Javy. Na jednym ze slajdów były wypisane Problemy (z jego obecnym systemem w Javie); na następnym wypisano Wymagania (dla cudownego oprogramowania, które nigdy nie pojawiło się na rynku). Problemem numer 1 był rozmiar kodu: jego system składał się z milionów linii.

Łał! Z pewnością już to widziałem i naprawdę prawdziwie podzielałem jego uczucia. Geoworks miał grubo ponad 10 milionów linii kodu. Jestem zdania że to było jedną z przyczyn ich bankructwa (choć to znów jest opinią mniejszości - Ci goście nigdy się niczego nie nauczą!). Pracowałem też przez 7 lat dla Amazonu; oni mają grubo ponad sto milionów linii kodu w przeróżnych językach i “złożoność” jest często wymieniana jako ich największy techniczny problem.

Byłem naprawdę zadowolony z faktu, że ten gość wymienił ilość kodu jako problem numer 1.

I wtedy dałem się zaskoczyć. Zmienił slajd na “Wymagania”, na którym to wymienił “musi skalować się na miliony linii kodu” jako wymaganie. Wszyscy za wyjątkiem mnie pokiwali głowami i zaakceptowali wymaganie. Padłem.

Cholera, z jakiego powodu wymieniasz swój problem numer 1 jako wymaganie dla Twojego nowego systemu? To znaczy, jeśli tworzysz wymagania, zwykle starasz się rozwiązywać prolemy zamiast zakładać, że pojawią się ponownie. Wciąłem się w wystąpieniei zapytałem, co on sobie do cholery myślał.

Jego odpowiedź brzmiała tak: “no więc, system ma sporo cech, a im więcej cech, tym więcej kodu, więc miliony linii są Po Prostu Nie Do Uniknięcia”. “To nie jest tak, że Java jest rozwlekła!”, dodał - co jest całkiem zabawne, jako że nie wspomniałem o Javie czy rozwlekłości w moim pytaniu.

Rzecz w tym, że jeśli gapisz się teraz zszokowany tą historią, myśląc “jak ten koleś od Javy mógł być taki ślepy”, jesteś oficjalnie mniejszością w programistycznym światku. Do tego niemile widzianym.

Większość programistów z sukcesem podzieliła swoje wierzenia na temat kodu. Programiści Javy są wyjątkowymi winowajcami, ale nie tylko oni. Po części wiedzą, że duże bazy kodu są złe. Wystarczy szkolna matematyka by zrozumieć, jak złe mogą być. Jeśli masz miliony linii kodu, 50 linii na “stronę”, to masz 20 000 stron kodu. Jak długo zajmie Ci przeczytanie 20 000 stron instrukcji? Wysiłek potrzebny na proste przewertowanie kodu i próbowanie odkrycia jego ogólnej struktury może zająć tygodnie lub nawet miesiące, zależnie od “stężenia”. Znaczące zmiany architektury mogą zająć miesiące, a nawet lata.

Po części myślą też, że ich IDE rozwiąże problem ilości kodu. Za chwilę do tego dojdziemy.

A milion linii to nic, naprawdę. Większość firm pragnęłaby mieć jedynie milion linii kodu. Zwykle jeden zespół jest w stanie wytworzyć tyle przez kilka lat hakowania. Duże firmy publikują obecnie dziesiątki do setek milionów liniii kodu.

Podam Ci streszczenie w pigułce, jednozdaniowe podsumowanie wszystkich lekcji, które dostałem od Złych Rzeczy, które przydarzyły mi się podczas pisania mojej gry w Javie: jeżeli zaczniesz z założeniem że musisz zmniejszyć swoją bazę kodu, w końcu zostaniesz zmuszony do porzucenia Javy. Odpowiednio, jeśli zaczniesz z założeniem, że musisz używać Javy, to zostaniesz zmuszony do pracy nad milionami linii kodu.

Czy ta wymiana jest tego warta? Programiści Javy powiedzą Ci “Tak, to jest tego warte”. Robiąc tak, milcząco przytakują swojej małej części siebie, która wie, że duże bazy kodu są złe, więc przynajmniej wygrałeś tą bitwę.

Powinieneś jednak wszystko, co powie Ci “programista Javy”, traktować z przymrużeniem oka, bo “programista X”, dla każdego X, jest raczej słabym przeciwnikiem. Musisz trenować wiele dyscyplin, żeby zostać znaczącym sportowcem w obecnych czasach. Programiści muszą płynnie posługiwać się wieloma językami z fundamentalnie różnymi “charakterami”, zanim będą w stanie podejmować prawdziwie świadome decyzje projektowe.

Ostatnio zauważam, że Java jest wyjątkowo kiepską wartością dla X. Jeśli koniecznie musisz zatrudnić programistę X, upewnij się, że jest to Y.

Naprawdę nie jest moją intencją skupiać się na Javie w tej przemowie (ani klonach Javy takich jak C#, który - mimo że jest “lepszym” językiem, wciąż ma charakter Javy, czyniąc go językiem w najlepszym przypadku jedynie odrobinę lepszym). Dla pewności, moja opinia mniejszości dotyczy dowolnej bazy kodu w dowolnym języku. Wzdęcia są złe.

Skupiam się jednak na Javie dlatego, że mam tego olbrzymiego słonia kodowego do wskrzeszenia w tym tygodniu. Czy można mnie winić? Być może ktoś z domowym C++-owym słonikiem przybędzie i przyłączy się do naszej mniejszości. Teraz jednak spróbuję skończyć moje wyjaśnienia pojęcia wzdęcia jako problemu korzystając z kontekstu Javy.

Czy IDE mogą Cię uratować?

Społeczność Javy wierzy, z niemalże 100% zgodnością, że nowoczesne IDE rozwiązują problem rozmiaru kodu. Koniec, kropka.

Z tym punktem widzenia związanych jest kilka kłopotów. Jeden z nich to znów prosta arytmetyka: po osiągnięciu pewnej ilości kodu kończą Ci się zasoby do zarządzania tym kodem. Wyobraź sobie projekt z miliardem linii kodu, a potem wyobraź sobie, że próbujesz korzystać z Eclipse czy IntelliJ podczas pracy nad tym projektem. Komputery - procesor, pamięć, dysk twardy, sięc - po prostu by się poddały. Wiemy o tym, jako że bazy kodowe z dwudziestoma milionami linii kodu wychodzą poza zakres nowoczesnych IDE na nowoczesnych maszynach.

Diabli, nigdy nie zdobyłem się na to, żeby zmusić Eclipse do wczytania i zindeksowania nawet mojej 500 000-linijkowej bazy kodu, a spędziłem nad tym tygodnie. Po prostu wywala się, sparaliżowany. Dosłownie zawiesza się (mogę go zostawić na noc i nie ruszy się do przodu). Dwadzieścia milionów linii? Zapomnij.

Możemy ominiąć problem przemieszczając bazę kodu z lokalnej maszyny do klastra obliczeniowego. Prawdziwy problem jest jednak bardziej kulturowy niż techniczny: tak długo, jak użytkownicy IDE będą odmawiać przyznania, że to jest problem, nie zostanie on rozwiązany.

Wracając do naszego szalonego Tetrisa: wyobraź sobie, że masz narzędzie do zarządzania wielkich ekranów Tetrisa, mających setki pięter. W takiej sytuacji układanie elementów w stos nie jest problemem - nie trzeba więc pozbywać się elementów. To jest problem kulturowy: oni nie zdają sobie sprawy, że już nie grają w tą samą grę.

Kolejnym problemem związanym z “poglądem IDE” jest to, że javowe IDE mają wbudowany pewien “zapętlony” problem. Zapętlenie wynika z natury języków programowania: kształty klocków w grze wynikają ze statycznego systemu typów języka. Javove klocki nie pozwalają na eliminowanie kodu, gdyż statyczny system typów Javy nie ma żadnych środków kompresji: żadnych makr, lambd, deklaratywnych struktur danych, szablonów, nic co pozwoliłoby na pozbycie się wzorców kopiuj-wklej, o których programiści Javy myślą jak o “źle koniecznym”, które jednak łatwo się pozbyć w dynamicznych językach programowania.

By uzupełnić pętlę, dynamiczność języków znacząco utrudnia IDE wykonywanie ich magicznych sztuczek związanych z zarządzaniem statycznym kodem. IDE nie dają sobie za dobrze rady z dynamicznymi cechami języków, więc IDE są odpowiedzialne za agitację na rzecz języków, które wymagają... IDE. Auć.

Programiści Javy rozumieją to w pewnym stopniu; dla przykładu, popularna refleksja w Javie, która pozwala Ci konstruować nazwy metod w locie i wywoływanie tychże metod po nazwie, pokonuje możliwość przeprowadzenia tak prostego refaktoringu jak Przemianowanie Metody. Dzięki udanemu podzieleniu swoich wierzeń, goście od Javy wskazuja na dynamiczne języki programowania i wyją, że (niektóre) automatyczne refaktoringi są niemożliwe. One są jednak w istocie możliwe w takim samym stopniu, w jakim są możliwe w Javie - to znaczy, częściowym. Refaktoringi nie “udadzą się” do tego stopnia, w jakim korzystasz z dynamicznych cech języka - czy piszesz w Javie, czy innym języku. Refaktoringi nigdy nie są w 100% skuteczne; w szczególności, jeśli baza kodu jest publikowana razem z publicznymi API: to jest dokładnie powód, dla którego Java ma system deprecjacji. Nie możesz przemianować metody na każdej maszynie na ziemi. Nie mniej jednak goście od Javy wciąż deklamują (prawdopodobnie niepoprawnie) że automatyczne refaktoringi działają na “całej” bazie kodu.

Założę się, że teraz jesteś tak samo zadowolony jak ja, że nie rozmawiamy z programistami Javy w tej chwili! Teraz, gdy przedstawiłem jeden z (wielu) powodów, dla których są kompletnie nieracjonalni, powinno być całkiem jasne, że ich odpowiedź nie będzie raczej racjonalna.

Rozsądna ilość kodu

Rozsądną odpowiedzią byłoby uczynić wielki krok w tył, wstrzymać cały rozwój, i zadać trudne pytanie: “z czego powinienem korzystać zamiast Javy?”.

Zrobiłem tak jakieś 4 lata temu. To wtedy wstrzymałem pracę nad swoją grą, i przełączyłem w tryb “serwisowania”. Chciałem ją przepisać do, powiedzmy, 100 000 do 150 000 linii, czy gdzieś w okolicach, z dokładnie taką samą funkcjonalnością.

Zajęło mi 6 miesięcy by zrozumieć, że tego nie da się zrobić z Javą, nawet z rzeczami, które dodano do Javy 5, i nawet z rzeczami, które planują dla Javy 7 (nawet jeśli dodadzą te super rzeczy jak np. porządne domknięcia, przeciw którym społeczność Javy broni się rękami i nogami).

Tego nie da się zrobić za pomocą Javy. Mam jednak spory wkład w wirtualną maszynę Javy - z dokładnie tego samego powodu, dla którego Microsoft inwestuje w .NET. Maszyny wirtualne mają dla mnie w tej chwili sens. To znaczy, miały dla mnie sens na jakimś powierzchownym poziomie gdy przeczytałem broszury reklamowe, ale teraz gdy napisałem kilka interpreterów i pogrzebałem w kompilatorach do kodu natywnego, mają dla mnie dużo więcej sensu. Dlaczego, to już kwestia innej mowy, niestety.

Mając więc zagwarantowane, że maszyny wirtualne są “dobre” i przyjmując do wiadomości, że moja gra jest dość mocno związana z JVM - nie tylko z powodu rozległego wykorzystania bibliotek i narzędzi do monitorowania, ale także z powodu nieco bardziej subtelnych decyzji architekturalnych jak np. wielowątkowość czy modele pamięci - racjonalną odpowiedzią na wzdęcie kodu byłoby wybranie jakiegoś innego języka na tą maszynę.

Przyjemną rzeczą związaną z językami na wirtualną maszynę Javy jest to, że programiści Javy mogą się ich całkiem szybko nauczyć, jako że mają wszystkie biblioteki, narzędzia monitorujące i decyzje architekturalne za darmo. Minusem jest to, że programiści Javy są programistami X, i - jak powiedziałem - nie chcesz mieć programistów X w swoim zespole.

Ale jako że nie jesteś jednym z tych ludzi, którzy zdecydowali się nosić te poliestrowe dzwony do końca swoich dni, nawet jeśli miałbyś żyć pięćset lat, jesteś otwarty na sugestie dotyczące języka. Dobrze!

Trzy lata temu rozpocząłem dochodzenie, który z języków na maszynę wirtualną Javy byłby najlepszym kompresorem kodu zastępującym Javę. Zajęło to dłużej niż myślałem, a odpowiedź była dużo mniej satysfakcjonująca niż przypuszczałem. Nawet teraz, trzy lata później, odpowiedź jest wciąż odległa o rok lub dwa od bycia naprawdę pociągającą.

Jestem już cierpliwy, więc gdy już opadnie kurz, wiem, że zostanie mi około dwóch lat, podczas których fanatyczni programiści Javy napiszą następną wielomilionową katastrofę. Właśnie w czasie, gdy zestawią obok siebie następne slajdy z Problemami i Wymaganiami, będę miał dla nich odpowiedź.

W międzyczasie mam nadzieję, że znajdę czas na przepisanie tej gry w tym języku, zmniejszając ilośc kodu z 500 000 linii do 150 000 linii, z dokładnie taką samą funkcjonalnością (plus przynajmniej 50k linii na testy jednostkowe).

Następna Java

Więc jaki język będzie nastepną Javą?

Cóż, jeśli naprawdę zależy Ci czystej na kompresji kodu, to z pewnością wybierzesz dialekt Lispu: Common Lisp czy Scheme. I istnieją dla nich naprawdę dobre implementacje na maszynę Javy. Korzystałem z nich. Niestety, język JVM musi być jakimś zastępnikiem Javy (inaczej portowanie stanie się poważnym problemem logistycznym), a żaden z twórców Lispa/Scheme’a nie wygląda na takiego, który ma to wysoko na swojej liście priorytetów.

Dodatkowo, wszyscy zaczną na Ciebie pluć. Ludzie, którzy zwyczajowo nie plują, będą wyrzucali z siebie plwocinę na wysokość trzydziestu stóp, jak wielbłądy w zoo, po to żeby móc Cię nią pokryć jak tylko zaproponujesz możliwość użycia Lispu czy Scheme’a w Twojej firmie.

Nie będzie to więc Lisp czy Scheme. Będziemy musieli poświęcić odrobinę kompresji na coś nieco bardziej zgodnego syntaktycznie z głównym nurtem.

Teoretycznie mógłby być to Perl 6, zakładając że goście od Parrot w końcu go skończą. Oni są jednak bardziej cierpliwi niż ja, jeśli wiesz o co mi chodzi. Perl 6 naprawdę jest całkiem fajnie zaprojektowanym językiem - żeby było jasne, byłem w nim zadurzony w 2001. Nasz romans umarł jakieś 5 lat temu. No i Perl 6 pewnie nigdy nie uruchomi się na JVM. Zbyt mocno zależy od potężnych cech Parrota, których JVM nigdy nie będzie wspierał (zaryzykowałbym stwierdzenie, że Parrot też nie będzie ich wspierał, ale to byłoby okrutne).

Najprawdopodobniej Nową Javą zostanie język dość popularny z dobrym portem na JVM. To będzie język z naprawdę zaangażowanym zespołem i świetnym działem ds. marketingu.

To zawęża zakres poszukiwań z ponad 200 języków do jakichś trzech czy czterech: JRuby, Groovy, Rhino (Javascript), i może Jython, jeśli przebudzi się ze swojej śpiączki.

Każdy z tych języków (tak jak i Perl 6) dostarcza mechanizmów, które pozwoliłyby na kompresję dobrze napisanej, 500 000-linijkowej bazy kodu w Javie rzędu 50-75%. Gdzie dokładnie leży ta granica jeszcze nie wiemy, ale spróbuję wybadać to samodzielnie.

Osobiście wypróbowałem Groovy’ego, ale uznałem go za brzydki języki z kilkoma przyzwoitymi pomysłami. Chciałby być Ruby’m, ale brakuje mu jego elegancji (lub elegancji Pythona). Jest już dostępny od dłuższego czasu, ale nie wygląda na to, zeby nabierał jakiegokolwiek pędu, więc wyrzuciłem go ze swojego warsztatu (i to na dobre - nie spojrzę już na niego więcej. Błędy implementacyjne Groovy’ego naprawdę dały mi się we znaki).

Bardzo lubię Ruby i Pythona, ale żaden z nich nie był dostepny na JVM gdy rozpoczynałem swoje badania trzy lata temu. JRuby miał jeszcze sporo do dopracowania w międzyczasie. Gdyby ludzie, z którymi pracuję nie byli tak betonowo przeciwko Ruby’emu, zapewne bym go wypróbował, i mam cholerną nadzieję, że jego implementacja będzie w końcu “dostatecznie szybka” w porównaniu do Javy.

Stało się jakoś tak, że zostałem przy Rhino. Będę pracował z zespołem od Rhino by był w końcu zgodny ze specyfikacją EcmaScript w wersji 4. Wierzę, że ES4 dołączy JavaScript do grona języków równych Ruby czy Pythonowi w kontekście (a) mocy wyrazu i (b) możliwości strukturyzowania i zarządzania dużymi bazami danych. Wierzę też, że JavaScript (szczególnie na sterydach z ES4) będzie łatwiejszy do sprzedania od Ruby czy Pythona tym, którzy lubią nawiasy wąsate - czyli komukolwiek korzystającemu obecnie z C++, Javy, C#, JavaScriptu czy Perla. To naprawdę spooooooro miłośników wąsów. Jestem zwyczajnie praktyczny.

Nie spodziewam się, żeby moja dzisiejsza tyrada przekonała kogokolwiek do opinii mniejszości na temat ilości kodu. Wiem, ze niektórzy goście (Bill Gates dla przykładu, jak i Dave Thomas, Martin Fowler czy James Duncan Davidson) niezależnie doszli do tego samego wniosku: nazywając rzecz po imieniu: wzdęcie to najgorsza rzecz, jaka może się przydarzyć kodowi. Ale oni wszyscy przeszli przez te wszystkie bolesne rzeczy, które im się przydarzyły.

Nie mogę sobie życzyć, żeby coś bolesnego przydarzyło się deweloperom Javy, jako że to już im się przydarzyło: nauczyli się udawać, że to ich nie boli.

Tobie jednak, gorliwemu uczniowi szkoły średniej czu studentowi, który chce zostać wspaniałym programistą pewnego dnia, dałem - mam nadzieję - kolejny wymiar do obserwowania podczas pielenia swoich kodowych ogródków przez następne kilka lat.

Kiedy będziesz gotowy na zmianę, cóż - Mozilla Rhino będzie gotowa. Już dziś działa świetnie i będzie zdecydowanie wybitna za rok. I szczerze liczę na to, że JRuby, Jython i spółka będą używalnymi alternatywami dla Javy. Możesz je wypróbować nawet dziś i zobaczyć, jak pójdzie.

Twój kod podziękuje Ci za to.

Data publikacji oryginału: grudzień 17, 2007

Daj się poznać!

Ponieważ podoba nam się inicjatywa ogłoszona kilka dni temu przez Macieja Aniserowicza, postanowiliśmy wspomnieć o niej na devBlogach:

Nudzisz się w wakacje? Nie masz co robić po pracy? Od dawna chcesz poznać nową technologię, ale brakuje Ci motywacji? Masz w głowie szatański plan napisania świetnego projektu, ale boisz się, że nikt o nim nie usłyszy? A może zastanawiasz się nad założeniem bloga, ale wstrzymuje Cię obawa przed brakiem tematów do poruszenia?

Mogę powiedzieć jedno: DO ROBOTY! :)

W celu rozruszania programistycznej braci w urlopowym czasie organizuję konkurs na... zdobywanie doświadczenia i dzielenie się nim. Potrzebne są trzy rzeczy: zaangażowanie, projekt open source oraz blog techniczny.

W imieniu Macieja zapraszamy na stronę konkursu Daj się poznać!.

Gorąco zachęcamy do wzięcia udziału w konkursie!
Zespół devMedia.pl

Przed refaktoryzacją

Opublikowaliśmy kolejne tłumaczenie w serwisie 97rzeczy:

  • Przed refaktoryzacją (autor: Rajith Attapattu)
    "W pewnym momencie, każdy programista będzie odczuwał potrzebę refaktoryzacji istniejącego kodu. Ale przed rozpoczęciem, proszę, pomyśl o następujących rzeczach, ponieważ mogą one zaoszczędzić Ci sporo czasu (i bólu)."

Zachęcamy do lektury,
Zespół devMedia.pl

Myślisz, że zarabiasz tyle, na ile zasługujesz?

Mapa zarobków programistów w Polsce

Pewnie jak wielu z Was, kolegów programistów, zastanawiamy się czasem, czy w naszych aktualnych miejscach pracy jesteśmy uczciwie wynagradzani za naszą wiedzę i zaangażowanie. Negocjowanie wynagrodzenia to trudna i delikatna kwestia, a niestety w Polsce jeszcze rzadko spotykamy się z ofertami pracy, w których pracodawca podawałby widełki płacowe, podczas gdy w wielu innych krajach zwyczaj ten przyjął się już dawno.

Rozmawianie z kolegami z pracy na temat zarobków uchodzi za niezbyt profesjonalne i przede wszystkim może prowadzić do niepotrzebnych nieporozumień i pogorszenia ogólnej atmosfery w zespole, a to, jak wiemy, z pewnością nie wpłynęłoby pozytywnie na efektywność i przyjemność z wykonywania swoich obowiązków.

W związku z powyższym, jak również ze względu na to, że tworzymy już całkiem sporą społeczność programistów w Polsce, postanowiliśmy przygotować prostą ankietę na temat naszych zarobków. Wypełniając ją, będziecie mogli przekonać się, jak przedstawiają się zarobki Waszych kolegów po fachu w różnych częściach kraju wraz z podziałem na stosowany w pracy język programowania.

Wyniki ankiety

Pozdrawiamy!
Zespół devMedia.pl

Rzeczy, których nigdy nie powinieneś robić, część I

Oryginalny post: Things You Should Never Do, Part I

Autor: Joel Spolsky

Netscape 6.0 wreszcie dotarł do swojej pierwszej publicznej wersji beta. Wersja 5.0 nigdy nie istniała. Ostatnie istotne wydanie, 4.0, zostało opublikowanie prawie 3 lata temu. Trzy lata to bardzo długi okres w świecie Internetu. Przez cały ten czas Netscape bezsilnie patrzył na to, jak jego udział w rynku spada na łeb, na szyję.

To odrobinę lizusowskie z mojej strony, by krytykować ich za tak długą zwłokę w publikacjach. Nie zrobili tego celowo, nieprawdaż?

W rzeczy samej - zrobili. Popełnili ten największy błąd strategiczny, jaki może popełnić firma:

Zdecydowali się przepisać program od zera.

Netscape nie było pierwszą firmą, która popełniła taki błąd. Borland zrobił to samo, gdy kupił Arago i próbował go przerobić na dBase dla Windows - projekt skazany na zagładę, który trwał tak długo, że Microsoft Access zdążył zjeść ich kawałek tortu. Później zrobili dokładnie to samo, przepisując Quattro Pro od zera i zaskakując swoich klientów tym, jak uboga była ich aplikacja po publikacji. Microsoft także otarł się o ten sam błąd, próbując przepisać Word dla Windows w projekcie skazanym na porażkę - Pyramid. Pyramid został przerwany i zamieciony pod dywan. Szczęśliwie dla Microsoftu, ich programiści nie przestali rozwijać starej wersji, więc mieli co wysłać w świat - obracając wydanie jedynie w finansową, a nie strategiczną, katastrofę.

Jesteśmy programistami. Programiści są w głębi serca architektami, a pierwsze co chcą zrobić, gdy dostaną się na plac budowy, to zrównać wszystko z ziemią i zbudować coś wspaniałego i wzniosłego. Nie czerpiemy radości z przyrostowej odbudowy: majsterkowania, poprawiania, sadzenia klombów.

Jest pewien subtelny powód, dla którego programiści zawsze wolą wyrzucić kod do śmieci i spróbować od początku. Powód ten jest mianowicie taki, że programiści myślą, że stary kod to bajzel. I tu ciekawa obserwacja: prawdopodobnie są w błędzie. Powód, dla którego myślą, że stary kod jest stertą śmieci, wynika z jednego fundamentalnego prawa związanego z programowaniem:

Trudniej jest czytać kod niż go pisać.

To dlatego ponowne wykorzystywanie kodu jest takie trudne. To dlatego każdy członek Twojego zespołu ma inną funkcję do dzielenia łańcucha znaków na tablicę łańcuchów. Piszą własną funkcję, ponieważ to jest łatwiejsze i ciekawsze niż główkowanie nad tym, jak działa stara funkcja.

W następstwie tego, gdy zapytasz niemalże dowolnego programistę o kod, nad którym pracuje, ten odpowie Ci, że “To jeden wielki bajzel”. “Niczego innego nie pragnę, jak tylko wyrzucić to wszystko i zacząć od początku.”

Dlaczego ten kod to taki bałagan?

“Wiesz,” mówią, “spójrz na tę funkcję. Ma dwa ekrany długości! Żadna z tych rzeczy nie powinna tu być! Nie mam pojęcia, do czego służy połowa z wywołań tych funkcji z API.”

Zanim Borland wypuścił swój arkusz kalkulacyjny dla Windows, Philippe Kahn, barwny założycieł Borlanda, był wielokrotnie cytowany w prasie, przechwalając się, jak bardzo Quattro Pro będzie lepsze od Microsoft Excel - jako, że miało być przepisane od zera. Cały kod miał być nowiutki! Tak jakby kod źródłowy kiedykolwiek rdzewiał.

Pomysł, że nowy kod jest lepszy od starego jest oczywiście absurdalny. Stary kod był wykorzystywany. Był przetestowany. Znaleziono mnóstwo błędów, które naprawiono. Wszystko jest z nim w porządku. Nowe błędy nie pojawiają się przez to, że ten kod mieszka sobie na Twoim dysku twardym. Wprost przeciwnie, mój drogi! Czy oprogramowanie ma być starym Dodge Dartem, który rdzewieje w Twoim garażu tylko dlatego, że w nim stoi? Czy oprogramowanie to pluszowy miś, który jest jakby brzydszy, jeśli nie jest wykonany całkowicie z nowych materiałów?

Wróćmy do dwustronicowej funkcji. Tak, wiem, to jest zwyczajna funkcja do wyświetlania okna, ale urosła odrobinę i nikt nie wie dlaczego. Powiem Ci dlaczego: to wszystko to poprawki. Jedna z nich naprawia błąd, na który natknęła się Nancy, gdy próbowała zainstalować aplikację na komputerze, który nie miał Internet Explorera. Inna naprawia błąd, pojawiający się, gdy brakuje nam pamięci. Jeszcze inny naprawia błąd, który pojawia się, gdy użytkownik uruchomi program z dyskietki i wyjmie ją w trakcie pracy. To odwołanie LoadLibrary jest paskudne, ale dzięki niemu kod działa na starszych wersjach Windows 95.

Każdy z tych błędów potrzebował tygodni działania programu w prawdziwym świecie, zanim został znaleziony. Programista mógł spędzić kilka dni, próbując odtworzyć ten błąd i go naprawić. Jeśli jest tam mnóstwo błędów a naprawienie każdego z nich kosztowało jedynie linijkę kodu - lub nawet kilka znaków - to w te kilka znaków włożono ogrom czasu i pracy.

Gdy wyrzucasz kod i zaczynasz od zera, wyrzucasz całą tę wiedzę. I zebrane poprawki. Lata programistycznej pracy.

Wyrzucasz pozycję lidera na rynku. Dajesz swoim konkurentom prezent w postaci dwóch lub trzech lat, i wierz mi, to bardzo długo w tym świecie.

Stawiasz się w wyjątkowo niebezpiecznej sytuacji, w której będziesz sprzedawał starą wersję programu przez kilka lat, kompletnie niezdolny do wprowadzania strategicznych zmian i reagowania na nowe żądania rynku - dlatego, że nie masz kodu, który mógłby być wydany. Równie dobrze mógłbyś zamknąć biznes na ten czas.

Marnujesz niebiańską sumę pieniędzy na pisanie kodu, który już istnieje.

Czy istnieje alternatywa? Konsensusem wydaje się być to, że kod starego Netscape’a był naprawdę kiepski. Cóż, może i był kiepski, ale wiesz co? Działał wcale nieźle na ogromnie dużej ilości prawdziwych komputerów.

Kiedy programiści mówią, że ich kod to koszmar (jak zwykle), to są ku temu trzy powody:

Po pierwsze, problemy związane z architekturą. Kod nie jest produkowany należycie. Kod związany z siecią pokazuje okna dialogowe znikąd; to powinno być zadaniem kodu związanego z interfejsem. Te problemy mogą zostać rozwiązane, jeden po drugim, za pomocą ostrożnego przemieszczenia kodu, refaktoryzacji, zmian w interfejsach. Mogą zostać dokonane przez jednego programistę, pracującego ostrożnie i wrzucającego swoje zmiany na raz, kiedy nikomu to nie przeszkodzi. Nawet dość poważnie zmiany w architekturze mogą zostać przeprowadzone bez pozbywania się kodu. W projekcie Juno spędziliśmy kilka miesięcy przebudowując jeden fragment: po prostu przemieszczając kod, czyszcząc go, tworząc klasy bazowe, które mają sens, wyznaczając jasne interfejsy między modułami. Zrobiliśmy to jednak ostrożnie, z istniejącą bazą, i nie wprowadziliśmy nowych błędów - nie wyrzucając kodu.

Drugim powodem, dla którego programiści myślą, że ich kod jest do bani, to jego niewydajność. Chodziła plotka, że kod związany z odrysowywaniem w Netscape jest wolny. To jednak dotyczy tylko małej części projektu, którą możesz zoptymalizować czy nawet przepisać. Nie musisz jednak przepisywać całego projektu. Gdy optymalizujesz wydajność, 1% pracy przekłada się na 99% efektu.

Trzecia rzecz: kod może być paskudnie brzydki. Jeden projekt, nad którym pracowałem, miał nawet typ danych nazwany “PieprzonyString”. Inny projekt zaczynał z konwencją, w której nazwy pól zaczynały się od podkreślenia. Później zmieniono to na bardziej standardowe “m_”. Tym samym połowa funkcji zaczynała się od “_” a druga od “m_”, co wyglądało paskudnie. Szczerze, jest to jedna z tych rzeczy, które załatwiasz w 5 minut jednym makrem w Emacsie, nie zaczynając niczego do początku.

Ważnym jest, żeby pamiętać, że gdy zaczynasz pisać coś od początku, nie ma absolutnie żadnego powodu, dla którego można myśleć, że odwalisz lepszą robotę niż za pierwszym razem. Przede wszystkim, najprawdopodobniej nie masz takiego samego zespołu jak ten, który pracował nad pierwszą wersją - a tym samym nie masz “większego doświadczenia”. Popełnisz większość tych samych błędów ponownie i wprowadzisz nowe, które nie istniały w oryginalnej wersji.

Stara mantra “pierwsza wersja jest do wyrzucenia” jest niebezpieczna, gdy zastosuje się ją do produktów komercyjnych wielkiej skali. Jeśli piszesz eksperymentalny kod, możesz chcieć usunąć funkcję, którą napisałeś tydzień temu, gdy wpadniesz na lepszy algorytm. To jest w porządku. Możesz chcieć zrefaktoryzować klasę, by dało się z niej łatwiej korzystać. To też jest w porządku. Wyrzucanie całego programu to jednak głupota i jeśli tylko Netscape miałby jakiś dojrzały nadzór i doświadczenie w branży, to mógły uniknąć tak bolesnego strzału w stopę.

Data publikacji oryginału: kwiecień 6, 2000

Karol Stosiek - nowy tłumacz na devBlogach

Karol Stosiek

Chcielibyśmy oficjalnie powitać nowego członka naszego zespołu. Od niedawna pracuje nad pierwszym tłumaczeniem, które powinno pojawić się już niebawem. On sam pisze o sobie:

Karol Stosiek, student informatyki w Instytucie Informatyki Uniwersytu Wrocławskiego. Zapalony programista i wzięty menedżer projektów. Swe programistyczno-menedżerskie pasje rozwija udzielając się na swojej uczelni (poprzez prowadzenie projektów programistycznych oraz aktywne uczestnictwo w pracach tutejszego koła naukowego, któremu do niedawna przewodniczył) oraz w komercyjnych firmach. W chwili obecnej odbywa swój drugi staż centrali Google w Zurychu.

Zespół devMedia.pl

Nauka czytania dla użytkowników

Oryginalny post: Teaching Users to Read

Autor: Jeff Atwood

Pisałem już wcześniej o nieodpowiedzialnym używaniu okien dialogowych, ale coś co przeczytałem ostatnio, podkreśliło interesujący aspekt tego tematu, którego wcześniej nie rozważyłem. Najpierw, Joel Spolsky:

Może to zabrzmieć surowo, ale zdasz sobie z tego sprawę, kiedy zrobisz testy z użytkownikami, że znajdzie się trochę takich, którzy nie czytają słów, które umieściłeś na ekranie. Jeśli pokażesz okno z jakimkolwiek błędem, po prostu go nie przeczytają. Może to być żenujące dla Ciebie jako programisty, ponieważ wyobrażasz sobie siebie jako tego, który prowadzi dialog z użytkownikiem. Hej, użytkowniku! Nie możesz otworzyć tego pliku, ponieważ nie obsługujemy tego formatu! Wciąż, doświadczenie pokazuje, że im więcej wyrazów umieścisz w oknie dialogowym, tym mniej ludzi w rzeczywistości to przeczyta.

A Mike wykopał fascynujący komentarz Erica Lipperta na ten sam temat:

To nie jest tak, że użytkownicy są kretynami, albo że "zapominają" myśleć. To jest tak, że użytkownicy są wytrenowani, aby nie myśleć. Użytkownicy bardzo szybko uczą się z doświadczenia, że:

  • Okna dialogowe są modalne. Ale użytkownicy nie myślą o nich jak o "modalnych", ale o takich, które "przeszkadzają mi w wykonaniu mojej pracy dopóki się go nie pozbędę."
  • Okna dialogowe niemal zawsze znikają, kiedy kliknie się przycisk po lewej bądź po prawej.
  • W oknach dialogowych zazwyczaj jest napisane "Jeśli chcesz techn. techn., to musisz techn. techn. za pomocą techn. techn.. Techn techn.? Tak / Nie"
  • Jeśli wciśniesz jeden z przycisków, coś się stanie. Jeśli wciśniesz ten inny, nic się nie stanie. Bardzo niewielu użytkowników nie chce, aby się coś stało -- w większości przypadków, cokolwiek się nie stanie, to jest to, czego chciał użytkownik. Tylko w nielicznych przypadkach zdarza się coś złego.

Pokrótce, z perspektywy użytkownika okna dialogowe to przeszkoda w produktywności, która nie dostarcza żadnych informacji. To tak jak uderzać małpę albo dawać jej jedzenie, kiedy wciska odpowiednie przyciski -- ssaki naczelne bardzo szybko się uczą, co daje w efekcie dobre skutki, a co złe.

Cóż, nie mogłem przestać myśleć o klasycznym komiksie Gary'ego Larsona:

Co słyszą psy

Moją intencją nie jest nabijanie się z użytkowników, ale pokazanie tego, że istnieje sporo, o wiele bardziej efektywnych sposobów komunikacji ze swoim psem. W gruncie rzeczy, to za każdym razem, kiedy pytasz użytkownika o wybór, na którym mu nie zależy, to go zawiodłeś. Dobrze zaprojektowane oprogramowanie samo zajmuje się rzeczami typu "techn. techn. za pomocą techn.", a użytkownikowi pozostawia ze zmartwieniami dotyczącymi pracy, którą wykonują. Okna dialogowe niemal zawsze są szkodliwe. Celem powinno być tworzenie całych aplikacji bez okien dialogowych.

Dobrze zaprojektowane oprogramowanie unika pytania użytkownika poprzez..

  • Przewidywanie potrzeb użytkownika (kreatory, szablony, autouzupełnianie, IUI)
  • Zapamiętywanie preferencji i używanie ich, aby lepiej przewidzieć przyszłe potrzeby
  • Ciche i automatyczne zabezpieczanie użytkownika przed konsekwencjami negatywnych akcji (wersjonowanie, cofanie)

To zadziwiające, jak niewiele aplikacji w ogóle próbuje sprostać tym wymaganiom, nawet jeśli chodzi o proste, popularne rzeczy. Dla przykładu, dlaczego okno zapisywania pliku zawsze domyślnie wskazuje na Moje Dokumenty, nawet jeśli ostatnio, kiedy używałem aplikacji, to zapisywałem na Pulpicie?

Data publikacji oryginału: 25 października, 2004

Related Posts with Thumbnails