Programistyczne WTF jakie Was spotkały

4

Mamy sobie fragmencik kodu:

Timex.parse("6/17/19 9:13", "{M}/{D}/{YY} {h24}:{m}")

Pytanie, jaki jest wynik? Oczywiście błąd:

{:error, "Expected `hour between 0 and 24` at line 1, column 9."}

ale, że jak? Ano tak, że biblioteka domyślnie traktuje {h24} jako zawsze dwuznakowy zapis godziny. A teraz najlepsze. Prawidłowy kod w tym przypadku to:

Timex.parse("6/17/19 9:13", "{M}/{D}/{YY} {_h24}:{m}")

tak z podkreśleniem na początku. Podkreśleniem, które w elixirze oznacza „olej mnie”. I na deser – jest jeszcze format {0h24}, który wymusza zero wiodące przy godzinach 0-9. I jak tu nie kochać konsekwencji elixirowców.

ps. zwróćcie uwagę na zapis miesiąca i dnia. Tam od ręki przyjmuje jednocyfrowe wartości i istnieje dodatkowa opcja {0M} i {0D}

3

Code review C++. metoda uruchamiana raz na 15 minut - dosłownie.

void Class::Method(Arg arg)
{
    static std::vector<Data> tab;
    const auto _ = utils::finally([] { tab.clear(); });

    ....
}

Pytam się autora czemu to tak wygląda, bo jest to dziwne: "Optymalizacja pamięci" :|

0
Integer sum = someMethod().anotherMethodA().anotherMethodB().anotherMethodC().anotherMethodD().anotherMethodE().anotherMethodF().anotherMethodG().anotherMethodH().anotherMethodI().anotherMethodJ().anotherMethodK();
14

CR
Code Review hinduskiego kodu ;)

8

Naprawdę ktoś miał na tyle śmiałości żeby w oficjalnej dokumentacji wpisać "or something? ;|

screenshot-20190703184155.png

2

Może nie jest to programistyczne (chociaż jakby nie patrzeć to programowanie się za tym kryje), ale tak dzisiaj rzuciło mi się w oczy.

WTF.png

3

Ja dziś miałem nieco poważniejszy problem z t-mobile:
screenshot-20190707135515.png

Na szczęście w PDF już podali numer umowy :)

2
orchowskia napisał(a):

Ja dziś miałem nieco poważniejszy problem z t-mobile:
screenshot-20190707135515.png

Na szczęście w PDF już podali numer umowy :)

Mi Virgin przysyla rachunek do 6 miejsc po przecinku
Witaj, w dniu 12/04/2019 wystawilismy fakture VAT na 10,166179 zl z platnoscia do 29/04/2019. Aktualne saldo Twojego konta to 10,17 zl do zaplaty. Dokonaj platnosci na konto ...

8

WTF z wczoraj:

Dodaję nowe funkcje do istniejącego kodu. Potrzebuję obiektu, który będzie ważny przez czas trwania całego żądania i będzie dostępny z dowolnego miejsca tak aby nie dodwac nowego parametru do każdej z 23459408 metod z 3545 warstw. Szukam, szukam, w końcu... JEST! To jest dokładnie to, czego mi potrzeba: RequestLocal<T>. Ma metody get() i set(). Aaa, no tak, czyli to jest taki jakby ThreadLocal<T> ale dla requestu, świetnie.

Rzucam się w wir kodowania, dopisuję static RequestLocal<X> costam = new RequestLocal<X>() i....
WTF?! RequestLocal jest interfejsem a nie klasą!

Szybki rzut oka w istniejący kod, w celu dowiedzenia się, jak się tego wynalazku używa. Okazuje się, że jak chcesz dodać własny RequestLocal:

  1. Musisz napisać nowa klasę (nazwijmy ją X), która implementuje RequestLocal<X.State>
  2. W klasie X musisz zdefiniować klasę wewnętrzną State, przechowującą stan współdzielony w kontekście requestu.
  3. W klasie X musisz dać pole ThreadLocal<X.State> które stanowi faktyczne miejsce składowania stanu, zarządzane przez set() i get().
  4. W klasie X musisz dodać statyczne pole public static X instance = new X(), aby inne fragmenty kodu miały do tego wynalazku dostęp.
  5. W interfejsie RequestLocal trzeba dopisać do pewnej tablicy ten X.instance
  6. W kolejnej klasie RequestLocals trzeba też uzupełnić kod o ten X.instance
  7. W paru innych miejscach trzeba dorzucić kod aby prawidłowo nasz stan X.State kopiował się między wątkami i faktycznie był ten sam dla całego requestu.

