Programistyczne WTF jakie Was spotkały

0

Pierwszy raz w życiu mi się Notatnik wywalił. Nie wiedziałem że potrafi ;-)

notepad.PNG

0

Pracuję z jakimś starym kodem, w którym wiele zapytań jest pisanych nie przy wykorzystaniu ORMa, a czystego SQLa. Miałem dodać do jednej kwerendy jakiś tam nowy parametr, nic trudnego, ale po mojej zmianie pojawił się problem z N+1 zapytań. No cóż, jako że mój poziom znajomości czystego SQLa jest niski, uznałem, że coś zepsułem.

Explain zapytania niee mieści się na ekranie fhd (tak, wiem, ciekawa miara), więc zacząłem usuwać zbędne elementy. Doszedłem w końcu do momentu, w którym nie zostało już właściwie nic budzącego moje wątpliwości, a mimo to problem występował nadal.

Zacząłem w końcu porównywać z ostatnią wersją z gita, bo zwyczajnie nie wiedziałem o co chodzi, niby powinno działać, a nie działa. Zapytanie w ORMie wygląda tak:

Model.includes(:certificates).where('jakiś sql').select('inny sql').(+kilka takich doklejek).map (i tu przebiegnięcie po wynikach)

Teoretycznie to includes powinno wywołać eager loading, jednak nie tym razem. Prawidłowa wersja natomiast wygląda tak:

Model.includes(:certificate).where('jakiś sql').select('inny sql').(+kilka takich doklejek).map (i tu przebiegnięcie po wynikach)

Prawda, że duża różnica? Gdzieś na samym początku modyfikacji spluralizowałem asocjowany model (prawdopodobnie dlatego, że pierwotnie była wersja, że Model będzie posiadał wiele certyfikatów), co nie powodowało żadnego jawnego faila, warninga, nic.

Straciłem na tym dwa dni, zacząłem już tworzyć jakieś powiązane modele trzymające część danych i różne inne cuda, nigdy jeszcze tak długo nie ścigałem jednej literki.

Edit: Ok, znalazłem przyczynę, bo normalnie powinno to wywalać błąd, jak @winerfresh napisał. W modelu poza miejscem, gdzie są zebrane wszystkie asocjacje było 'has_one'), natomiast kilkaset linijek dalej (model jest całkiem spory) jest kilka radośnie dopisanych kolejnych, między innymi 'has_many' do w/w modelu). Nigdy więcej pracy z czyimś kodem...

0

Ciekawy sposób na konkatenacje stringów:

Log.Info(String.Join("", "xxx  ", id.ToString()));
0

Programowanie w kurzu, gdy za ścianą rozwalają żelbet młotem pneumatycznym, a w powietrzu unosi się zapach farb nie sprzyja jasnemu myśleniu.
Zrobiłem bodaj najbardziej klasyczny błąd w dziejach programowania - na szczęście z jego powodu straciłem mniej czasu niż na napisanie tego posta ;)

if ($fooCount = $maxFooCount) {
...
}

;-)

0

Wstaję dzisiaj rano z zamiarem dalszej pracy nad jednym z projektów, otwieram eclipse'a, rozwijam projekt i... folder 'src' jest pusty O.O zatkało mnie... jak to możliwe? Zapisywałem oczywiście systematycznie pracę, więc jakim cudem dwa pakiety mogły się pójść je#$@? O.O

0

Od jakiegoś czasu grzebie się w iOS. Dziś zainstalowałem nowego XCode 5.0.
Zepsuli interpretera Interface Builder-a. Jeśli ktoś ma aplikację z navigation controller-em to główny widoki controller'ów zostały powiększone tak, że wchodzą pod navigation bar.
Efekt jest taki, że jeśli u góry widoku ma się ważne pole tekstowe (wprowadź adres url), to w momencie kiedy chce się go wypełnić to wjedzie ono pod navigation bar i nie widać co się tam pisze.
Próba przesunięcia ekranu palcem nic nie zmienia, bo widok natychmiast wraca do pozycji, w której pechowe pole tekstowe jest niewidoczne.

W iOS xml z opisem jak wygląda UI jest konwertowany do kodu, wiec kod skopiowany pod starszą wersją XCode na nowym iOS 7 działa perfekcyjnie. Nowy tool chain ma ten bug ze wszystkim wersjami iOS (próbowałem 5.0.1 i 7.0).

Wniosek, jeśli macie aplikację z rozbudowanym UI to na razie nie instalujcie nowego XCode lub przynajmniej zostawcie sobie gdzieś starą wersję by nie musieć poprawiać wszystkich widoków.

