馃悤 O psie, kt贸ry je藕dzi艂 kolej膮. 馃殏 Jak zap艂aci膰 za koszyk w serwisie PKP? Odrobaczanie systemu.

Powy偶ej zosta艂o u偶yte zdj臋cie psa ze strony Pies.pl

O psie, kt贸ry je藕dzi艂 kolej膮, albo bardziej o naszym polskim PKPowym isPies czy 鈥渒艂opotliwych zni偶kach鈥 s艂ysza艂 w bran偶y IT ju偶 prawie ka偶dy. Chocia偶 w mi臋dzyczasie dosz艂a 鈥渟zybka szpachla ifem鈥 w postaci fragmentu if(ZakupBiletuUtil().isCOVID()), to dzisiaj tak偶e nie o tym. Dzisiaj historia z 偶ycia na kodach wzi臋ta. Co stanie si臋, kiedy trzech programist贸w podejmie si臋 karko艂omnego wyzwania zap艂acenia za jedyny bilet w koszyku? Czy zwyci臋偶膮 鈥淐annot read properties of null鈥? W jaki spos贸b wyrusz膮 w swoj膮 podr贸偶? Czy przeprowadz膮 odrobaczanie? A mo偶e si臋 poddadz膮? Przeczytaj, jak 3 programist贸w bilet na PKP kupowa艂o i pokonali siej膮cego czerwone logi buga, kt贸ry mieszka艂 w przypadku brzegowym.

  • Ten wpis pomo偶e Ci rozwi膮za膰 problem w serwisie PKP, je艣li masz w koszyku bilet/y na jedno po艂膮czenie kolejowe i nie mo偶esz dokona膰 p艂atno艣ci.
  • Jako programista przeczytasz troch臋 o Debuggerze w Google Chrome i Ubiquitous Language z Domain-Driven Design. Dowiesz si臋, kiedy Polskie wyrazy w kodzie maj膮 uzasadnienie!
  • Zab艂膮dzi艂e艣/a艣 w odm臋ty internetu? W najgorszym przypadku jedynie umil臋 Ci troch臋 czas, je艣li nie kupujesz 偶adnego biletu i znasz si臋 na frontendzie oraz DDD.

Enjoy!

Z 偶ycia na kodach

Bywaj膮 tacy podr贸偶ni, kt贸rzy mog膮 鈥渘ie dba膰 o baga偶, nie dba膰 o bilet鈥 tak jak bohater ksi膮偶ki 鈥淥 psie, kt贸ry je藕dzi艂 kolej膮鈥. Jednak w naszym przypadku taka zasada nie mia艂a zastosowania. Zaopatrzenie si臋 w bilet powinno by膰 jedn膮 z najprostszych czynno艣ci zwi膮zanych z podr贸偶膮, ale nie tym razem!

I mo偶e nic by si臋 nie uda艂o, gdyby nie Ci w艣cibscy programi艣ci. A w艂a艣ciwie ja i dw贸ch koleg贸w frontendowc贸w 鈥 pozdrawiam Marcina i Konrada :) Historia niestety jest niezmy艣lona i du偶o w niej prawdy.

Weszli艣my na stron臋 PKP i wykonali艣my rutynowe kroki zakupu bilet贸w.

  1. Wprowadzili艣my kryteria wyszukiwania 鈥 stacj臋 pocz膮tkow膮 i docelow膮 oraz dat臋 wyjazdu.
  2. Wybrali艣my jedno z proponowanych po艂膮cze艅 po艂膮czenie.
  3. Okre艣lili艣my ile bilet贸w, jakiego typu chcemy kupi膰.
  4. Nie zap艂acili艣my za wybrane bilety, ale wybrali艣my opcj臋 鈥淒odaj do koszyka鈥.
Zakup biletów w serwisie Intercity PKP. Kroki dodania do koszyka.

Zakup biletów w serwisie Intercity PKP. Kroki dodania do koszyka.
(Kliknij, aby powiększyć)

Plan by艂 taki, aby wyszuka膰 te偶 bilety na kolejne po艂膮czenia. Jednak po chwili, zdali艣my sobie spraw臋, 偶e nie wiemy jeszcze, kiedy chcemy wraca膰. Dlatego porzucili艣my na razie ten pomys艂 i postanowili艣my od razu zap艂aci膰 za bilety w koszyku.

Bug zamieszka艂y w przypadku brzegowym

