Faile w IT

1

Ktoś kojarzy jakieś ciekawsze wpisy lub może z własnego doświadczenia zna historie faili projektów it od strony programistycznej i chciałby się pochwalić?

0

Wątek chyba podobny do: Programistyczne WTF jakie Was spotkały

7

ja znam 2 i zdarzają się dość często a ich imiona to klient i estymacja.

1

Wszystkie projekty nad którymi pracowałem w ciągu ostatnich 10 lat. :)

Jeden z nich przyniósł nawet stratę w wysokości 1 miliarda dolarow. :)

31

Pisałem, że nie znam takich prawdziwych katastrof z własnego doświadczenia. Natomiast takie półfaile (semi faile) to poznałem. Nie kończyły się one zamknięciem projektu, ale były nauczką, czasem kosztowną.

Jeden przypadek:
Dawno, dawno temu prawcowałem dla całkiem fajnej firmy. Klasyczny układ: niemieccy architektci i management oraz polsko-hinduska hołota do oprogramowania tego co tamci wymyślą.

Projekt to był taki dropbox w wersji enterprajs. Obiecywał poprawiać współpracę międzyludzką w projektach. Technicznie: webówka z UI specjalnie pod IE 6 :-) , backend java EE/weblogic. Frontend HTML poparty strutsem z elementami pierwszego JSF :-) (jeszcze gorszy niż ten późniejszy).

W takim dropboksie, czy czymś podobnym, wrzucasz plik i dzielisz się linkiem z kim tam chcesz.
Tu było trochę więcej pracy:

  1. tworzysz obiekt - wirtualna firmę,
  2. zakładasz wirtualnych współpracowników,
  3. zakładasz zespoły i przydzielasz do nich współpracowników,
  4. tworzysz grupy uprawnień i przydzielasz do nich zespoły i pracowników,
  5. tworzysz projekty w ramach firmy,
  6. projekty mają foldery, milestone itp.
  7. przydzielasz uprawnienia do powyższych,
  8. na koniec w pewnym folderze robisz upload tego pliku word, którym chcesz się podzielić,
  9. podczas uploadu zwykle zrywa się transfer, zawiesza się IE6 czy coś jeszcze,
  10. po trzech próbach dowiadujsz, się że plik przekracza 4mb i nie moze być uploadowany,
  11. kompresujesz plik,
  12. uploadujesz skompresowany plik, ale okazuje się, że program akurat tego .zip to nie obsługuje,

W końcu poddajesz się, robisz szczepionkę przypominającą, załatwiasz wizę, nagrywasz program na pendrive, wsiadasz w samolot do Frankfurtu, przesiadka i prosto do Bangalore. Na miejscu możesz wręczyć pendrive twojemu koledze. Gotowe.
Ponieważ współpraca twarzą w twarz jest bardzo efektywna to można przyjąć, że program spełniał obietnice usprawniania tejże współpracy.
Sukces.

Tym niemniej, w trakcie tworzenia tego cuda, były pewne potknięcia.

Mniej więcej po roku tworzenia (~20 osób) system powoli wyglądał tak jak miał wyglądać i jakoś działał. Jakkolwiek, działał dość wolno.

Każdy ekran to było solidne czekanie aż sie załaduje. I to na porządnych serwerach, niezłym łaczu i przy jednym użytkowniku. Dwóch użytkowników równoczesnych zabijało system całkowicie.

Dość szybko niemieccy architekci zidentyfikowali problem. Każdy ekran to kilkaset zapytań do bazy danych. Głównie do jednej tabelki ( resources chyba). Jak robimy ultra enterprisy system uprawnień, - grupy, zespoły, projekty, idt. i mamy np. na ekranie 10 dokumentów to troche trzeba zapytań zrobić - czy użytkownik widzi dokument? A może otworzyć? A czy zespół, grupa etc. A czy ma prawo do widzenia wersji? a do daty? a ma prawo zobaczyć autora? itd.
Pełen wypas :-)

Wiadomo, że tak pięknego systemu uprawnień uprościć nie wolno, zresztą kto by chciał?

