Programistyczne WTF jakie Was spotkały

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.

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