Bilety w koszyku figurowa艂y jako jedna pozycja, poniewa偶 by艂y wybrane dla tego samego po艂膮czenia kolejowego. Jak si臋 okaza艂o, by艂o to bardzo zgubn膮 decyzj膮 i tu le偶y isPies pogrzebany. Niestety, zaatakowa艂 nas znienacka bug siej膮cy czerwonymi logami w konsoli. Jakie by艂o nasze zdziwienie (no dobra, tak naprawd臋 to nic nas ju偶 na tej stronie nie zaskoczy), kiedy kilkukrotne klikanie w button 鈥淜upuj臋 i p艂ac臋鈥 nie powodowa艂o 偶adnej reakcji systemu (stan aktualny na 24.11.2021). S艂ysza艂em kiedy艣 histori臋, o tym, 偶e przez kilka dni od startu nowej firmy, nikt nie kupowa艂 produktu przez internet. Ca艂y sztab ludzi analizowa艂 sytuacj臋, marketingowcy zastanawiali si臋, co jest nie tak z reklam膮 itp. A okaza艂o si臋, 偶e przyczyna le偶y zupe艂nie gdzie indziej. Po prostu przycisk 鈥渒up teraz鈥 nie dzia艂a艂鈥

W naszym przypadku konsola w przegl膮darce zabarwi艂a si臋 na czerwono, a wszystko jakby krzycza艂o: 鈥渮awr贸膰cie z tej drogi鈥, niczym potwory w Scooby-Doo. Ale my postanowili艣my si臋 nie poddawa膰 i przeprowadzi膰 odrobaczanie (lu藕ne t艂umaczenie dla ang. debugging) tego kodu z b艂臋d贸w. Zbadali艣my pacjenta za pomoc膮 trybu Inspect w Google Chrome oraz debuggera kodu JavaScript. B艂膮d w konsoli wygl膮da艂 nast臋puj膮co:

Uncaught TypeError: Cannot read properties of null (reading 'value')
    at platnosc (platnosc.js?ver=883646852:63)
    at HTMLInputElement.<anonymous> (main.js?ver=883646852:1449)
    at HTMLDocument.dispatch (jquery-3.2.1.min.js:3)
    at HTMLDocument.q.handle (jquery-3.2.1.min.js:3)

Jako programi艣ci postanowili艣my pobawi膰 si臋 w Devtektyw贸w i osi膮gn膮膰 nasz cel. Nadszed艂 czas na tripple programming.

Szybkie otworzenie narz臋dzi deweloperskich i鈥 znale藕li艣my k艂opotliw膮 linijk臋 (nie zni偶k臋) w pliku platnosci.js. Problem nie le偶a艂 w isPies, tylko zupe艂nie gdzie indziej鈥

document.getElementById('faktura_nazwa_firmy').value = convertString(document.getElementById('faktura_nazwa_firmy').value);

Przeprowadzaj膮c 艂膮czenie kropek mi臋dzy b艂臋dem a linijk膮, wida膰, 偶e null zosta艂 zwr贸cony przez document.getElementById('faktura_nazwa_firmy'), bo to z tego obiektu chcemy odczyta膰 w艂a艣ciwo艣膰 value. Oznacza to, 偶e na stronie jest brak pola faktura_nazwa_firmy, kt贸rego warto艣膰 jest konieczna do wykonania kodu po wci艣ni臋ciu przycisku. Dlaczego kod wymaga czego艣 takiego, skoro ja wcale nie kupuj臋 biletu na firm臋? To ju偶 pozostanie tajemnic膮. Poradzili艣my sobie z tym bardzo 艂atwo. Najprostszym rozwi膮zaniem by艂o dodanie jednej linijki kodu w kodzie HTML strony. <input id="faktura_nazwa_firmy" value="ZycieNaKodachPL" /> Dzi臋ki temu pojawi艂o si臋 dodatkowe pole, kod wykona艂 si臋 bez rzucenia b艂臋dem i mogli艣my przej艣膰 do p艂atno艣ci. Dalej ju偶 wszystko dzia艂a艂o. Po zap艂aceniu bilety pojawi艂y si臋 w systemie i podczas kontroli przez konduktora, te偶 nie by艂o problemu :) Bug zosta艂 przechytrzony!

Przycisk nie reaguje. Po otwarciu konsoli widoczny błąd.

Przycisk nie reaguje. Po otwarciu konsoli widoczny błąd.
(Kliknij, aby powiększyć)

Co to za hackowanie!?