Jak napisałem innemu programiście, że to jest trochę "dziwny" design, to odpisał, że faktycznie, ale to tylko dlatego, że użyto dziedziczenia a nie kompozycji. :D
Chciałem być miły, więc nie przyznałem: "Tak, to na pewno przez brak kompozycji."


WTF z dzisiaj:

Mam komunikat klasy Message. Pytam kolegę, co wysyła te komunikaty do zdalnego serwera. Odpowiedź: ChannelWriter. Faktycznie, jest taka klasa i ma nawet pole queue z kolejką komunikatów do wysłania. Jak dotąd, całkiem logiczne. Szukam w kodzie ChannelWriter, gdzie jest jakieś "weź z kolejki i wrzuć do kanału", a tu zonk - nie ma. Szukam jeszcze raz. No, wtf, po prostu, nie ma! No to szukam jeszcze wystąpienia channel.write czy czegoś podobnego i znajduję takie coś:

channel.write(this), gdzie this to instancja... ChannelWriter.

Serio zajęło mi dobre kilkanaście minut rozczajenie jak to w ogóle działa, mimo że to w sumie banalnie proste:
Otóż na channelu jest zainstalowany (w innym miejscu) handler, który wyłapuje ten wrzucony ChannelWriter uprzednio zrobiwszy rzutowanie z Object, czyta jego kolejkę (package private), serializuje każdy komunikat i wysyła do kanału. :D Oczywiście kod handlera w zupełnie innym miejscu niż ChannelWriter.

4

form.png

Nie no, fajnie ze dali test na człowieczeństwo :D (pomijając że i tak zrobiłem ctrl+c/v do kalkulatora i każdy bot by to zrobił :D)

3

Hahaha! :D Teraz zauważyłem że powyższy formularz, ile razy na niego nie wejdę zawsze ma to samo zadanie do rozwiązania :D tzn, zawsze mam "692+3*5+6-2".

Jak ktoś jest zainteresowany to http://forum.php.pl/rejestracja.html

7

Od wieków składam sobie internetową wersję lokalnej gazety. Parę lat temu zaktualizowałam silnik pod responsywność, parę dni temu dodałam skróty do łatwiejszego przechodzenia poprzedni/następny artykuł. Stronka w PageSpeed Insights ma 100/100 w obu kategoriach.

A dzisiaj się dowiedziałam, że nowa administratorka chce zamieszczać numery w PDF-ie. Sugerowałam, że to na telefonie będzie nieużyteczne, ale powiedziała, że ona tak właśnie na telefonie pdf-y przegląda i jest jej bardzo wygodnie. Z dziesięć lat temu może bym się jeszcze kłóciła, że chcą sobie zrobić krzywdę, ale obecnie po prostu wzruszam ramionami. Ich strona, ich sprawa. Niemniej po raz kolejny dochodzę do wniosku, że większość ludzi ma chyba jakieś inne mózgi :/

4

Cenię Chipa za to, że w zalewie lajfstylowych, pseudotechnologicznych bzdetów potrafi zaserwować sążniste analizy jak za starych dobrych czasów.

Tym bardziej boli, jak redaktora portalu technologicznego nie odróżnia emoticon od emoji i jeszcze twierdzi, że w GG używaliśmy właśnie tego wekotorwego szkaradztwa zamiast jedynych prawilnych graficznych emoticonek :/

Do ekspansji emoji przyczyniło się rozpowszechnienie kodu Unicode, dzięki któremu zestawy emotek pojawiły się w popularnych komunikatorach (także w polskim Gadu-Gadu).