Edit: instalacja starszego SDK nie naprawia sytuacji, najwyraźniej interpreter xml-a IB jest zintegrowany z XCode nie z SDK.

0

http://stackoverflow.com/questions/3786358/get-rid-of-ugly-if-statements
Rozwiązanie czwarte, wielomianowe. Wesoły pomysł.

0

Jeszcze raz SDL2 (SDL_image): skompilowałem źródła, próbuje skompilować przykładowy program.

Próba nr 0:

(Unable to load nananana.png! Unsupported image format)

**Nie działa**;

Próba nr 1:
Dodaje flagi do linkera, buduję projekt jeszcze raz...
Nie działa;
Próba nr2:
Zwyczajnie buduje, szukam rozwiązania problemu na internecie...
Nie działa;
Próba nr3:
Zły, rozmawiam ze znajomym (może pomoże?), chcąc pokazać mu komunikat, buduję jeszcze raz...
DZIAŁA;

1

Kod (Objective-C) senior architecta:

    if (currentPreset == 1) {
        self.preset1Button.highlighted = YES;
    } else {
        self.preset1Button.highlighted = NO;
    }

    if (currentPreset == 2) {
        self.preset2Button.highlighted = YES;
    } else {
        self.preset2Button.highlighted = NO;
    }

    if (currentPreset == 3) {
        self.preset3Button.highlighted = YES;
    } else {
        self.preset3Button.highlighted = NO;
    }

    if (currentPreset == 4) {
        self.preset4Button.highlighted = YES;
    } else {
        self.preset4Button.highlighted = NO;
    }

    if (currentPreset == 5) {
        self.preset5Button.highlighted = YES;
    } else {
        self.preset5Button.highlighted = NO;
    }

    if (currentPreset == 6) {
        self.preset6Button.highlighted = YES;
    } else {
        self.preset6Button.highlighted = NO;
    }
0

Kazdy z tych ifow da sie chociazby zastapic tym:

 self.preset1Button.highlighted = currentPreset == 1;
 self.preset2Button.highlighted = currentPreset == 2;

Mozna tez tak (pisane bez IDE):

NSArray *btns = @[self.preset1Button, preset2Button, ..., preset6Button];
for (int i = 0; i < [btns count]; ++i) {
    id btn = [btns objectAtIndex:i]; // nie chce mi sie rzutowac ale tez mozna
    [btn setHighlighted:i + 1 == currentPreset];
}

W tym kodzie jest duzo takich kwiatkow, gdzie dla kazdego buttona robi sie to samo, wiec mozna sie pokusic o metode allButtons ktora zwraca tablice taka jak powyzej. Dodanie kodu do nowego buttona wymaga tylko zmiany tej jednej metody.
Dodatkowo, tutaj nie pokazalem, ale jest tez 12 metod (2 grupy po 6 metod) ktore roznia sie tylko buttonem - wszystkie sa callbackami bioracymi jako argument sendera, i zapisuja cos / wysylaja przez socket wartosc int ktora jest, a jakze, wartoscia ktora reprezentuja (1 do 6). W iOS wszystkie UIView maja property 'tag', ktore moze przyjac wartosc int, za pomoca ktorej mozna w 1 metodzie rozpoznac ktory button zostal klikniety - mozna ja wykorzystac aby wyslac wartosc tag do socketa lub zapisac, prawda Itp. To sie da naprawde zrobic ladniej i zdecydowanie bardziej kompaktowo, i da sie lepiej czytac.

0

tak wiem, że tak można, pisałem jedynie, że nie jest to aż tak wielki niewybaczalny WTF. Sam pozbyłbym się tylko głupawych if-ów, ale nie dawałbym NSArray. Jeśli stan buttonów musiałby być aktualizowany w bardziej skomplikowany sposób to ostatecznie zastosowałbym zwykłą tablicę znaną z C.

UIButton *buttons[] = {self.preset1Button, preset2Button, ..., preset6Button};
for (int i = 0; i < sizeof(buttons)/sizeof(buttons[0]); ++i) {
    buttons[i].highlighted = currentPreset == i;
}
0

Ha, taka tablica nie przeszlaby u mnie w zespole code review - takie zasady i juz, a jakies liczenia z pomoca sizeof to juz w ogole zonk...

0