Je艣li dopiero zaczynasz przygod臋 z programowaniem, to z pewno艣ci膮 zastanawiasz si臋: 鈥淢o偶na tak sobie zmienia膰 kod strony鈥? Czy to nie jest jakie艣 hackowanie? Ot贸偶 nie鈥 Pami臋tam, jak w czasach gimbazy roi艂o si臋 w internecie od poradnik贸w, w stylu 鈥淛ak zarobi膰 99999 surowc贸w w grze Plemiona鈥. Autorzy tych filmik贸w po prostu zmieniali warto艣膰 w kodzie strony. Oczywi艣cie taka zmiana w praktyce nie dawa艂a zupe艂nie nic. Dlaczego? Tak samo, jak w przypadku dodania pola przy zakupie biletu. Twoja przegl膮darka dzia艂a w taki spos贸b, 偶e pobiera kod strony i wykonuje go u Ciebie na komputerze. Dlatego te偶, skoro kod, znajduje si臋 u Ciebie, to mo偶esz te偶 wprowadza膰 dowolne zmiany. Jednak s膮 one widoczne tylko dla Ciebie i nie maj膮 wp艂ywu na innych graczy, czy klient贸w PKP. Przy ponownym otworzeniu strony nawet na Twoim komputerze, pliki serwisu zostan膮 ponownie pobrane z serwera, a wcze艣niej wprowadzone zmiany znikn膮.

Zreprodukowanie buga

Znacie ten dowcip, jak wchodzi tester do baru i zamawia 1 piwo, potem 999999 piw, oczywi艣cie te偶 0 i -1 piwo? Sytuacja podobna jak na poni偶szym filmiku HRejter贸w.

Tak samo tutaj, prawdopodobnie trafili艣my na pewien przypadek brzegowy (ang. edge case). Postanowi艂em zreprodukowa膰 ten b艂膮d i wyst臋puje on jedynie, kiedy w koszyku mamy jedn膮 pozycj臋 (bilety na jedno po艂膮czenie kolejowe). Dlatego pewnie w wi臋kszo艣ci przypadk贸w funkcjonalno艣膰 dzia艂a poprawnie (kto u偶ywa koszyka dla jednego biletu!? ja :D). Ty te偶 mo偶esz go powt贸rzy膰, wykonuj膮c kroki, kt贸re opisa艂em. To bardzo istotne, je艣li pracujesz jako tester, 偶eby dok艂adnie opisywa膰 jakie Twoje dzia艂ania spowodowa艂y b艂膮d. Niezast膮piony mo偶e by膰 te偶 filmik obrazuj膮cy problem!

Dlaczego dla wi臋kszej ilo艣ci bilet贸w koszyk dzia艂a? Nie mam poj臋cia. Je艣li chcesz, podejmij wyzwanie, przeanalizuj b艂膮d i daj zna膰 w komentarzu! A mo偶e pracujesz w PKP i zaraz zabierasz si臋 za to zg艂oszenie? Pami臋tajcie na pocz膮tek o odpowiednich testach, aby pokry膰 ten przypadek!

Ucz si臋 na b艂臋dach

B艂臋dy s膮 po to, 偶eby si臋 na nich uczy膰! Najlepiej wiedz膮 o tym osoby odpowiadaj膮ce za nasze bezpiecze艅stwo podczas podr贸偶y samolotem. Z katastrof lotniczych zawsze wyci膮ga si臋 wnioski i wprowadza nowe procedury, aby co艣 podobnego si臋 nie powt贸rzy艂o. Szcz臋艣cie, 偶e to tylko sprzeda偶 bilet贸w i nie spowoduje to 偶adnego zderzenia poci膮g贸w (co innego, kiedy od softu zale偶y ludzkie 偶ycie) :)

Jednak, aby nasze systemy nie mia艂y takich defekt贸w, konieczne jest ich odpowiednie przetestowanie. Chcesz wiedzie膰 jak pisa膰 aplikacje, aby by艂y testowalne? Zastanawiasz si臋, w jaki spos贸b pisa膰 utrzymywalne testy? Zdradz臋 Ci teraz, od czego zacz膮膰 nauk臋. Zr贸b w tym kierunku pierwszy krok i ju偶 dzisiaj zaopatrz si臋 w ksi膮偶k臋 Unit Testing Principles, Practices, and Patterns: Effective Testing Styles, Patterns, and Reliable Automation for Unit Testing, Mocking, and Integration Testing with Examples in C#. Tytu艂 niebywale d艂ugi jak nazwy klas w Javie, ale temat jest jednak obszerny :D

Wsta艅 z kanapy! A raczej siadaj do komputera鈥 Masz troch臋 czasu, zanim kurier zapuka do Twoich drzwi. Ju偶 teraz warto zajrze膰 na blog autora ksi膮偶ki Enterprise Craftsmanship - Vladimir Khorikov. Znajdziesz tam wiele o testach, ale te偶 o Domain-Driven Design.

Nie wiem, czy wybrano psa, ale wiem, 偶e Ponglish czasem nawet na propsie

ZycieNaKodach.pl | Lampo, czyli prawdziwy pies, który jeździł koleją. Żył we Włoszech w latach 50. XX wieku.

Lampo, czyli prawdziwy "Pies, który jeździł koleją" żył we Włoszech w latach 50. XX wieku.