Niemieccy architekci podumali i zaproponowali inne rozwiązanie:
Ponieważ jak wiadomo każde zapytanie SQL kosztuje 1 to im mniej zapytań tym lepiej. Zamiast 400 prostych zapytań zróbmy jedno zajebiste über-zapytanie. Zanim strona sie wyrenderuje to będzie generowany taki jeden wielki SQL, który zwróci wszystkie informacje potrzebne dla wszystkich możliwych checków na tej stronie. Szybko wyszło, że nie bardzo da sie takie pytanie napisać z palca (za wiele hierarchii). Powstał więc pomysł, że trzeba zrobić generator tego SQL. To zadanie dostał mój kolega (naprawdę kolega - nie ja). Kolega jest niestety dość bystry i dość szybko zaczął się buntować. Generalnie uważał pomysł za nonsens i płakał jak commitował. Szło mu jak krew z nosa, co chwilę znajdował problemy. W nagrodę niemieccy architekci oskarżali go o olewanie pracy, buntowanie zespołu i generalnie nie bycie team playerem. Chyba nawet wymusili pojechanie mu po pensji / premii:-( .
Pamiętam jak ten kolega w trakcie przyszedł raz do mnie z wydrukiem - 4 kartki A4 SQLa - wygenrowanego zapytania. Drobnym fontem. I był tam błąd do znalezienia :-) Widziałem człowieka na krawędzi szaleństwa.
Tak czy siak, po kilku miesiącach i wielu przepychankach był branch z rozwiązaniem. Jakie było zdziwienie jak się okazało, że nie jest szybciej...
Ba, udało się stworzyć kwerendę, która prawie zabija bazę (ORACLE) i to na etapie tworzenia planu :-)

W tym czasie była już lekka panika, klienci mieli obiecany soft, a tu dramat więc była akcja wszystkie ręce na pokład i dołączyłem do projektu, żeby pomóc znaleźć i rozwiązać problem.
G... pomogłem :-(, profilowanie serwera Java EE w antycznych narzędziach i z moją ówczesną wiedzą trochemnie przerastało. Tworzyłem jakieś typowe bzdury, jakie tworzą juniorzy - sprawdzanie czasu przy pomocy System.currentTimeMillis() itp.
Pojawił się wtedy pomysł, żeby pomierzyć jakoś bardziej profesjonalnie. Firma wynajęła konsultanta z bardzo drogim softem do profilowania enterprajs. Borland (tak!) Server trace.
Już po kilku godzinach walki z setupem tego softu udało się uzyskać pierwsze wyniki. Z diagramów jasno wynikało :

  • faktycznie, przy na renderowaniu strony leci około 400 zapytań (wersja bez przesławnej poprawki z ubersqlem),
  • przetwarzanie tych 400 zapytań zajmuje mniej więcej 1% czasu :-).
  • cała reszta, w zasadzie wszystko, siedzi w jakimś tagu JSP :-)

Do dzisiaj pamiętam historię tego swetraTaga. To było coś w stylu struts:if i był to tag związany z uprawnieniami. Generalnie konstrukcja w stylu :
<stuts:if test="$doc7.permission(user, 'READ') == `Allow`"> <button>edit</button></stuts:if> (na pewno dokładnie tak nie wyglądało, ale o coś podobnego chodziło).
I takie coś kilkaset (jak nie więcej) razy na stronę, przy każdym duperelu.
Nie masz uprawnienia - nie widzisz buttona - oczywiste.

Dowcip był w implementacji tego if , a dokładniej wyrażenia związanego z == czyli porównania. Z jakiś archeologicznych względów te wyrażenia przychodziły generalnie jako ciągi tekstowe. To wiedzieliśmy i generalnie zależało nam na porównaniu ciągów tekstowych. Natomiast twórcy Taga (open source) mieli jakieś inne pomysły. Może chciałeś porównać liczby, daty ... które tylko przypadkiem są chwilowo zserializowane jako tekst? Pomożemy Ci.

Kluczowy kod wyglądał mniej więcej tak:

