do if ($this->_getParam('foo') == 'bar') {
...
} while (false);
WTF?!
opis: "umożliwia w ifie zrobienie break"
dla mnie to taka przypudrowana wersja GOTO
do if ($this->_getParam('foo') == 'bar') {
...
} while (false);
WTF?!
opis: "umożliwia w ifie zrobienie break"
dla mnie to taka przypudrowana wersja GOTO
Skorzystałem z WTF i wyszedł WTF:
http://screener.tk/f/o/f/RRU1n.jpg
Rok temu w Gimnazjum jeszcze będąc na kółku informatycznym gdzie uczyłem się c++ pisałem chyba w Dev Cpp albo w Xcode (Mieliśmy też maki ) jakąś klasę , jakież było moje zdziwienie kiedy na 100 linijek kodu kompilator wywalił mi około 4000 błędów .
Chyba najpotężniejszy WTF jaki mnie spotkał w JavaScripcie. Przy okazji smutne jest to, że wiele -- zbyt wiele... -- osób piszących w JavaScripcie może nie zobaczyć w tym natychmiast WTF-a.
Fragment dużego, potężnego, komercyjnego, drogiego frameworka od bardzo znanej firmy, której nazwy (ani nazwy produktu) miłosiernie nie wymienię. Firma ta ma na pewno również i dobrych programistów, ale mimo setek tysięcy linii kodu w JS, zdaje się im brakować dobrych JS-owców.
namespace = {
createFileUploadField: function(elem, allowFlash){
return this.createFileUploadField(elem, allowFlash, false);
},
createFileUploadField: function(elem, allowFlash, enableFiltering){
// logika dla wywołania z trzema argumentami
}
};
namespace.makeFileUploadField(domEl, true);
Programista, prawdopodobnie Javowiec (nie żebym śmiał się z javowców -- po prostu back-end tego systemu jest napisany w Javie) najwyraźniej myślał, że JavaScript wspiera przeładowanie funkcji. Niestety, nie wspiera, a przynajmniej nie w ten sposób. W powyższym kodzie, druga deklaracja metody NADPISUJE tę pierwszą. Pierwsza przestaje istnieć.
Co więcej, gdyby używali trybu Strict, to parser natychmiast by im to zgłosił jako błąd. Niestety, nie używają.
Co śmieszno-tragiczne, ponieważ w swoim kodzie twórcy frameworka często korzystają z niesławnego operatora porównania z koercją typów (==
) zamiast bezpiecznego operatora identyczności (===
), lub używają po prostu testów if (enableFiltering)
, a brakujące argumenty są w JavaScripcie ustawiane na undefined
, które ma wartość fałszywą, to faktycznie -- z ich punktu widzenia -- wszystko będzie najczęściej działało. Bo chcieli domyślnie mieć w tej zmiennej false
, a otrzymują undefined
, które też jest wartością fałszywą. Akurat `undefined != false', ale w teście z if-em już nie zobaczą tej różnicy.
Czyli: popełnili rażący błąd, ale ze względu na ogólną, niezbyt wysoką jakość kodu, inny fail może ten fail zrównoważyć. I oni myślą, że to działa. Minus i minus daje plus.
protected
, a czy private
da się tam zrobić używając semantyki class
? Zdaje mi się, że konsekwentnie przeceniasz możliwości CoffeeScriptu. CS pomaga na stosunkowo niskim poziomie i w zasadzie nie wpływa na architekturę aplikacji. Nie powiedziałbym, że wprowadza jakieś wielkie rzeczy/paradygmaty do języka.
@Wibowit:
Ci najwyraźniej nie są, bo używają operatora z koercją typów (==) zamiast operatora ściśle uwzględniającego typy (===). Tych fanów JS-a zgubiła raczej to, że myśleli, iż przeładowanie funkcji robi się tu podobnie jak w Javie.
Po zobaczeniu tego kodu, który jest już którymś kolejnym, zapowiedziałem zemstę na Javowcach. I na c-sharpowcach. I reszcie ferajny, co pisze w obcym dla siebie, zupełnie innym języku tak, jak w tym swoim, i najwyraźniej nie widzi w tym problemu. A jeśli już, to w owym nowym, dziwnym dla nich języku, a nie w swojej niekompetencji w tymże.
Będę pisał kod w Javie tak, jakbym wciąż pisał w JavaScripcie, se-se-se! Do tworzenia obiektów będę używał TYLKO refleksji. Jak mi się zachce, to na siłę zaimplementuję sobie dziedziczenie prototypowe, bo to klasyczne jest jakieś dziwne i wprowadza niepotrzebne byty zwane "klasami" (prościej jest, gdy obiekty dziedziczą po obiektach!). Aha: moje obiekty to będą po prostu HashMapy, bo "u mnie tak to się robi i po co mam się uczyć czego innego". Będę se tam ładował własności dowolnych typów i będę narzekał na kompilator, że próbuje mnie przed tym bronić... znaczy się: że utrudnia mi życie. Bo chce, żebym na siłę sobie zawracał głowę jakimiś tam typami.
I będzie to tak samo fajne i inteligentne, jak pisanie w JS-ie tak, jak w Javie ;) ;) ;)
0x200x20 napisał(a):
Dziś spędziłem godzinę na debugowanie błędu, którego nie było.
skad ja to znam ;)
0x200x20 napisał(a):
Dziś spędziłem godzinę na debugowanie błędu, którego nie było.
Sytuacja w poprzedniej robocie, jakieś niecałe 2 lata temu - zrobiłem stronę (jakieś 5 podstron) dla naszego głównego i prestiżowego klienta. PM (nasz) zgłasza mi buga, że na jednej z podstron tekst jest przesunięty w lewo w stosunku do innych. Ja patrzę - faktycznie tak się dzieje. Walczę z CSSami godzinę i nie daję sobie rady, idę do mądrzejszego kumpla. Walczymy obaj kolejną godzinę, ale on też nie ma pojęcia o co chodzi.
Wreszcie przychodzi do pracy drugi kolega, nasz firmowy master od CSS, pokazujemy mu, a on mówi: "No, ale przecież tu jest więcej tekstu, więc pojawia się pionowy scrollbar."
PM są głupi. ;P
Rozjechana jak zawsze strona pomocy Google Adsense:
<meta name="description" content="
.Table {
border:1px solid #CCCCCC;
padding:0;
margin:20px;
width:90%;
}
.Table th {
padding:10px;
text-align:left;
font-weight:bold;
background-color:#CCCCCC;
font-size:110%;
}
.Table tr:nth" />
Win.
no może nie programistyczne WTF, ale aż przetarłem oczy jak próbowałem znaleźć coś o wtyczce "tilt" do FF - przez przypadek znalazłem Easter Egg'a :P
formularz z ochroną przed botami zakładającymi konta (usunąłem nieistotne fragmenty):
<form action="login.html">
<input type="text" name="username">
<input type="password" name="password">
teraz mistrzostwo:
<input name="logincode" type="text"/>
<img src="code.html?num=VHPJ" />
</form>
kod oczywiście generowany dynamicznie, ale chyba nie trzeba mówić co trzeba przepisać z obrazka :P
M jak Microsoft to głąby, odcinek 152900.
Robię raport w Reporting Services, ogólnie to fajne i wygodne narzędzie, ale...
Wpisałem do DataSetu takie zapytanie:
SELECT cośtam
FROM Tabela1 Tabela2 Tabela3 (joiny, szczegóły nieistotne)
WHERE Tabela1.UserId = @userId AND DATEPART(year, Tabela3.Date) = @year
Klikam Ok i... wyskoczył jakiś dziwny komunikat o niezdefiniowanych parametrach zapytania, a samo zapytanie się nie zapisało.
Myślę, że coś skopałem, więc piszę zapytanie w managerze bazy, odpalam - działa, więc kopiuję do RS, wklejam, Ok - i znowu dupa.
Próbuję jeszcze raz, klikam Ok - i zanim zamknąłem komunikat zauważyłem, że treść zapytania nie jest taka, jak wpisałem!
A mianowicie:
SELECT cośtam
FROM Tabela1 Tabela2 Tabela3 (joiny, szczegóły nieistotne)
WHERE Tabela1.UserId = @userId AND DATEPART(Tabela2.Year, Tabela3.Date) = @year
Tak, Tabela2 ma kolumnę Year, i designer zamienił argument year funkcji datepart na nazwę tej kolumny. :|
Ich własny designer od ich własnych raportów w ich własnym dialekcie SQL nie ogarnia podstawowej składni ich funkcji. WTF?
@Override
public String getUsername() {
return email;
}
Caly kod jest pelen takich nazewniczych baboli. Np. DbAuthenticationProvider uzywa LDAPa jako zrodla danych o userach, a bazy dopierdo jako fallback, itp. itd. Rzygac mi sie chce jak widze takie cos. Najlepsze ze glowny architekt / programista na stole ma Clean Code Wuja Boba.
mućka napisał(a):
@Override
public String getUsername() {
return email;
}
:)
mućka napisał(a):
Najlepsze ze glowny architekt / programista na stole ma Clean Code Wuja Boba.
Może stara się chłonąć wiedzę na odległość.
Dzisiaj mialem ciekawy WTF. C#, lapany Exception, a nastepnie sprawdzany jego typ - po msg'u (porownywanie string'ow) i obsluga konkretnego przypadku.
Rozwalilo mnie to, bo string do porownania byl po angielsku... a na tym konkretnym systemie rzucilo message'a po polsku i szlag trafil cala obsluge bledu :P
Może to nie jest WTF, bardziej atak złości, że COŚ jest nie tak, ale muszę się tym podzielić (tekst jest długi, ale to dobrze oddaje to, co przeżyłem).
Jest sobie stronka hostująca pliki. Bardzo mi się spodobała (dobre warunki, transfery itp), na tyle, że zachciało mi się mieć tam backupy i masę innych rzeczy. Niestety - webinterfejs mają strasznie dupny i korzystanie z tego jest katorgą. No to zachciało mi się napisać sobie do tego pseudo-API. Jako, że najlepiej znam PHP, w dodatku mogę to łatwo postawić na każdej maszynie - właśnie w tym to sobie napisałem. Po stronie serwera stronki stoi sobie ASP.NET. [I jeszcze dopisek - nie udostępniają żadnego API].
Jej autorzy od początku raczyli mnie cudami - zapisywanie zmiennych w różnych żądaniach ajax raz używając CamelCase, raz wszystko małymi, raz CamelCase tylko pierwsza literka małą. W jednym zapytaniu jedna zmienna w ogóle była z literówką. Zwrotka - czasem JSON ze statusem, komunikatami, kodem HTML, czasem tylko HTML. No masakra.
W końcu doszło do momentu napisania wysyłki plików. Przeparsowałem sobie formularzyk, wybrałem wszystkie ukryte zmienne, poskładałem to do kupy i robię pierwszą próbę wysłania pliku: Informacja, że wysyłanie nie jest aktualnie dostępne. I tu się zaczyna moja w sumie 5. godzinna zabawa.
Na początku pomyślałem, że to może "pominięte" zmienne z pustymi inputami typu file
, które służyły jako szablon do kopiowania ich, żeby umożliwić wysyłanie większej ilości plików naraz. Nie pomyślałem w sumie, żeby spróbować je usunąć z przeglądarki i zobaczyć czy ruszy - zacząłem się zastanawiać jak do cholery wysłać żądanie imitujące pustego inputa z typem file
przy pomocy PHP i cURLa - do teraz nie wiem. Wszelkie próby kończyły się tym, że żądanie w ogóle się nie wysyłało nie wyrzucając przy tym żadnego błędu. Z głupia spróbowałem w przeglądarce zatem "odkryć" ukryte pola, wrzucić pliki i zobaczyć, czy się wyśle. Wysłało się (o dziwo plik wrzucony tam także, ale to mniejsza). Potem nadeszły myśli, że serwer sprawdza kolejność zmiennych - poprzestawiałem (bo mój parser trochę inaczej je pozbierał). Wciąż nic. Teraz już było bardzo źle. Już straciłem na to dużo czasu i traciłem dalej kombinując, szukając sposobów i nic. Żeby jeszcze serwer zwracał o co mu chodzi to by było dobrze, ale nie. Zacząłem analizować działanie multipart/form-data
i stwierdziłem, że przeglądarki wysyłają inputy po kolei jak w HTML są - plik + jego opis, plik + opis, a cURL może np. przerzuca pliki na sam koniec i dupa, po zabawie (ew. zostanie pisanie zapytań przez fopen i ręczna implementacja dobrodziejstw cURL). Głupie mi się to wydało, w końcu jakaś przeglądarka też mogłaby tak robić i co?.. Nie bardzo było mi to jak sprawdzić z kolei (zainstalowałem jakiś sniffer requestów http, ale nie działał tylko przy tym jednym requeście). Poddałem się. Chwila przerwy, myślenie, czy pisać do supportu - tylko tutaj mogę dostać bana (choć w regulaminie nie ma wzmianki o pisaniu botów do wspomagania uploadu i zarządzania kontem), albo zostać olany (i ew. oznaczony w bazie jako "niebezpieczny"), a z szansą 1% - otrzymać pomoc. Postanowiłem, że nie, że zrobię, bo całość piszę już trzeci dzień i szkoda się poddać. Zastanowiłem się nad trzema magicznymi polami: __EVENTTARGET
, __EVENTARGUMENT
, __VIEWSTATE
. Teoretycznie na pierwszy rzut oka nic ciekawego się z nimi nie dzieje. Tj. EVENTTARGET
na początku jest pusty, a jak przeglądarka wysyła żądanie zawiera nazwę buttona, ale stwierdziłem, że podstawię i będzie ok, no bo musi być ok. Ale poczytałem trochę do czego to służy, potem przyszła kolej na __VIEWSTATE
- tutaj tekst był dłuższy, sprawdziłem sobie co zawiera, nawet zdekodowałem. W kodzie javascript nie znalazłem jednak wzmianki o tym polu. Dodatkowo pole tak jak zostało odebrane w HTMLu, tak samo było potem wysyłane. Tak samo sobie sprawdziłem action
w formie - sprawdziłem gdzie przeglądarka wysłała żądanie w narzędziach deweloperskich i porównałem to sobie z tym co wyskoczyło jak zrobiłem echo
na sparsowanym URLu. Identyczne.
Aż w końcu zdecydowałem się po raz kolejny zajrzeć w kod HTML formularza (pokaż źródło) i znowu oglądać to __VIEWSTATE
i inne poukrywane zmienne. I rzucił mi się w oczy atrybut action
formy. Aż zapomniałem jak się oddycha, a przed oczami widziałem już tylko &
, &
, &
, &
, &
... No więc nie zrobiłem url_decode
pobierając wartość action
, a wyświetlając to za pomocą echo
przeglądarka przerabiała te ampy
oczywiście. Tak samo Dragonfly/Firebug wyświetlając wartości atrybutów - dekoduje już wszelkie encje.
Podsumowanie i tl;dr
:
Zmarnowane 5 godzin z powodu braku dekodowania encji w adresie URL.
Szczypta WTF-ów z firmy gdzie obecnie pracuję:
W firmie z którą miałem (a może i będę miał) przyjemność współpracy był sobie jeden pracownik, Tadzio. Tadzio był geniuszem uwielbianym przez przełożonych, a konkretniej rzecz biorąc był synem siostry prezesa. Tadzio był CTO. Tadzio lubił dużo pisac i programować. Tadzio dużo komentował kod który pisał.
A teraz powód wtf, czyli poprawianie po Tadziu (idealnie oddaje kod. W całości problemu chodzi o serwis w php napisany przez Tadzia i jego team - nie chodzi na jednym z hostingów):
//To pisał Tadziu! Działa dobrze, nie psuć!
procedure TadziuShow($tresc){
echo $tresc;//Tu wypisuje treść, by Tadziu!
}
//To pisał Tadziu! Dizała!
procedure TadziuGet($tresc){
$tresc = $_GET[tresc]; //Tu pobiera tresc, działa, sprawdziłem - Tadziu
return $_GET['tresc'];//Tu zwraca tresc (hehe) działa, bo to Tadziu pisał!
}
Ciekawostka - takie coś to kilkadziesiąt plików. Jedyne co zmieniłem to imie bohatera... Poniżej główna przyczyna "nie chodzenia" na jednym hostingu:
//Tadziu Sessions
<?php
session_start();//start sesji - powinno działać, ja tego nie pisałem to nie wiem - Tadziu
Programiści .net i javy dziwią się że w C++ (natywnym) operacja 2/0 nie generuje wyjątku. To wft czy nie?
Jak C++ ma rzucać wyjątkiem skoro chodzi o rzeczy obsługiwane w C poprzez sygnały? Przecież tak samo nieprawidłowe odwołania do pamięci kończą się SIGSEGV
zamiast jakiegoś NullPointerException
. Kłania się kompatybilność wsteczna i rozdzielenie problemów niskopoziomowych od wysokopoziomowych, tutaj nie ma WTF.
rozdzielenie problemów niskopoziomowych od wysokopoziomowych
Czyli co, olewamy bezpieczeństwo i poprawność, a potem robimy globalnego handlera na sygnały, który będzie wywalał użytkownikowi na ryj, że "coś tam" się zesrało?
A porównywanie zakresów to też operacja niskopoziomowa?
http://en.wikipedia.org/wiki/X86_instruction_listings#Added_with_80186.2F80188 napisał(a)
BOUND Check array index against bounds raises software interrupt 5 if test fails
To jest taki WTF, że absolutnie nikt obecnie tej instrukcji nie używa.
Wibowit napisał(a):
rozdzielenie problemów niskopoziomowych od wysokopoziomowych
Czyli co, olewamy bezpieczeństwo i poprawność, a potem robimy globalnego handlera na sygnały, który będzie wywalał użytkownikowi na ryj, że "coś tam" się zesrało?
Nie. Jak chcesz mieć wyjątek, bezpieczeństwo i poprawność to sam to sobie zapewnij. Dodaj if
, dodaj throw
.
Wait, bound
jednak obsługuje i 32-bit. Co nie zmienia faktu, że używanie przerwań w miejscu, gdzie wystarczy prosty if
jest skrajnie niewydajne.
No, jak ktoś jest cierpliwy to nawet i w Brainfucku program napisze.
Potrafią sobie radzić? Na studiach w zasadzie jedynymi przedmiotami, które opierały się o C/ C++/ Pascala to różne semestry ASD. No i tam było od groma sygnałów (przy sprawdzaniu), które są mega topornym rozwiązaniem.
Dodaj if, dodaj throw.
No, w takim programie na ASD to chyba musiałbym wpisywać to throw co dwie linijki.
Co do bound to nikt tego nie używa z innej przyczyny, to instrukcja dla trybu 16-bit, indeks tablicy nie może przekroczyć 65535.
BOUND ma przecież wersję 32-bitową, a być może także i 64-bitową.
http://www.posix.nl/linuxassembly/nasmdochtml/nasmdoca.html napisał(a)
BOUND expects its second operand to point to an area of memory containing two signed values of the same size as its first operand (i.e. two words for the 16-bit form; two doublewords for the 32-bit form).
kwestia kompatybilności wstecznej z C
To jest moim zdaniem jedyny powód, żeby zostawić taką idiotyczną semantykę w C++.
Wait, bound jednak obsługuje i 32-bit. Co nie zmienia faktu, że używanie przerwań w miejscu, gdzie wystarczy prosty if jest skrajnie niewydajne.
BOUND służy do sprawdzania indeksów i generuje wyjątek, jak można się domyślić, tylko w sytuacji wyjątkowej. A więc generalnie przerwanie powinno być wywoływane sporadycznie. Mimo to i tak się tego badziewia nie używa, bo generuje przerwanie zamiast po prostu np ustawić jakąś flagę.
W procku 386 dodano instrukcję BSR, która liczy część całkowitą logarytmu o podstawie 2. Jakoś tutaj nie zrobiono już WTFa i nie inicjuje ona przerwania czy innego badziewia w przypadku liczenia logarytmu z zera, a zachowuje się lekko mniej WTFowo.
BSF searches for a set bit in its source (second) operand, starting from the bottom, and if it finds one, stores the index in its destination (first) operand. If no set bit is found, the contents of the destination operand are undefined.
BSR performs the same function, but searches from the top instead, so it finds the most significant set bit.
Gdyby to jakąś flagę ustawiało to już byłoby super.
Brak wyjątków w C to duża wada tego języka, ale można sobie je symulować:
http://www.smartango.com/articles/c-language-exception-handling
http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
othello napisał(a):
Programiści .net i javy dziwią się że w C++ (natywnym) operacja 2/0 nie generuje wyjątku. To wft czy nie?
Jestem programistą .NET i jakoś mnie to nie dziwi. WTF?