Skoro jeste艣my ju偶 w temacie PKP, to warto przypomnie膰, 偶e swego czasu kod na stronie przewo藕nika by艂 po艣miewiskiem internetu i spad艂a na niego fala hejtu. Wa偶ne jest, aby krytykowa膰 sam kod, a nie programist贸w, kt贸rzy go napisali. Na pewno ka偶demu zdarzy艂o si臋 napisa膰 w karierze podobnego potworka :) Ale co z tymi Polskimi nazwami w kodzie? Czy kto艣 w ko艅cu wie czyWybranoPsa i dlaczego? Czy mieszanie Polskiego z Angielskim, tzw. 鈥淧onglish鈥 jest tutaj uzasadniony? Tego nie wiem, ale odejd藕my na chwile na bezpieczn膮 odleg艂o艣膰 od tor贸w i zadajmy sobie pytanie kiedy warto rozpatrzy膰 taki spos贸b zapisu.

Jak wiemy w IT zawsze 鈥渢o zale偶y鈥. Super przyk艂ad podaje 艁ukasz Szyd艂o w rozmowie z Mariuszem Gilem w podca艣cie Better Software Design O r贸偶nych odmianach Ubiquitous Language. Szczeg贸lne bran偶owe s艂ownictwo mo偶e by膰 ci臋偶ko przet艂umaczalne, a jedn膮 z najwa偶niejszych zasad Domain-Driven Design jest utrzymanie j臋zyka biznesowego w kodzie. To podstawa do tego, aby nasz kod m贸g艂 ewoluowa膰 wraz z biznesem. Je艣li jeste艣my w stanie przet艂umaczy膰 s艂ownictwo domenowego 1 do 1, a biznes funkcjonuje w innym j臋zyku ni偶 angielski, to warto utrzymywa膰 s艂owniczek, 偶eby艣my nie mieli kilku wyraz贸w na to samo. By艂em ju偶 w projekcie, gdzie np. na paliwo raz by艂o s艂owo Gas, a raz Fuel. Polski j臋zyk ma sens, kiedy nie potrafimy przet艂umaczy膰 dok艂adnie, albo w naszym j臋zyku mamy wi臋cej okre艣le艅 na to samo ni偶 angielski. 艁ukasz daje przyk艂ad Glebogryzarki w bran偶y rolniczej, a tak偶e instytucji finansowych. Po wi臋cej odsy艂am Ci臋 do podcastu i na m贸j mailing. Jaki mailing? Wszystko masz poni偶ej :)

鉁夛笍 isCovid - jak to zrobi膰 lepiej?

Kod PKP, chocia偶 jest ju偶 legacy, to nie mo偶na o nim zapomnie膰. Na przepisanie zapewne nie ma czasu, a dochodz膮 nowe wymagania. Ostatnio jak m贸g艂 zauwa偶y膰 uwa偶ny obserwator, dosz艂a 鈥渟zybka szpachla ifem鈥 w postaci fragmentu if(ZakupBiletuUtil().isCOVID()). Tak膮 implementacj臋 mo偶naby nazwa膰 anty-wzorcem. Dostrzegam tutaj pewn膮 przypad艂o艣膰, kt贸r膮 mo偶na nazwa膰 鈥渟chizofreni臋 kontekst贸w鈥. Jest to problem, o kt贸rym pisz臋 wi臋cej na mailingu Domain-Driven Design. Kod nie wie, czy funkcjonuje w kontek艣cie epidemii, czy nie i musi co chwile pyta膰 samego siebie czy isCovid. To rodzi potrzeb臋 ci膮g艂ej ifologi i zagnie偶d偶ania, tam, gdzie kod tak naprawd臋 powinen zosta膰 rozdzielony na konteksty i uproszczony w my艣l zasady 鈥渄ziel i zwyci臋偶aj鈥. Takie rozwi膮zanie mo偶e by膰 dobrym sposobem na 鈥淒eadline-Driven Development鈥, ale z pewno艣ci膮 nie jest to inwestycja w przysz艂o艣膰.

Chcesz uczyni膰 swoje programowanie bardziej pragmatyczne? Marzysz, 偶eby modelowa膰 procesy biznesowe zamiast tabelek w bazie danych? Ju偶 pierwsz膮 dawk臋 wiedzy otrzymasz po zapisaniu si臋 na mailing Domain-Driven Design. B臋dziesz mia艂 ze mn膮 bezpo艣redni kontakt i dostaniesz praktyczne zadania prosto na swoj膮 skrzynk臋! ZAPISZ SI臉 TUTAJ

Inni te偶 tym 偶yj膮

2021 Mateusz Nowak | Polityka prywatno艣ci