Ja wiem ze to jest normalny kod, ale w projekcie w ktorym jestem uzywa sie tylko wysokopoziomowych rozwiazan z Obj-C. Wszystko inne 'is frowned upon'. Nie wiem dlaczego, ja dopiero zaczynam w projekcie (2-gi miesiac) oraz nie mam wielkiego pojecia o programowaniu na iOS ;d

0

WTF z dzisiaj:
Za pomocą magicznej aplikacji napisanej w Excelu/VBA ludzie korzystają z bazy danych MS Access. Problem w tym że baza jest współdzielona przez ludzi z różnych krajów (ergo z różnymi ustawieniami "regional settings" w systemie). Efekt jest taki że w bazie połowa doubli ma przecinek a połowa kropkę jako separator dziesiętny. Ktoś sprytny już to zauważył i postanowił to w tym kodzie w VBA "naprawić" poprzez otoczenie wszystkich odczytów danych z bazy przez string replace które zamieniało kropkę na przecinek. Oczywiście rozwiązanie zupełnie z d**y bo dzięki niemu aplikacja działa tylko u ludzi u których to przecinek jest separatorem :D I niestety musiałem ręcznie podmieniać te wszystkie replace na wywołanie mojej trzylinijkowej funkcji która wykonuje normalną konwersję (tzn zamienia te kropki i przecinki na systemowy separator dziesiętny ;]). Gdyby kmiot który to "naprawiał" wcześniej zamiast gołego replace dał swoją funkcję, która woła replace, to fix zająłby mi minutę a nie godzinę ;]

0

Sprawa może i błaha, ale nieźle mnie rozsierdziła...

Mniej więcej miesiąc temu podczas kończenia optymalizacji kilku tysięcy linii kodu (głównie zastąpienie debilnych wywołań funkcji RTLowskich własnymi bazującymi na wskaźnikach) przyszedł czas na przetestowanie wprowadzonych zmian; Tesuję różne wariacje danych wejściowych aby sprawdzić co zostanie wyłapane jako błąd; Idzie gładko - co jest zapisane poprawnie zostaje elegancko przetworzone, a kiedy podaje błędne dane odpowiednie mechanizmy wychwytują to; Aż tu nagle podaje poprane dane wejściowe, a na wyjściu dostaję dziwactwa...

Szperam w kodzie, analizuję co i jak jest po kolei wykonywane - błędu nie widać; Debuguję kod żeby się upewnić, że wszystko jest w porządku - błędu dalej nie widać; Godzinę grzebię i dalej wszystko wygląda jak należy, a działa inaczej;

W końcu dochodzę do wniosku, że TStringList nawala; Wrzucam odpowiednie wartości (oddzielone własnym separatorem) do tej listy, po czym na koniec ta właśnie lista ma mi zwrócić jeden łańcuch przez DelimitedText (StrictDelimiter ustawiony jest na True); Okazuje się, że klasa zachowuje się bardzo dziwnie - jeśli dodam do listy jedną pustą linię, właściwość DelimitedText zwraca mi łańcuch "", czyli dwa znaki cudzysłowu... Do tego separator (czyli właściwość Delimiter) ustawiona jest na #10, więc niejak to nie pasuje do rezultatu; Testuję na Delphi7 - to samo...

Patrzę więc w źródła klasy i widzę tam takie kwiatki:

Function TStrings.GetDelimitedText: string;
var
  {...}
begin
  {...}

  If (Length(Result)=0) and (Count=1) then
    Result:=QuoteChar+QuoteChar;
end;

WTF? Kto to wymyślił? Po jaką cholerę jest to przypisywane? Najlepsze jest to, że nijak się tego pozbyć nie można, bo kompilując kod na innym komputerze klasa ta będzie wykonywać to dziwne przypisanie...

Zgłaszam tę sytuację na bug trackerze free pascala, czyli że właściwość DelimitedText daje dziwny rezultat, po czym dostaję informację, że:

Jonas Maebe (manager) napisał(a)

The output is the same in Kylix 3. Please ask questions on the mailing list instead.

Czyli mam zrozumieć, że jeden pieron czy działa dobrze/logicznie czy nie, najważniejsze że jest tak samo jak w Delphi...

0

c4100.PNG

Patrzę i patrzę i patrzę i nie kumam.

0