//porównujemy czy a==b
try { 
  return Double.parseDouble(a) == Double.parseDouble(b)
} catch (Exception e) {

return Float.parseFloat(a) == Float.parseFloat(b)
} catch (... 
parseDate...
catch ( 
parseDateAleInnyformat,
catch (
return Integer.parseInt(a) == Integer.parseInt(b),
...
... i jeszcze pare innych try and error
...
i daleko na końcu
return a.equals(b); // a o to właśnie nam chodziło :-)
}

Czyli próbujemy na rożne sposoby sparsować String i dopiero jak wszelkie sposoby zawiodą to wracamy do zwykłego porównania. Genialne.
Nie wiem co kierowało twórcami tego taga, że nie zrobili od razu tego zwykłego porównania. Pewnie był jakiś powód, którego nie rozumiem.
Natomiast fakt jest taki, że rzucanie tonami exceptionów. tak z 10 przy każdym porównaniu to nie jest to co JVM lubi najbardziej.

Tworzenie stack trace jest dośc kosztowne. Wiele optymalizacji JVM typu inlining bierze w łeb..., a jeszcze wchodzą problemy z lockami, save pointami itd. Dramat.
Podsumowując praktycznie całe CPU siedziało na rzucaniu tymi exceptionami (nigdzie nie były logowane - czyli tylko sobie tak wewnętrznie szły).

Napisaliśmy własną wersję tego taga, która od razu przechodziła do rzeczy (robiła zwykłe porównanie).

Projekt ruszył i jakoś się tam sprzedawał. Firma działa do dzisiaj, projekt nadal w ofercie (choć strzelam, że z tamtego kodu nic już nie zostało).

Pod wpływem doświadczeń postanowiłem trochę bardziej zająć się wnętrznościami JVM i profilowaniem.
Kolega od ueber sql powiedział, że z taką bandą idiotów jak w IT to już nie chce pracować i po jakimś czasie zmienił branżę.

EDIT: Jakiś czas po tej akcji miałem oświecenie i popełniłem ten wpis:
http://www.99-bottles-of-beer.net/language-java-866.html

Czyli, krótki przykład jak ify/ while i inne konstrukcje można zastąpić przez try catch.

1

Uncle Bob (Rober C. martin) podczas swoich prezentacji opowiada o dwóch takich przypadkach:

  • firma która zrobiła pierwsze IDE z prawdziwego zdarzenia dla C. Napisali szybko i niechlujnie, pojawiło się C++ i zapotrzebowanie by ich IDE obsługiwało też C++. Próby kończyły się produktem, który często się wieszał lub crashował i z tego powodu stracili klientów i zbankrutowali
  • Świeższa historia: firma od High Frequency Trading, dla wygody ktoś użył jakiejś flagi do oznaczania zachowania, która wcześniej znaczyła coś innego. Podczas instalacji na 14 maszynkach ktoś zapomniał o jednej maszynie i zaczęły się dziać dziwne rzeczy. Koniec końców dnia następnego właściciel firmy obudził się jako bankrut. (Uncule Bob Talk wiki Knight Capital Group (dzięki @hauleth).

Linka z filmikami, gdzie Uncle Bob o tym opowiada <deL>teraz nie</del> dostarczę, a oficjalnego potwierdzenia opowiadanej historii nigdy nie szukałem.

Z osobistych doświadczeń: zaliczyłem 3 projekty u Nokia (wszystkie wylądowały w koszu) - problem ewidentnie polegał na złym zarządzaniu.

Z innych ciekawych rzeczy to jest jeszcze General Magic - technologiczny falstart.

18

widzialam calkiem sporo porazek, zazwyczaj wynikajacych z polityki, projekty ktore byly tworzone latami przy wielomilionowych budzetach i cicho ubijane, tak ze ostatecznie konsekwencje finansowe ponosili (posrednio) klienci.
z takich bledow (przynajmniej okolo) programistycznych ktorych bylam jednym z glownych winowajcow (ale bez formalnej odpowiedzialnosci):

  • testowa gielda uzywala danych z poprzedniego dnia wiec sila rzeczy nie bylo tam biezacych orderow, caly algorytm "part rate" (tzn trzymaj swoj udzial w ogolnym wolumenie na jakims tam poziomie) napisalam i testowalam przy uzyciu swoich mockowanych danych, po wrzuceniu na produkcje wygladalo ok (bo rano nie bylo zadnego wolumenu) akcja zaczela sie gdy pojawil sie pierwszy order, w uproszczeniu, wszystko w ulamkach sekund (A - nasz algorytm, B - reszta gieldy, C - calosc gieldy):
  1. A - 0, B - 0, C - 0 (nikt nic nie traduje)
  2. A - 0, B - 100, C - 100 (ktos tam cos wyslal)
  3. A - 100, B - 100, C - 200 (wysylamy nasz udzial)
  4. A - 200, B - 100, C - 300 (o kurde, zapomnielismy odjac nasz udzial od calej gieldy)
  5. A - 300, B - 100, C - 400 ...
  6. A - 400, B - 100, C - 500 ...
    ...
    w miedzyczasie inni gracze zauwazyli ze ktos (tzn my) jest dosc zdecydowany ;) i tez zaczeli wysylac.
    straty byly minimalne, niemniej ten blad byl najbardziej istotny z 4 zauwazonych i ujetych w podsumowaniu przez regulatora, lacznie $7M kary za niedostateczna kontrole jakosci.
  • pisalam optymalizator do zapytan do realtime indeksu, w qa dzialal swietnie, na produkcji struktury danych byly bardziej skomplikowane. klienci wysylali tylko nudne proste zapytania, ja bylam ciekawa co sie stanie jak bedzie cos naprawde ambitnego. efekt - OOM w optymalizatorze i jego kolegach, niezoptymalizowane zapytanie do wlasciwego indeksu ktore go zawiesilo, failover zawiesil sie rowniez, wszyscy klienci przeniesli sie na stara wersje co ja za bardzo obciazylo i zdechla, przy restarcie nie umialo nic wstac bo za duzo danych w file cache bylo...
    efekt - nikt nie obliczyl strat, ale realtime analytics nie dzialaly do konca dnia.

  • pisalam prosty algorytm do limit orderow (cos na zasadzie jak cena sie zbliza do limitu to zreleasuj za jakis tam czas), testowalam na equities, futures i opcjach, potem przyszedl request ze cena moze byc ujemna dla multileg spreads (tzn moze to byc roznica miedzy cenami) wiec spedzilam sporo czasu zeby sie upewnic ze cena moze nie byc liczba naturalna, niestety nie przetestowalam 0, co bylo traktowane jako non-limit order w efekcie szlo na gielde z dowolna cena, natychmiastowe straty na poziomie $15k + klienci juz nie tradowali tych instrumentow z nami :(

  • dodawalam tzw inline replace do SOR (smart order router), przetestowalam dla jednorazowego replace, przy kazdym nastepnym wchodzil w nieskonczona petle, efekt - w ciagu 10 minut terabajty logow i milionowe straty

  • tez SOR - jako reviewer przepuscilam kod ktory w razie niepowodzenia probowal do skutku, bez zadnego licznika czy timeoutu (dzialo sie to przy udziale kilku roznych modulow, ale pozniej jak spojrzalam to daloby sie wykryc. efekt trudny do zmierzenia, ale trzeba bylo cala produkcje cofac do starszej wersji w ciagu dnia

  • ktos w wiki pomylil label prod i dev przy connection details wszyscy o tym wiedzieli ale nikomu nie chcialo sie zmienic bo trzeba bylo dodatkowe uprawnienia requestowac zeby zmienic opis. koles ktory byl teoretycznie moim podwladnym usunal rekordy z bazy ktore wg regulacji powinny byc trzymane przez 10 lat. w tajemnicy odzyskiwalam to przez iles dni z roznych logow :)

w obecnej pracy w kazdym tygodniu tracimy te pare k na bledach w algorytmach wynikajacych z tego ze za malo testowalismy i tez nikomu nie chce sie angazowac za bardzo bo i tak jestesmy na +

3

Sa firmy gdzie jesli blad pojdzie na produkcje, to mozna sie o tym z TV dowiedziec:

5

A pamiętacie polski kalkulator wyborczy?

7

Nie do końca fail, ale było groźnie.

Kiedyś firma, w której pracowałem miała zlecenie na zrobienie odtwarzacza internetowego na komórki. Coś jakby protoplasta Spotify, ale z naciskiem głównie na radio. To było w czasach, kiedy modne były ficzerfony z kolorowymi ekranami, ale jeszcze nie było smartfonów.

Na poziomie zarządu jakoś zadecydowano, że my się zajmiemy wypasionym interfejsem zarówno po stronie serwera jak i apką mobilną na telefony, treści muzyczne dostarczy firma zewnętrzna (partner) zgodnie z umową na wysokim szczeblu, natomiast sprawy dekodowania dźwięku będą zrobione z pomocą jeszcze innej firmy trzeciej, która dostarczy odpowiednie biblioteki natywne do dekodowania strumieni, a my je tylko wywołamy w aplikacjach. Idealny plan - to się nie mogło nie udać!

  • Miesiąc 1: Partner uruchomił testowy serwer strumieniujący dźwięk. Nam udało się dostać do nich przez specjalne API. Z działu graficznego przyszły jakieś szablony interfejsu. Pełna ekscytacja w każdym zespole.
  • Miesiąc 2: Został ustalony stos dla aplikacji - zespół frontendu zaczął kodować prototyp aplikacji bazując na szablonach. Wkrótce mieli prototyp aplikacji z prostym UI radia. W międzyczasie zespół serwerowy zrobił duży kawałek części serwerowej (jakieś tam logowanie, rejestracja, model bazy danych, wysyłanie danych potrzebnych do frontendu itp.). Ekscytacja nawet jeszcze większa bo przecież JUŻ COŚ DZIAŁA, można wyświetlić i pokazać szefowi!
  • Miesiąc 3: Dostaliśmy ten obiecany kodek z firmy trzeciej. Chłopaki z frontendu szybko to oprogramowali i YES YES YES - nasza apka faktycznie gra muzykę na emulatorze jakiejś Nokii. Ale czad! W międzyczasie prace nad UI dalej idą pełną parą i aplikacja wygląda coraz ładniej i ma coraz więcej funkcji.
  • Miesiąc 4: Przyszły telefony do testów. Wrzuciliśmy apkę na prawdziwą, najbardziej wypasioną Nokię jaką dostaliśmy. Taką super Nokię, która nawet pozwalała pisać nawet emaile! Apka działa, UI chodzi jak marzenie, ale... muzyka się rwie. Pewnie jakiś bug. Poprawimy.
  • Miesiąc 5: Przyszła prawdziwa grafika od grafików. UI wygląda przecudownie. Dźwięk się nadal rwie na telefonie. Na emulatorze wszystko działa ładnie więc nie ma nerwów.
  • Miesiąc 6: Deadline projektu się zbliża. Mamy kompletne UI działające na wszystkich telefonach. Muzyka nadal się rwie na wszystkim oprócz emulatora. Trzy osoby siedzą 8h dziennie i szukają błędu. Znaleźli kilka bugów, ale muzyka nadal się rwie.
  • Tydzień przed deadlinem: Zarząd zobowiązuje się dostarczać pizzę nawet w niedzielę, byle w końcu to odtwarzanie dźwięku działało. Równocześnie negocjują przesunięcie deadline'u. Niestety z firmą która dostarczyła nam kodeki nie podpisano kontraktu na support. Nikt nie wie jak te kodeki działają, bo napisano je w C. Muzyka dalej nie działa.
  • Tydzień po deadlinie: deadline przesunięty, muzyka dalej nie działa. Klient wkurzony i grozi karami umownymi.
  • Dwa tygodnie po deadlinie: Znajdujemy kilka kolejnych bugów w obsłudze buforów. Wszyscy są podjarani że udało się znaleźć problem. Po instalacji na telefonie muzyka jednak dalej się rwie jak internet przez EDGE'a w lesie. Klient wk***ony, że zrobiliśmy odtwarzacz dźwięku, w którym działa wszystko oprócz odtwarzania dźwięku.
  • Trzy tygodnie po deadline: Nad problemem niedziałającego dźwięku pracuje już chyba cała firma łącznie z działem HR i sprzątaczką.
  • Cztery tygodnie po deadline: W końcu jakiś koleś z zupełnie innego działu natrafia w kodzie C na linijkę wyglądającą mniej więcej tak:

    #define USE_INT_MATH FALSE

    Zmienia na TRUE i przekompilowuje wszystko.
    Aplikacja zaczyna śmigać na wszystkich telefonach. Happy End!
3

Z tego co mi się przypomina:

  1. Update bez WHERE. Na produkcji. Udało się przywrócić poprzedni stan flashbackiem tabeli.
  2. Menedżer plikow, F8, ENTER. Upssss, właśnie usunąłem 5 baz danych. Po 2 godzinach były odtworzone, bo ja z tych co robią backupy. :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1