https://www.chip.pl/2019/07/ile-wy-wysylacie-tych-emotikonow/

3

Kolejny dowód na to, że informatyka i pociągi nie idą w parze.

Chcę kupić bilet do Krakowa korzystając z https://portalpasazera.pl
Wpisuję datę, godzinę, stacje. Dostaję wynik:

screenshot-20190723222057.png

Już mam kupić bilet, gdy dostrzegam, że znaleziony bilet jest na dzień wcześniej. I tak można ufać PKP...

EDIT.
W ogóle ten portal ma beznadziejny interfejs.

  • Nie można wybrać wszystkich stacji w danym mieście, tylko konkretną. A skąd mam wiedzieć z góry z jakiej stacji odjeżdża dany pociąg, albo na jaką przyjeżdża?

  • Gdy zaznaczam PRZYJAZD w opcjach wyszukiwania, to znaczy, że chcę przyjechać PRZED tą godziną i szukam najbliższego pociągu, który tego dokona. Najwyraźniej jednak to zaznaczenie nie ma żadnego wpływu na wynik.

1

Właściwie, nie wiem, czy to bardziej tu czy do trochę humoru.
Dzisiaj natrafiłem na takie coś:

try {
    throw new RuntimeException();
} catch (Exception e) {
    ...
}     

Oczywiście od razu nabrałem podejrzeń, że to napisał taki jeden mój człowiek, który miał kiedyś w zwyczaju napisać puste catch (Exception e) {} (taki nasz "wyjątkowy antytalent"), więc natychmiast pomyślałem, że to on. Git Annotate... a tu zonk, nie on, tylko dev z duuużym doświadczeniem.

Zagadka: po co ktoś mógłby to napisać?

1

screenshot-20190729154522.png
screenshot-20190729154725.png

6

Jak wygląda proces "unsubscribe" w pewnym angielskim banku:)
https://twitter.com/Joe8Bit/status/1156312965265707013

1

Że JS miewa bzdurne przekonania odnoście wartości i równoważności zmiennych, to wiem. Ale to już przebija wszystko:

x = 0.1 + 0.2; // -> 0.30000000000000004

1

Pozwolę sobie skomentować komentarze odnośnie mojego powyższego WTF
x = 0.1 + 0.2; // -> 0.30000000000000004 - JavaScript rulez!

Tak, wiem że dwójkowa reprezentacja ułamków dziesiętnych może skutkować dziwacznymi wynikami. Walczyłam z podobnymi efektami już 20+ lat temu. Niektórzy komentatorzy pisali powyżej, coś w stylu "przecież to jest zapisywane w postaci dwójkowej, więc takie będą efekty", z czym pozwolę się sobie nie zgodzić, bo zapis wartości w postaci dwójkowej nie wymusza wcale, by operacje matematyczne z ich udziałem wykonywać zawsze po prostu na bitach.

Moje WTF tyczy się tego, że po ponad 20 latach nie widzę w tej kwestii żadnego postępu, a twórcy języka/implementacji nie widzą żadnego problemu w tym, żeby taki sposób przeprowadzania operacji stosować w języku "dla ludu", w którym ktoś mógłby chcieć np. podliczyć swoje rachunki.

A na koniec wkleję skrin z identyczną operacją przeprowadzoną w Basicu na prawie 40-letnim Commodore 64:

C64, basic, dodawanie

jako komentarz, dla tych, którzy uważają, że "tak po prostu jest, więc tak musi być".

5

Jeśli już kiedyś tutaj było, to wybaczcie:

8

javascript:
title

9

Nie do końca programistyczne.

2 tygodnie temu wróciłem z urlopu i VDI (zdalny Windows) zgłosił mi wygaśnięcie hasła. W wymogach wielkie/małe litery, cyfry i znaki specjalne. Wbiłem nowe hasło i kontynuowałem pracę. Niestety, mniej więcej raz w tygodniu leci wymuszony restart. Nowe hasło zostało przyjęte na stronie, z której odpalam VDI, ale już na ekranie logowania Windows wywalało błąd. Ani stare ani nowe nie przechodziło, zablokowałem konto, kontakt z ITS (mniej więcej jak na ostatnim filmiku HRejterzy), pan odblokował mi konto i strzelił reseta.. po resecie Windows czasem nie pyta o hasło, loguje się jakoś automatycznie.