Skrobię sobie w eclipsie, otwieram jedną z klas z kilkoma metodami, a metod... nie ma O.O Zostały tylko komentarze dokumentujące... Myślę sobie "WTF, przecież poszedłem na moment do toalety...!" Zacząłem już podejrzewać lokatorów, że może chcieli zrobić psikusa i skasowali mi kod, ale po chwili doszedłem do wniosku, że jest to idiotyczna myśl z uwagi na fakt, że jest 2 w nocy... "Co jest grane?" - myślę. Pamiętam, że zwijałem metody i komentarze, żeby pisać następne rzeczy... "Może jakiś eclipsowy bug?" No nic. Postanowiłem zrestartować eclipse'a i voila! Metody wróciły na swoje miejsce :D

0

mam plik z logami o takiej nazwie: "Logs-30 Sep 2013 13/20/45.zip". Chcę je wgrać do bug report. Co zrobiła mi JIRA? Zmieniła slashe na dwukropek: "Logs-30 Sep 2013 13:20:45.zip".
Jak dotąd spoko, ale klikam "add" i JIRA rzuca się o to, że nazwa pliku zawiera niedozwolony znak ":" i nie pozwala mi dodać tego pliku :).

Tak zgaduje, że z jakiegoś dziwnego powodu JIRA rozpoznała godzinę w nazwie, a następnie ją zlokalizowała i stąd pojawił się ten dwukropek, który jest niedozwolony.

0

Check disk (chkdsk) pod Win7 sprawdzający kopnięty dysk:
http://i.imgur.com/ShklRaN.png
http://i.imgur.com/k96hkJ9.png

Srogo sobie poczyna...

A z innej beczki - gratulacje dla tłumacza, który "JavaScript" przetłumaczył jako "skrypty Java" ;-)
http://i.imgur.com/ik34qfF.png

1

Nie wiem jeszcze, czy to programistyczne czy sprzętowe WTF, ale podejrzewam bardziej Intela, bo takie numery już im się zdarzały.

Są bowiem sobie dwa zupełnie nieadekwatne dziś do zadania komputery:

1. Celeron 220	512k cache, 1.20 GHz, single core, produkcja 2007 r.
- 2 GB RAM, Windows XP x86
2. Atom N570	1M cache, 1.66 GHz, dual core + hyper threading, produkcja 2011 r.
- 2 GB RAM, Windows 7 x86

A zadaniem jest przekodowanie filmu: zmiana kodeka audio i video, zmiana rozdzielczości, deinterlace'ing.

Soft jakiego zawsze używam to: Virtual Dub, Avisynth, kodeki Xvid i Lame MP3.

I na czym fakap polega? Spodziewałem się, że drugi komputer będzie co najmniej trzy razy szybszy. Tymczasem "Video rendering rate":

1. 11 fps
2. 8 fps

Jak to jest, że procesor o 4 lata młodszy, o wyższych parametrach pod każdym względem, mimo zajętości procka 100% (więc działa multi-threading) jest mimo to wolniejszy?

9

Serwery NTP (do synchronizacji czasu) które odrzucają połączenie, bo lokalna data się nie zgadza. Noż kurna, przecież po to korzystam z serwera, by dostać dobrą datę i czas, zaoszczędzając te 10 kliknięć na ręcznym ustawianiu.. :|

0

explorer.exe miał ciężkie chwile po których nie mógł dojść do siebie. Pomogło dopiero uśmiercenie go...

user image

Dodam, że zjadł taką ilość ramu na systemi 32-bitowym.

0

@Rev Przyczyną było zaznaczenie ~65k plików w folderze, kliknięcie PPM, a następnie 7-Zip -> Dodaj do archiwum. Zresztą po samym wejściu do folderu zużycie ramu wzrasta do ~260 mb :P

No i dla takich plików jakie tam są (b. dużo małych) wyrównanie danych jest dosyć widoczne (zajmują na dysku praktycznie 100x więcej niż w rzeczywistości).

0

Miałem wolnego 15,075GB - odinstalowałem z 8 komponentów Windows 7 w tym wszystkie wbudowane gry, narzędzia wyszukiwania, windows media player/dvd maker/ etc etc etc
Poprosił o reset, poleciały procenty kończenia konfiguracji..
Teraz mam wolnego 15,003GB :|

Co ciekawe, po odinstalowaniu Windows Search z Menu Start znika możliwość filtrowania programów :)

0

Zawsze do benchmarków podchodziłem z rezerwą. Tym bardziej do takiego PyPy które szczyci się tym, że jest nawet 6 razy szybsze od CPythona. Ale potrzebowałem zoptymalizować pewien kod (górny limit na czas działania to było 300 sekund), który już był zoptymalizowany do granic możliwości więc postanowiłem sprawdzić ile można zyskać zmianą interpretera ;]
Czas działania - 1000 sekund
Czas działania po 4 godzinach rozkminiania nad optymalizacjami i profilowania kodu (przy założeniu żeby nie psuć czytelności kodu) - 700 sekund
Czas działania zoptymalizowanego kodu na PyPy - 130 sekund