Minęło dni kilka, znów reset, znów hasło nieprawidłowe.. Ustawiłem sobie nowe (przez stronę można), zalogował się automatycznie.. ale po paru dniach znów reset i znów "hasło nieprawidłowe" i ITS..
Sytuacja stawała się co raz bardziej absurdalna aż do dziś... ta sama historia, ale tym razem znajoma z biurka obok "a spróbuj wirtualną klawiaturą wpisać". Odpalam, a tam... układ brytyjski! WTF. Dlatego nic poza wykrzyknikiem nie przechodzi, jakieś funty i inne krzaki zamiast klasycznego układu amerykańskiego. Hash obok entera.. mogłem sobie wpisywać swoje hasło i 100 razy i bym nie trafił. Dopiero po zalogowaniu ładuje ustawienia mojej klawiatury.

Co więcej, kursor myszy znika jak najeżdżam na tę wirtualną klawiaturę, więc muszę na oko z wyczuciem niewidzialnym kursorem najechać, kliknąć i mieć nadzieję, że * w polu hasła to odpowiedni znak :D

5

screenshot-20190814110824.png

1

WTF No. 1

Gdzieś w odmętach pull requesta drugiego juniora, javowca 2y:

@Test
void 'Foo should this and that blah blah blah unit test'() {
  def foo1 = new Foo(/* jakieś 80 znaków inicjalizacji */)
  assertFooThisAndThatInThose2LinesOfCodeOrSo(foo1, CONST_1)

  def foo2 = new Foo(/* jakieś 80 znaków inicjalizacji */)
  assertFooThisAndThatInThose2LinesOfCodeOrSo(foo2, CONST_2)

  def foo3 = new Foo(/* jakieś 80 znaków inicjalizacji */)
  assertFooThisAndThatInThose2LinesOfCodeOrSo(foo3, CONST_3)
}

No zdarza się. Sam ciągle popełniam takie wtopy i babole, że jak już mija zaćmienie umysłu to aż łapię się za głowę i rozważam pokutę w postaci 10 lat robót w kamieniołomie.

Ale...

Ten sam junior namawia mnie do parametryzowania wszystkiego co się da, również wtedy, gdy zwyczajnie żadnej korzyści to nie przyniesie. Ale widocznie tego nie szło ani sparametryzować, ani rozbić tych 3 przypadków na 3 osobne testy ¯\_(ツ)_/¯

WTF No. 2

Ten sam delikwent, ten sam pull request, też gdzieś w testach:

@Test
void 'this and that should blah blah blah'() {
  // coś tam coś tam
  assertThisAndThatBlahBlah(foo, bar)
}

private assertThisAndThatBlahBlah(Foo foo, Bar bar) {
  assertThisAndThatBlahBlah(foo, bar, SOME_DEFAULT_BAZ)
  assertThisAndThatBlahBlah(foo, bar, SOME_DEFAULT_BAZ)
  assertThisAndThatBlahBlah(foo, bar, SOME_DEFAULT_BAZ)
  assertThisAndThatBlahBlah(foo, bar, SOME_DEFAULT_BAZ)
  assertThisAndThatBlahBlah(foo, bar, SOME_DEFAULT_BAZ)
}

private assertThisAndThatBlahBlah(Foo foo, Bar bar, Baz baz) {
  // nic co mogłoby uzasadnić N wywołań pod rząd
}

A może to po prostu dobre praktyki testowania w JUnit, a ja jestem głupi i się nie znam? :/

10

javascript:

('b' + 'a' + + 'a' + 'a').toLowerCase()

banana

7

https://github.com/techtalk/SpecFlow/issues/1696

drugi komentarz :D (kliknijcie w duplikat)

5

Sam się zaorałem.

Pisząc testy w Jest, utworzyłem sobie na potrzeby testów pewną strukturę danych (tablicę tablic), do której dodałem taką oto asercję:

    expect(whatHappened).toEqual([
       ['UPDATE', {a: 10}, {a: 10}],
       ['EFFECTS', {a: 10, b: 11}, {a: 10, b: 11}],
       ['UPDATE', {a: 10, b: 11}, {a: 10, b: 11}]
       ['EFFECTS', {a: 10, b: 11}, {a: 10, b: 11}],
    ]);

I testy nie przechodziły, pomimo, że powinny były przejść! Aż sprawdzałem JSON.stringify(whatHappened, 0, 2) i przyglądałem się po kilka razy, wszystko wydawało się w porządku. Nawet sprawdzałem kolejne elementy tablicy po kolei i wszystko przechodziło. Tylko jak się dało całą tablicę naraz, to nie przeszło. I dawało w diffie, że gdzieś jest undefined, mimo, że go przecież nie było!

Więc zmieniłem expect z Jest, na assert.deepStrictEqual, mając nadzieję, że to bug w Jest. Bo przecież jak to tak? Jednak assert.deepStrictEqual także wywalało mi błąd, jednak nieco czytelniej mi pokazywało diffa.

fragment tego diffa (wreszcie załapałem, gdzie się pojawia to undefined.

        Array [
          "EFFECTS",
          Object {
            "a": 10,
            "b": 11,
          },
          Object {
            "a": 10,
            "b": 11,
          },
        ],
    -   undefined,
    +   Array [
    +     "UPDATE",
    +     Object {
    +       "a": 10,
    +       "b": 11,
    +     },
    +     Object {
    +       "a": 10,
    +       "b": 11,
    +     },
    +   ],

Jak widzimy, między dwoma elementami tablicy nijak skądś wyskakuje undefined. Wiecie już?
.
.
.
.
.
.
.
.
.
Otóż, ku mojemu przerażeniu dokonałem straszliwego odkrycia. Zapomniałem przecinka

       ['UPDATE', {a: 10, b: 11}, {a: 10, b: 11}]
       ['EFFECTS', {a: 10, b: 11}, {a: 10, b: 11}],

i tutaj szybko wykoncypowałem, że JS [] wziął za indeks tablicy, a nie za kolejny element, więc dla JS te dwa elementy to było coś jak to:

jakasTablica =  ['UPDATE', {a: 10, b: 11}, {a: 10, b: 11}]; // pierwszy element
jakasTablica['EFFECTS', {a: 10, b: 11}, {a: 10, b: 11}], // drugi element

Jednak dalej coś się nie zgadza. Przecież w JS można dawać tylko jeden argument jako indeks []. no ale tutaj z górki. Po prostu w JS wyrażenie może zawierać przecinki, ale liczy się ostatnia wartość, czyli:

alert(('Hello', 'World')); // równoważne w tym wypadku alert('World');

wyświetli samo World (zwróćcie uwagę, że dałem tu dodatkowy nawias, bo bez tego potraktowałby wartość po przecinku jako separator między argumentami, więc wyświetliłby samo Hello.

Czyli JS potrafi być wredny. Nie poprzez brak typów, ale przez to, że wszystko może być wszystkim, a wiele znaków ma podwójne znaczenie (tutaj [], ale także {} rodzi tego typu problemy, podobnie jak () czy +...). Swoją drogą ciekawe, czy TypeScript i statyczne typowanie by mnie tutaj uratowało w tym momencie? Możliwe, mogłoby zaalarmować, że coś jest nie tak, ale czy dałoby mi na tyle czytelny komunikat, żebym zakumał od razu, co robię źle? Bo, że "coś nie działało", to mnie ostrzegł już Jest, ale to był komunikat, który wcale niewiele mi pomógł, poza tym, że wiedziałem, że coś nie działa, a powinno).

2

Dostałem przed chwilą maila z mBanku i moją uwagę zwrócił jeden szczegół:
screenshot-20190822141929.png

W źródle wiadomości jest:
screenshot-20190822142030.png

Kim jest Michał Maciejewski w mBanku :P?

Ps. To naprawdę jest mail z mBanku.

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