Oczywiście wszystko ma swoje plusy i minusy ;] Nie ma na przykład sensownego wsparcia na numpy w PyPy i musiałem trochę rzeczy sobie własnoręcznie zaimplementować ale mimo wszystko, to jest ponad 5 razy szybciej! Ten JIT to jednak nie jest ściema :D

0

Dla mnie jednym wielkim WTF jest programowanie na Androida - kiepska dokumentacja, pelno bzdur, fragmentacja i tysiace urzadzen do testowania a i tak zawsze jakis piksel sie wyjebie (argh!), lipne API (jak np. podawanie kryteriow filtrowania w contentproviderach jako string z sql where), emulator (WTF?!), ant i eclipse (ale to sie zmienia, gott sei dank), mnostwo (naprawde mnostwo) bugow, gotchas i glupot takich jak ta (oficjalna dokumentacja):

Every Android-compatible device supports a shared "external storage" that you can use to save files. This can be a removable storage media (such as an SD card) or an internal (non-removable) storage.

Czyli external storage moze byc internal storage. WTF? Naprawde musieli przeciazac te 2 pojecia? To nie mogli tego nazwac private / shared?

Ogolnie wczesniej nie programowalem za wiele na Androida, ale ostatnio robie coraz wiecej i strasznie mnie jako platforma dle devow rozczarowuje.

0

@mućka nie spinaj, JetBrains pracują nad IntelliJ dla Androida (już ponoć w becie IntelliJ13 trochę tego wrzucili) ale póki co jest chyba wersja 0.2 dopiero. Myśle że jak skończą to będzie się klepało bardzo przyjemnie ;)

0

Wiem, sam uzywam IDEA i mam wersje Enterprise czy jak ona sie nazywa, do tego ich plugin do Androida (a z tego co czytalem to ten plugin i android studio czy jak tam to ten sam kod?), ale w pracy uzywam Eclipse (wymog projektu, ale walcze coraz zacieklej), no i od poczatkow Androida zawsze byl uzywany Eclipse - ja sie pytam, kogo tak pojebalo?
Wybor anta zamiast mavena rozumiem, ale wiaze nadzieje z gradle (ale i ten ma duzo problemow, ktore jednak da sie obejsc za pomoca grooviego). Ale tak ogolnie, to programowanie na Andka ssie jaja.

3

Ja wiem, że to nie dział flame, ale...

Ale tak ogolnie, to programowanie na Andka ssie jaja.

  • to nie android ssie jaja, a Twoja wiedza odnośnie tej platformy. Nie piszę tego złośliwie, bo jak zaczynałem to miałem bardzo podobne obiekcje. Teraz już nie mam bo na pytania zadane przez Ciebie jestem w stanie odpowiedzieć.
    1.Co do emulatora, to nie jest żaden WTF, zainstaluj Genymotion albo HAXM jak masz procesor intela. Emulator chodzi wtedy szybciej niż przeciętny smarfon/tablet.

Czyli external storage moze byc internal storage.

  • mylisz pojęcia pomiędzy internal storage, a pamięcią wbudowaną (to są dwie różne rzeczy!). Do tego dochodzi jeszcze karta sd, więc telefon może mieć 3 rodzaje pamięci. Wołasz getExternalStorageDirectory i jeżeli nie jest null to nie obchodzi Cię czy jest to karta sd, czy pamięć wewnętrzna (nie internal storage).

piksel sie wyjebie

  • tutaj kłania się nauka tworzenia layoutów (najtrudniejsza część nauki jeżeli chodzi o androida). Do tego tworzysz specjalne foldery np. layout-land-small, layout-sw600dp, values-portrait-xxlarge itp. itd. i wszystko wygląda jak trzeba.

jak np. podawanie kryteriow filtrowania w contentproviderach jako string z sql where

  • Naprawdę? To nie lepiej skorzystać z GreenDao i wszystko robić na obiektach np. tak : qb.where(PersonDao.Properies.Id.eq(10)).build().unique() ?

mnostwo (naprawde mnostwo) bugow, gotchas i glupot

  • bugów trochę jest, ale nie mnóstwo. Często spotykam się w tej platformie z zarzutami o bugi, a okazuje się, że programista stosuje złe rozwiązanie uparcie twierdząc, że to bug.

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