Programistyczne WTF jakie Was spotkały

Programistyczne WTF jakie Was spotkały
9

Dzieciak uczy się od miesiąca (!!!) języka niszowego, przeznaczonego do wąskiej dziedziny, nie zna żadnego innego języka - pisał podstawy w c++, czyli właściwie nic nie wie, a pisze na forum jak jakiś znawca :D

Gimnazjum, czy liceum?

Laflx
nie zapominaj jeszcze o 4 GL
bakeraw2
Hahaha.. teRroRysta :)
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0

Chciałem mieć pseudo element który będzie pod rodzicem. Wyczytałem sobie

An element with greater stack order is always in front of an element with a lower stack order.

Wytłumaczy mi ktoś dlaczego pierwszy przykład (1 is lower than 2) nie działa, ale drugi (-1 is lower than 2) już tak?

Kopiuj
        h1.fancy-shadow {
            position: relative;
            z-index:2;
            color: #10BD00;
        }
        h1.fancy-shadow:before {
            position: absolute;
            z-index: 1;
            font-size: 1.3em;
            font-family: "Vivaldi";
            opacity: 0.2;
            color: black;
            content: 'smth';
        }
Kopiuj
        h1.fancy-shadow {
            position: relative;
            z-index:2;
            color: #10BD00;
        }
        h1.fancy-shadow:before {
            position: absolute;
            z-index: -1;  /*  works :|  */
            font-size: 1.3em;
            font-family: "Vivaldi";
            opacity: 0.2;
            color: black;
            content: 'smth';
        }
Koziołek
pobaw się position to zrozumiesz ;)
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:10 dni
12

W związku z naszym spammeRem przeglądałem dokumentację i znalazłem takie coś:

ca31bba9b7.png

Co się wydarzyło w tym czerwcu-sierpniu? Lafix odkrył R, że pobrano bibliotekę 25000 razy?


Koziołek
Na Courserze była runda kursów o programowaniu w R i data science.
hauleth
To by trochę wyjaśniało :D
satirev
  • Rejestracja:prawie 14 lat
  • Ostatnio:około 4 lata
5

Dzisiaj natrafiłem na pewien problem z rozpakowywaniem paczki szablonu zmiennoargumentowego, który jak dla mnie jest wtf. Szukałem i zastanawiałem się nad przyczyną takiego stanu rzeczy ale nie widzę racjonalnego wytłumaczenia dlaczego nie mogłoby to działać (zostać zaimplementowane). Tyle tytułem wstępu, teraz rzeczony wtf.

Przykładowo mamy, taki kod jak poniżej:

Kopiuj
template <typename... Args>
void foo(Args... args)
{
    [args...](){};   
}

int main()
{
    foo(4, 4.5f, "asdasdsa");
    return 0;
}

Super wszystko działa. Ale załóżmy teraz, że chcielibyśmy obsługiwać poprawnie r-value i l-value. No to nic prostszego, perfect frowarding i capture by forward panie!

Kopiuj
#include <utility>

template <typename... Args>
void foo(Args&&... args)
{
    [args = std::forward<Args>(args)...](){};   
}

int main()
{
    foo(4, 4.5f, "asdasdsa");
    return 0;
}

I co?
error: expected ',' or ']' in lambda capture list [args = std::forward<Args>(args)...](){};
Z jakiś przyczyn nie można zachować rozpakowanej paczki w zmiennej.

Workaround to zforwadowanie paczki do tuple:

Kopiuj
template <typename... Args>
void foo(Args&&... args)
{
    [args = std::std::forward_as_tuple<Args...>(std::forward<Args>(args)...)](){};   
}

Btw, trochę w tym temacie, a trochę poza - jeśli byłby ktoś zainteresowany to mogę skrobnąć artykuł na temat tego jak napisać fajny, generyczny singleton w C++ przy użyciu tag dispatchingu, tak by zachować lazy initialization + wymusić initialization, tak gdzie trzeba. Jak by znalazł się ktoś zainteresowany niech da znać via komentarz/PM.

Zobacz pozostałe 44 komentarze
Endrju
Funkcja składowa i wskaźnik. To rozwiąże Twoje problemy. :-P Wiem, że lambda jest taka super pr0, ale jeżeli w jakimś zastosowaniu powoduje problemy, to po to istnieją te "klasyczne" mechanizmy.
vpiotr
Dla mnie "variadic template" = szczytowe osiągnięcie twórców C++ w dziedzinie nieczytelności składni. Możliwe że przebija nie tylko każdą inną konstrukcję w C++ ale i we wszystkich innych językach też. Może poza składnią wskaźnika na funkcję w C :)
spartanPAGE
Mi tam się podoba :P Oznacza tyle ile można się domyśleć
satirev
@vpiotr, rozumiem, że ellipsis operator też uważasz za nieczytelny? Poza tym, jak porównamy formę zapisu variadic template z boost variadic macro to chyba nikt nie powie, że ten drugi sposób jest czytelniejszy.
vpiotr
@Satirev: Elipsis też potrafi zadziwić: "void SampleFunction(Arguments......)". A Boost jak to biblioteka, zwykle jest mniej czytelny niż rozwiązania wbudowane w język.
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
2

Workaround z GCC do MSVC 6 żeby namespace'y się zgadzały...

Kopiuj
	typedef ::size_t size_t2;
	#define size_t size_t2
edytowany 1x, ostatnio: alagner
ShookTea
  • Rejestracja:około 12 lat
  • Ostatnio:prawie 6 lat
  • Lokalizacja:Wrocław
  • Postów:629
5
winerfresh napisał(a):

W związku z naszym spammeRem

IMHO ostatnio nadużywa się słowa "spam". Przecież nie znaczy ono "flame" lub coś w tym guście (jak to się ostatnio używa), lecz natrętną reklamę.
Och, wait. Zwracam honor.

:P


Marooned
Często też spammerem nazywają floodera, zupełnie bez sensu.
10

Przyszła do nas aplikacja po testach penetracyjnych, do poprawy, bo oryginalna firma działająca 7 lat na rynku nie umiała poprawić banalnych SQLi i XSSów wykrytych w czasie audytu. Niektóre identyfikatory zmienione, zamysł kodu ten sam.

To jest diff kodu przed i po "poprawkach bezpieczeństwa". O samej jakości nie wspominam.

#1 - Escaping parametru przed sprawdzeniem, czy w ogóle istnieje - żeby nam ifa nie injectnęli...

Kopiuj
- 	if (empty($_GET['id'])) session_start();
+	 if (empty(neutralizeSQL($_GET['id']))) session_start();

#2 - Podmiana bezpiecznego kodu na niebezpieczny

Kopiuj
- 		$result = @mysql_query("SELECT * FROM tbl_firma_kategoria WHERE left_id='".intval($_GET['cat_id'])."'");
+	 	$result = $db->query("SELECT * FROM tbl_firma_kategoria WHERE left_id=".$_GET['cat_id']." LIMIT 1");

#3 - Cast na inta i escaping

Kopiuj
- 	$result2 = @mysql_query("SELECT * FROM tbl_firma_galeria WHERE user_id=".$firmaDane['user_id']);
+	 $result2 = $db->query("SELECT * FROM tbl_firma_galeria WHERE user_id=".neutralizeSQL(intval($firmaDane['user_id'])));

#4 - Zobaczył w dokumentacji operator trójargumentowy i zaczął nim szpanować w losowych miejscach, zamiast zrobić ifa

Kopiuj
		$redir = (isset($redir)) ? base64_decode($redir) : false;
		$redir = (!empty($redir) && check_url(CONFIG_SITE_URL.'/'.$redir)) ? $redir : false;

#5 - SQL injection w wyrażeniu bardzo poważna sprawa

Kopiuj
if (intval(neutralizeSQL($_GET['mode'])) == 1) {
   // ...
}

#6 - Tylko nie myślcie, że neutralizeSQL to jakaś sensowna funkcja
Neutralizacja HTML do zapytania SQL, szczena mi opadła do samej d**y.

Kopiuj
function neutralizeSQL($var, $kind='tekst') {
	global $db;

	$zmienna = htmlspecialchars(strip_tags($zmienna));

	switch ($rodzaj) {
		case 'numeric':
			return $db->real_escape_string(str_replace(' ', '', str_replace(',', '.', $zmienna)));
		break;
		case 'text':
			return $db->real_escape_string($zmienna);
		break;
	}
}

(mała poprawka na prośbę autora - msm, i dzek)

#7 - Hashowanie haseł
Oczywiście to substr($x, 0, 2) rozpieprzy hasha typu $2a$08$ albo $5$rounds=5000$.

Kopiuj
			$dbpasswd=$setinfo['usr_password'];
			$non_crypt_pass = $usr_password;
			$old_crypt_pass = crypt($usr_password,substr($dbpasswd,0,2));
			
			$new_pass = $uzytkownikClass->posol($usr_password);

Gdzie funkcja posol($x) to:

Kopiuj
	//posolenie hasła
	function posol($haslo) {
 
		#$salt = "4f4d34kjb7574sdoias1190ic3"; //przynajmniej 22 znaki

		#return crypt(md5($haslo), '$2a$10$'.$salt);

		return md5($haslo);

	}

Więc generalnie hasła hashowane czystym MD5 bez soli.

#8 - Register globals by design

Kopiuj
extract($_GET, EXTR_OVERWRITE);
extract($_POST, EXTR_OVERWRITE);
extract($_COOKIE, EXTR_OVERWRITE);

Nawet nie sądziłem, że coś takiego w stdlibie PHP w ogóle istnieje i ktoś może tego używać.
W którymś powyższym kodzie parametr $redir pochodził oczywiście bezpośrednio rozpakowany z $_GET. Problem zaczyna się, kiedy chcielibyśmy prześledzić skąd się dana zmienna wzięła. Tego czasem nie wiedzą sami developerzy:

Kopiuj
if($_COOKIE['foo'] == $foo) {
   // ...
}

#9 - Ciastko "uzytkownik"
Autoryzacja polega na wysłaniu użytkownikowi ciastka uzytkownik w składzie:

Kopiuj
id,login,hash_hasla_md5

Audyt oczywiście to wykazał i zalecenie było, żeby użyć losowego tokena, bo dowolny SQL injection umożliwiający na odczyt bazy umożliwia w banalny sposób craftowanie takich ciasteczek. Zalecenie oczywiście od góry do dołu olane.

Próbowaliśmy już to zrefaktoryzować i przenieść ciastko do wewnątrz sesji PHPowej - bo ona również jest startowana. Wykonanie niektórych akcji w systemie powodowało wylogowanie z dość enigmatycznego powodu. Po paru godzinach grzebania okazało się, że niektóre moduły robią np. coś takiego:

Kopiuj
$_SESSION = false;

#10 - Uwaga intruz
Jak komuś jeszcze nie wybuchł mózg to dobiję w ostatnim punkcie.

Kopiuj
	if (empty($_POST['aid']) OR empty($_POST['pwd'])) {
		$admintest=0;
		$alert = "<html>\n";
		$alert .= "<title>UWAGA INTRUZ!!!</title>\n";
		$alert .= "<body bgcolor=\"#FFFFFF\" text=\"#000000\">\n\n<br><br><br>\n\n";
		$alert .= "<center><img src=\"images/loading.gif\" border=\"0\"><br><br>\n";
		$alert .= "<font face=\"Verdana\" size=\"+4\"><b>Prosimy opuścić tą stronę!</b></font></center>\n";
		$alert .= "</body>\n";
		$alert .= "</html>\n";
		die($alert);
	}

Lepsze decyzje projektowe podejmowałem w gimnazjum. Przypominam, że firma która to zrobiła działa na rynku od 7 lat i ma się dobrze. Mam to poprawnie połatać. Nie wspomniałem jeszcze, że wejście na stronę główną generuje około 330 zapytań, niektóre lecą z pętli.

Jak nie dam znaku życia, to znaczy że utknąłem w ulubionym pubie. Over.

edytowany 4x, ostatnio: dzek69
B8
Uwaga intruz :D Dobre.
0

Przez kod od obsługi koszyka przewija się...

Kopiuj
$koszykClass->aktualizyjKoszyk(...);

Pierwszy raz w życiu stwierdzam, że ten kod to po prostu brute force. Jeszcze jeden fajny kawałek:

Kopiuj
function zrobCos($arg, $arg2) {
   // jakieś operacje na $arg i $arg2

   $arg = $_COOKIE['arg']; // totalnie zmieniamy kontekst, lol

   unset($arg); // na sam koniec funkcji unsetujemy zmienną - po co, czemu? :O
}

Czy ktoś tam umiał programować? Rozumiał koncepcję funkcji, pętli? To pytanie pozostaje otwarte.

2

Znaleźliśmy funkcję wołającą zapytania w pętli O(n) używaną w nestowanej pętli O(n^2).

To tłumaczy 330 zapytań po wejściu na stronę główną...

Shalom
Widzę że klasyczny problem n+1 selectów przeszedł właśnie na nowy poziom :D
no_solution_found
  • Rejestracja:prawie 18 lat
  • Ostatnio:dzień
0

@up to jeszcze nic. Ja przejąłem raz projekt CRM gdzie na podstronie było generowane 1000 zapytań, a na kolejnej prawie 2 tyś. A klient narzekał na słabą wydajność aplikacji :)


2

Helena, mam zawał.

kod.png

  • kod.png (72 KB) - ściągnięć: 286
Zobacz pozostały 1 komentarz
Shalom
Nasuwa się pytanie "w czym oni to pisali" bo jak widać na obrazu PHPStorm (WebStorm?) wyłapuje to w swojej statycznej analizie kodu... ;]
Sarrus
W notatniku chyba...
Demonical Monk
@Shalom: Niektóre ficzery analizy musiałem wyłączyć, bo edycja kodu zawieszała phpSztorma na minutę albo pięć :D Nowiutki laptop z Core i5 i 8GB RAM...
Demonical Monk
@Sarrus: Zdarzało się, że developer wysyłał klientowi patcha (oczywiście sam plik do podmiany) który rozpieprzał wszystko do tego stopnia, że nie dało się zalogować, albo wyskakiwały jakieś warningi ;]
Azarien
wystarczy zmienić nazwę funkcji, np. zipCodeIsBad ;-P
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0

Korzystam w javie z biblioteki która ma obrabiać obrazki. Nie jestem pewien czy tylko ta czy wszędzie tak jest, ale u mnie jeżeli mam czarno biały obraz, i ustawie całemu obrazowi png Transparency: 255. To mimo że nie ma tam nic widocznego, to i tak taka funkcja (która działa jak różdżka do wybierania kolorów) rozróżnia np rgba(255,255,255,0) i rgba(0,0,0,0).

Wydaje się logiczne, ale jednak przezroczysty to przezroczysty.

PS; Co dziwne, jeżeli wezmę kolor z jednego miejsca ("jasna" przezroczystość) i spróbuję wylać farbę na inne ("ciemna" przezroczystość) to wyjściowy plik jest taki sam (nawet sprawdziłem checksumy md5). Po wczytaniu sytuacja z funkcją-różdżką powtarza się.

edytowany 4x, ostatnio: Riddle
Olamagato
Przecież przezroczystość niczego w obrazie nie zmienia w stosunku do samego siebie. Alfa ma tylko znaczenie w stosunku do tła, albo innego obrazu. Kolory pikseli są nadal kolorami bez względu na to jaka jest przezroczystość. Gdzie tu WTF? A poza tym jedynym obrazem uprawnionym do nazywania czarno-białym jest obraz 1-bitowy, ewentualnie greyscale z 7-bitową przezroczystością i bitem na piksel. Wszystkie inne są kolorowe, a ich zawartość (czarny i biały) nie definiuje formatu.
Marooned
Mody do Quake dodające np. nowe celowniki zazwyczaj miały pliki .tga, które w programie graficznym były całe białe. Dopiero właśnie przeźroczystość uwidaczniała kształt celownika.
ShookTea
@Marooned w programie graficznym Paint? :P
Azarien
@Marooned: czy to była tylko taka konwencja, czy wymóg engine'u? tzn. czy celownik mógłby być np. kolorowy?
Marooned
To było, zanim poznałem Malatyńską. Nie pamiętam ;)
NO
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 6 lat
9

Na drugim semestrze informatyki miałem zastępstwo na programowaniu w C z jakimś doktorantem, proste programiki konsolowe, zalecał dawanie samych if. Zrobiłem operator wyrażenia trójargumentowy:

Kopiuj
zmienna = warunek ? wyrazenie1 : wyrazenie2;

Dziwił się, że tak można i się z tym jeszcze nie spotkał, ale skoro działa to chyba może być. Ech :)

`dodanie znaczników i ``` - @furious programming

edytowany 2x, ostatnio: flowCRANE
Riddle
U mnie było tak non-stop. Przez pierwszy miesiąc miałem ochotę tłumaczyć nauczycielom co do czego służy ale potem zaniechałem.
dam1an
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa
  • Postów:1589
8

@up Ja zajęcia z podstaw Javy miałem z takim doktorem który chyba dość dawno nie napisał żadnego programu. Pokazywał nam slajdy z podstawami. Pętle, ify itp, jednocześnie je omawiając. Doszedł do wyrażenia trójargumentowego. Zatrzymał się na tym slajdzie. Czyta opis przez chwilę. W końcu mówi coś w stylu "A no to jest taki operator warunkowy dla zaawansowanych, tego nie będziemy używać"
Inna sytuacja, ten sam doktor. Każdy miał sobie wymyślić program który napisze na zaliczenie półroczne w Javie. Ktoś tam mówi że chciałby napisać klienta e-mail. Tłumaczy doktorowi jak to ma działać, że będzie można z programu odbierać pocztę, wysyłać maile itp. Doktor na to "Wysyłać? Nie bo to .. spam .. FBI .." Tu właśnie nie pamiętam, ale coś gadał o spamie, o FBI, CIA albo NSA że to się może im nie spodobać czy coś w tym stylu.
A z kolei inny wykładowca ciągle na .Net mówił kropka-net.
Ehh jeszcze tylko miesiąc tych studiów.

edytowany 1x, ostatnio: dam1an
Sebastiano
"A no to jest taki operator warunkowy dla zaawansowanych, tego nie będziemy używać" - prawie sie popłakałem ze śmiechu:D Powiem Ci że u mnie podobne akcje były, lecz na inzynierii oprogramowania;/
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Tuchów
  • Postów:12163
0

Ja zajęcia z podstaw Javy miałem [...] W końcu mówi coś w stylu "A no to jest taki operator warunkowy dla zaawansowanych, tego nie będziemy używać"

W sumie coś w tym jest, jednak jeśli to były zajęcia z podstaw programowania, to lepiej najpierw nauczyć się tworzenia zwykłych warunków, zanim zacznie się stosować skrócone wersje.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Riddle
Fajniej jednakby było gdyby osoba ucząca miała pojęcie na temat tego co warto a czego nie warto uczyć (zanim zdecyduje o tym że coś jest zaawansowane bądź nie). PS; no bo błagam,nauczyciel który rozpoznaje operator trójargumentowy po tym jak dopiero przeczytał opis? PS2; słowo klucz: "nauczyciel", osoba która powinna uczyć (a nie uczyć się).
flowCRANE
Masz rację, jednak pamiętaj, że nauczyciel sam też musi się cały czas uczyć; No tylko nie w omawiany sposób i nie takich rzeczy;
Olamagato
  • Rejestracja:ponad 16 lat
  • Ostatnio:3 dni
  • Lokalizacja:Polska, Warszawa
  • Postów:1058
3

@up Tylko, że to nie są żadne skrócone wersje, lecz wręcz odwrotnie. Wyłącznie dzięki temu operatorowi można w językach o składni C pisać wyrażenia funkcyjne, no i kod jest zwyczajnie czytelniejszy (ten dobrze napisany, z właściwymi nazwami funkcji/metod/zmiennych).
Naturalnym rozwinięciem tego podejścia do wyrażeń są wyrażenia łańcuchowe, które pozwalają zapisać kod programu w postaci funkcyjnej. Czyli to, co obecnie jest modne... :)

A to, że na polskich uczelniach zostają doktoranci bo są zbyt ciency, żeby pójść do dowolnej firmy, to tylko pokazuje, że na polskich uczelniach niczego nie można się nauczyć. W sumie to korzystne nawet bo płace rosną. :D


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
fasadin
mylisz sie i co do skladni (ze czytelniejsze) i co do nauczania
hauleth
Czytelniejsze to by było, gdyby if był wyrażeniem a nie blokiem (vide Lispy, Ruby, Rust, Scala). Operator trójargumentowy w Javie jest raczej problemem niż jego rozwiązaniem (dodali go chyba tylko z sentymentu).
Olamagato
Nie mogę się mylić co do własnych odczuć bo to niemożliwe (dla mnie drabinki ifów, na dodatek jeszcze z obowiązkowo napieprzonymi klamrami, to jest po prostu koszmar :)) Natomiast mogę być w mniejszości (może nawet bardzo) w stosunku tych którzy ify nawalone klamrami w formatowaniu standardowym uważają za czytelniejsze. :)
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Tuchów
  • Postów:12163
0

@Olamagato - to skrócone wersje warunków; Prosty przykład:

Kopiuj
if(intValue == 5)
  intResult = 4;
else
  intResult = 18;

niektórzy lubią też grupować pojedyncze wyrażenia klamrami:

Kopiuj
if(intValue == 5)
{
  intResult = 4;
}
else
{
  intResult = 18;
}

Powyższe można skrócić do czytelnego jednolinijkowca:

Kopiuj
intResult = intValue == 5 ? 4 : 18;

więc operator ten służy jak najbardziej do skracania kodu przy tak prostych warunkach; A nawet stwierdziłbym, że przydaje się on tylko i wyłącznie do przypisań, ewentualnie jeszcze do zwracania rezultatu funkcji;

Poza tym można spokojnie pisać kod, znając zwykły if, ale trójargumentowca nie; W drugą stronę to nie działa - często obsługuje się tylko jeden stan warunku (prawdę lub fałsz), czego operatorem trójargumentowym nie można zastąpić;

Wyłącznie dzięki temu operatorowi można w językach o składni C pisać wyrażenia funkcyjne

Nawet jeśli to prawda, to zauważ, że na zajęciach z podstaw programowania ludzie i tak nie mają pojęcia o tym, o czym się do nich mówi (chyba że ktoś wcześniej programował); Naturalne jest uczenie się stopniowo, od najbardziej podstawowych rzeczy, a zwykły warunek if jest elementem bardzo podstawowym; A jak już ogarnie się sens używania instrukcji warunkowych, to wtedy będzie można prezentować dodatkowe rzeczy na ich temat, w tym operator trójargumentowy.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 2x, ostatnio: flowCRANE
n0name_l
czego operatorem trójargumentowym nie można zastąpić;, można, tyle że jest to brzydkie i bezsensowne.
flowCRANE
Dobrze, że nie napisałem nie da się ;)
Olamagato
Niestety to nie są skrócone wersje warunków. If-else nie jest instrukcją wyrażeniową (r-value), a tylko odgałęzieniem sterowania. Niczym więcej. To jest właściwy odpowiednik: private int tempExpression(int arg) { int result; if(arg == 5) result = 4; else result = 18; return result;} intResult = tempExpression(intValue); gdzie tempExpression musiałoby być metodą generowaną w locie.
Laflx
w R byłoby tak: Result<- as.integer(if(Value==5,4,18))
Marooned
Ternariusza można też użyć do kaskadowego łączenia metod, np: $(element).foo()[zmienna ? 'bar' : 'baz']().abc() ale to czyste zło ;-)
Olamagato
  • Rejestracja:ponad 16 lat
  • Ostatnio:3 dni
  • Lokalizacja:Polska, Warszawa
  • Postów:1058
1

@up Polecam napisanie za pomocą samych ifów poniższej procedury (z kodu produkcyjnego):

Kopiuj
	private void moveFocusForward(boolean forward) {
		List<Node> nodes = queryPane.getChildren().stream()
			.filter(node -> node instanceof TextField).collect(Collectors.toList());

		Iterator<Node> it = nodes.iterator();
		for(Node previous = null, next; it.hasNext(); previous = next) {
			next = it.next();
			if(next.isFocused() && (forward ? it.hasNext() : previous != null)) {
				(forward ? it.next() : previous).requestFocus();
				return;
			}
		}
	}

Dla mnie brak możliwości użycia instrukcji wyrażeniowej, to w wielu wypadkach kompletnie nieczytelny kod (a to co widać, jest już i tak wystarczająco skomplikowane). Moim zdaniem nie da się takiego kodu napisać prościej i czytelniej nie tracąc nic z obecnej funkcjonalności. Ale może ktoś mnie zaskoczy? :)


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 1x, ostatnio: Olamagato
Zobacz pozostałe 6 komentarzy
Olamagato
11 prostych linijek na 114 rozwleczonego kodu? Nie. Ostatnie co można powiedzieć, to to że 114 wierszy pozwala zrozumieć jego algorytm od jednego spojrzenia. :) Moim zdaniem kod ma być czytelny. Pięć stron kodu robiącego prawie nic nie jest czytelne. W ogóle. No chyba, że w założeniu piszemy w assemblerze albo w bytecode. :)
msm
Btw. jak już rozmawiamy o tym kodzie, to parametry boolowe do metod są często uważane za code smell (i/lub sugerują łamanie SRP) - http://programmers.stackexchange.com/questions/147977/is-it-wrong-to-use-a-boolean-parameter-to-determine-behavior - z tego co pamiętam na ten pomysł wpadł (aka pierwszy opisał) Martin Fowler (http://martinfowler.com/bliki/FlagArgument.html).
n0name_l
@Olamagato 114, z których 30 zajmują klamry, 10 fixanie poronionego boola, 20 klasa, która może być użyta w 500 przypadkach a nie w jednym, następne 10 na zrobienie pseudoTextFielda i kod metody, który ma coś robić jest napisany prawie jak książka. No ale niektórzy wolą pisać dziwne wyrażenia, bo mogą się pochwalić skutecznością eliminacji enterów ;-)
Olamagato
@msm - tak, oczywiście bo nigdy nie wiadomo co reprezentują. Znam to zastrzeżenie. Jednak takie użycie jest jak najbardziej zgodne z tym wyjątkiem, który jednoznacznie identyfikuje intencję użycia takiego argumentu. To praktycznie ten sam przypadek co setter. @n0name - szkoły, które bezwzględnie i bezmyślnie rugują jakieś typy danych, konstrukcje sterowania i paradygmaty są dla mnie passe. To jest praktyka, a nie teoria jak napisać "idealny", ale często nieefektywny kod, w który się trzeba wczytać, żeby zrozumieć o co chodzi. Może jestem w mniejszości, ale trudno. :)
KR
Boole są code smell tylko w językach, które nie mają nazywania argumentów aktualnych. Np. Java lub C++. W Scali ani R nie są.
Trebuh
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 4 lata
  • Lokalizacja:okolice Łodzi
8

Trafne komunikaty to jak widać sprawa drugorzędna.
trafne_komunikaty.PNG


GG: 10101100010110000100011101 (BIN)
"Nie wszystko napisane w internecie jest prawdą" - Józef Piłsudski.
Zobacz pozostały 1 komentarz
Trebuh
Manager plików na jednym z hostingu ;p
flowCRANE
@Trebuh - wszystko muszisz wiedzieć? ;P
Koziołek
Fajne. Mi się podoba, bo dobrze opisuje co się dzieje.
Sebastiano
Super:) Musze taką obsługę wyjątków zacząc stosować u siebie:D
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
1

Nowy projekt. No prawie nowy, bo klient podsyła nam to co spłodził jego dział IT za pomocą zip+email. Odpalamy Sonara

  • 48 plików
  • 55 klas
  • prawie 9k linii kodu...

Sonar wyliczył Technical Debt na 25 dni... 708 issues... w tym np coś takiego:

Kopiuj
if (dataSource == null) {
   synchronized (connectionJndiName) {
     //.... 
  }
}

Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
Shalom
A są jacyś faworyci z kosmicznym cyclomatic complexity? Czy wszystkie te klasy są mniej więcej "równie słabe"? ;)
Koziołek
Jedna ma 23... ale to jakiś dziwny pseudo test w postaci programu, który czyta jakiegoś excela z bazy i go parsuje...
fourfour
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 9 lat
  • Postów:627
0

Może nie do końca programistycznie, ale... zachciało się przez Windows Update nowego .Net 4.5.2, jednak wciąż instalacja poprawki kończyła się błędem. Dziwnym jakimś, bo bez informacji w necie na jego temat. Pobrałem paczkę do instalacji wspomnianego frameworka, niecałe 70 MB. Uruchomiłem i.. już znam przyczynę, dla której był problem z instalacją...

user image

:)

Zobacz pozostały 1 komentarz
Azarien
to jest chyba tylko na czas instalacji, na pewno u mnie nie ubyło tyle miejsca a aktualizowałem wczoraj.
Olamagato
Pewnie musi rozpakować, albo usunąć jakieś wcześniejsze poprawki. Dla mnie właśnie dlatego dotnet jest słaby. Co głupia poprawka, to pół giga mniej. A te wcześniejsze pół giga nadal zajmuje miejsce bo przecież ktoś może korzystać ze zwalonego kodu... To już JRE/JDK poszło w przeciwną stronę i domyślnie usuwa wszelkie stare i nadmiarowe wersje.
Azarien
@Olamagato: począwszy od wersji 4.0 każda kolejna zastępuje poprzednią. ale nie sprawdzałem jak to jest z miejscem na dysku.
Olamagato
Formalnie tak, ale system mi puchnie co każdą aktualizację dotneta. Nie wnikam głębiej jednak. :)
wasiu
Dlatego nowy .net jest przepisany by być bardziej na moduły podzielony, acz fakt, na serwerach to pewnie całego się będzie dalej instalowało :) Ale przyszłość zapowiada się kolorowo dla mac'ów, android'ów czy linux'ów :) W końcu oficjalne wsparcie będzie :)
0

Wiem, że to ani nowe, anie programistyczne, tylko analityczne, ale wtf jest:
Android używa MTP zamiast normalnego przesyłania danych do kompa.
Wszystkie pędraki, stary telefon, a nawet samochód mogę podmontować normalnie, ale już android który jest linuchem wybrał sobie jakiś standard ms.

Marooned
Jestem ciekaw, czy info z linku ma związek z tym, że mój Android (2.3.3) nie ma dostępu do karty SD przy "temporary root". Tzn. żadne aplikacje zainstalowane na SD nie działają.
Wizzie
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 7 lat
8

JavaScript :D

Kopiuj
> '5' - 3
2 // weak typing + implicit conversions = headaches
> '5' + 3
'53' // Because we all love consistency
> '5' - '4'
1 // string - string = integer. what?
> '5' + + '5'
'55'
> 'foo' + +'foo'
'fooNaN' // Marvelous.
> '5' + - '2'
'5-2'
> '5' + - + - - + - - + + - + - + - + - - - '-2'
'52' // Apparently it's ok

> var x = 3;
> '5' + x - x
50
> '5' - x + x
5 // Because fuck math

zajumane z reddita

edytowany 1x, ostatnio: Wizzie
Zobacz pozostałe 7 komentarzy
WhiteLightning
Nie lubie takich kruczkow - potem robia sie z tego jezyki typu "Napisz i zapomnij" , a w domysle niech sie jakis frajer pozniej martwi czemu dziala jak dziala.
Marooned
Dlatego cenię PHP za odróżnienie dodawania + od konkatenacji ..
Demonical Monk
@Marooned: W PHPie są znacznie ładniejsze koercje, niejeden programista o tym nie wie :D http://ideone.com/oqTMEu
msm
@Demonical Monk Ty to już na forum nie strasz, myślałem że odszedłeś.
Marooned
@Demonical Monk, true, true. Tu pisałem wyłącznie o braku problemu dodawania i konkatenacji. Nie implikuje to innych wad :)
Trebuh
  • Rejestracja:ponad 10 lat
  • Ostatnio:około 4 lata
  • Lokalizacja:okolice Łodzi
0

Może nie programistyczne ale związane z Windowsem.
Ostatnio słyszałem więcej dźwięków z otwierającego się MessageBox'a z Windowsa, myślałem że to wirus. Skanowałem kilka razy, czyściłem rejestr i nic. Okazało się że w pewnej piosence występuje bardzo podobny dźwięk. Ciekawe kto zgadnie co to za piosenka ;)


GG: 10101100010110000100011101 (BIN)
"Nie wszystko napisane w internecie jest prawdą" - Józef Piłsudski.
OK
Spotkałem się z takim samplem w pewniej piosence ambientowej której tytułu nie pamiętam. To ta sama?
Marooned
Niejaki Tarkan miał kiedyś taki kawałek wałkowany przez radia, w której był klakson. Znam przynajmniej kilka osób, które się spłoszyły podczas jazdy, że ktoś na nich trąbi. Sam też parę razy się rozglądałem.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:Wrocław
5

Dodawanie dat na stringach:

Kopiuj
int daysUntilExpriry = czytamy z bazy

string dateAsText = DateTime.Now.AddDays(daysUntilExpriry).ToString("yyyy-MM-dd") + "T23:59:59";
DateTime returnDate = DateTime.ParseExact(dateAsText, "yyyy-MM-ddTHH:mm:ss", null);

Ach, ten angielski profesjonalizm.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Tuchów
  • Postów:12163
0

Przepisuję właśnie algorytm tokenizera formatowanego labelka, tyle że stosując inne podejście - zamiast kopiować fragmenty łańcucha do tokenów, po prostu zapamiętuję wskaźniki na początki i końce fragmentów sekcji (nagłówków lub paragrafów); Dzięki temu łańcuch kodu labelka będzie tylko jeden, a lista tokenów (czy tam ich macierz) będzie przechowywać pary pointerów;

Wszystko mam gotowe, testowy kod wygląda tak i pod FPC działa wyśmienicie; Ale jak zwykle Delphi7 się buntuje - ostatnia literka ostatniej sekcji to h, a ten skądś wytrzasnął d:

console.png

Na dodatek do procedury AddSection trafiają wskaźniki z poprawnymi znakami (sprawdziłem pod debugerem), a druga pętla nie zmienia parametru ALast - potem już tylko przypisanie i tyle; Dlaczego więc w procedurze ShowSectionsContent wskaźnik wskazuje na jakąś dziwną literkę? Zielonego pojęcia nie mam; Próbowałem tę ostatnią sekcję modyfikować i modyfikacje działają super, ale ta konkretna sprawia problemy...

Dziwne to, ale ważne że FPC robi to poprawnie.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Zobacz pozostałe 2 komentarze
Patryk27
Ostatnie miesiące siedzę głównie w PHP więc wiesz, mikrooptymalizacje to nie mój klimat :D
flowCRANE
Heh, nie dziwię się ;)
Azarien
while pchrBegin &lt; pchrLast do begin while (pchrBegin &lt;= pchrLast) WTF. poza tym w jednym miejscu Last traktujesz jako wskaźnik na ostatni znak, a w drugim miejscu pchrLast jako wskaźnik na miejsce za ostatnim znakiem - niekonsekwentnie. na 99% masz UB które się objawia na D7.
flowCRANE
Dublowanie warunku pchrBegin &lt; pchrLast jest konieczne, to nie WTF; Jeśli o Last chodzi, to pchrLast wskazuje zawsze na ostatni znak kontentu, a ALast lub Last w macierzy zawsze na ostatni znak sekcji; To nie jest niekonsekwencja, tylko brak wyboru - pól nie mogę nazwać Begin i End (z wiadomych przyczyn), dlatego w kodzie testowym nazwałem je po prostu First i Last, jako pierwszy i ostatni znak sekcji;
flowCRANE
@Azarien - tutaj opisane jest dublowanie warunku: http://pastebin.com/RSNXupuC ; Jeśli duble usunie się, to kod będzie albo niebezpieczny (może wyjechać poza zakres łańcucha) dla nieprawidłowo podanego kontentu, albo nie będzie realizował założeń (pomijania znaków nienależących do sekcji);
szopenfx
  • Rejestracja:ponad 20 lat
  • Ostatnio:4 miesiące
0

Podczas dodawania AddSection masz

Kopiuj
AFirst: 'third paragraaa"q'
ALast: 'a"q'

zmieniłem też tekst na poniższy ale to jest to samo:
SAMPLE_CODE = AnsiString('qfirst headerq"first paragraph"q"second paragraph"qsecond headerq"third paragraaa"q');

A jednak nie...

musisz zamienić

Kopiuj
  procedure ExtractSectionsText(ACode: AnsiString);

na:

Kopiuj
  procedure ExtractSectionsText(var ACode: AnsiString);

Działasz na tymczasowej kopii łańcucha w tej funkcji.

edytowany 1x, ostatnio: szopenfx
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Tuchów
  • Postów:12163
0

@szopenfx - nawet jeśli bym działał na kopii, to ta kopia będzie dokładnie taka sama jak oryginał;

Ale czaję co źle zrobiłem - trzeba przekazać łańcuch przez referencję i nie będzie problemu... :] Normalnie operuję na polu klasy komponentu, więc parametry mi niepotrzebne, jednak przy przenoszeniu kodu zastąpiłem parametrem odwołanie do pola i tu wałek z kopią;

Tyle że nadal WTFem jest to, że tylko i wyłącznie taka wartość parametru daje niepoprawne wyjście - jeśli zmienię o jeden znak ciąg ze stałej, to wyjście będzie już poprawne; Próbowałem na różnych ciągach i różnych kompilatorach, no i tylko ten konkretny daje nieprawidłowe wyjście (tylko w D7);

Czas chyba w końcu iść spać o normalnej porze...


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
Zobacz pozostałe 5 komentarzy
KR
Nie możesz tego napisać po ludzku używając indeksów tablic a nie wskaźników? Używanie wskaźników, gdzie nie są potrzebne to WTF jest.
flowCRANE
@Krolik - a od kiedy to używanie wskaźników do obróbki łańcuchów to WTF? Cała biblioteka standardowa FPC czy Delphi na nich bazuje, więc to normalne; W moim przypadku ich użycie jest konieczne, bo pozostała część kodu używa instrukcji z biblioteki standardowej, które przyjmują w parametrach jedynie wskaźniki (do UTF-8); Po drugie, algorytmy muszą być bardzo szybkie, więc nie mając wskaźników, musiałbym korzystać z takich instrukcji jak Copy, Delete czy Pos, które działają dużo wolniej; Gdyby kod był powolny, to rozciąganie komponentu powodowałoby migotanie zawartości;
flowCRANE
Ja nie wiedzę nic złego w używaniu wskaźników w takich przypadkach; Owszem, łatwiej i krócej jest użyć instrukcji z RTL czy nawet regexów, ale liczy się maksymalna szybkość, którą wskaźniki mi zapewniają; A to że kod wygląda dziwnie czy jest dłuższy, akurat ma drugorzędne znaczenie - ja dokładnie wiem jak działa, więc jest dla mnie idealny ;)
KR
No, jesli Delphi nie umie zoptymalizować dostępu za pośrednictwem indeksów, to faktycznie inaczej pewnie się nie da. Czyli nie jest to w takim razie WTF Twojego kodu, a projektu biblioteki / kompilatora, że wszystko na wskaźnikach wymusza (rodem z C). Chodziło mi tylko o to, że wskaźniki są bardzo błędogenne; np. to kompilator nie zagawarantuje Ci, że AFirst i ALast wskazują na część tego samego stringa. Do tego bardzo łatwo popełnić właśnie różne dziwne błędy z zamazywaniem pamięci.
flowCRANE
Może odpiszę w poście, bo komentarz jest zbyt krótki;
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Tuchów
  • Postów:12163
0
Krolik napisał(a)

No, jesli Delphi nie umie zoptymalizować dostępu za pośrednictwem indeksów, to faktycznie inaczej pewnie się nie da.

Umie takie rzeczy optymalizować, FPC tak samo (którym kompiluję kod);

Czyli nie jest to w takim razie WTF Twojego kodu, a projektu biblioteki / kompilatora, że wszystko na wskaźnikach wymusza (rodem z C)

Tzn. nie wszystko, a niektóre z używanych przeze mnie funkcji, które operują na łańcuchach kodowanych w UTF-8; Głównie chodzi o funkcję UTF8CharacterToUnicode, która przyjmuje wskaźnik na pierwszy bajt znaku; Jakoś szczególnie nie utrudnia to przetwarzania łańcuchów, wręcz przeciwnie;

Chodziło mi tylko o to, że wskaźniki są bardzo błędogenne; np. to kompilator nie zagawarantuje Ci, że AFirst i ALast wskazują na część tego samego stringa.

Kompilator gwarantuje mi, że wskaźniki będą wskazywać na istniejące znaki w istniejącym łańcuchu, pod warunkiem że po ustawieniu wskaźników nie zmodyfikuje zawartości łańcucha - ale to normalne i nie dotyczy jedynie wskaźników na znaki; Moim błędem było przekazanie łańcucha przez wartość, dzięki czemu otrzymywałem kopię łańcucha, wskaźniki ustawiałem na znaki w skopiowanym łańcuchu, a po wyjściu z procedury referencja do łańcucha zostawała utracona (normalne zachowanie); Czyli wskaźniki wskazywały na pozostałość po łańcuchu; Gdybym przekazał łańcuch przez referencję, to wszystko by grało;

Do tego bardzo łatwo popełnić właśnie różne dziwne błędy z zamazywaniem pamięci.

Jeśli myśli się podczas pisania kodu (co czasem niestety, ale zawodzi), to nic się nie podzieje; Tym razem podczas przenoszenia kodu z klasy do testowego programu, nie pomyślałem o poprawnym przekazaniu parametru, dlatego też wyszedł wielki WTF; A tu się okazuje, że wszystko przez głupie niedopatrzenie;


Do przetwarzania łańcuchów używam wskaźników, dlatego że poprawny kod wykorzystujący je, pozwala na napisanie bardzo szybkiego skrawka kodu; Oczywiście można posiłkować się funkcjami z biblioteki standardowej, takimi jak Pos, PosEx, Copy czy Delete, jednak wielokrotne ich użycie znacznie spowalnia algorytm, albowiem wykonują kupę zbędnych rzeczy;

Weźmy na przykład pierwszą (wewnętrzną) pętlę z mojego kodu - szuka ona otwierającego znacznika, pomijając inne znaki; Jest to jedna pętla, gdzie w argumentach sprawdza czy wskaźnik na znak jest mniejszy od adresu ostatniego znaku, następnie czy wskaźnik wskazuje na znak znacznika i jeśli nie - inkrementuje wskaźnik za pomocą Inc - krótko i efektywnie; A teraz weźmy pod lupę funkcję PosEx, która ma nam zastąpić naszą pętlę; Oczywiście ona także używa wskaźnika do przeszukiwania łańcucha, jednak wykonuje zbędne sprawdzanie długości łańcucha, traci czas na inicjowanie zmiennych lokalnych oraz wymusza skopiowanie dwóch łańcuchów (w parametrach przekazanych przez stałą), aby móc wykonać przeszukiwanie lokalnie; W rezultacie działa dwa razy dłużej od mojej pętli; Niestety, ale taka jest cena uniwersalizmu;

Niby tak prosta operacja trwa bardzo krótko, jednak wywołań tej funkcji w procesie rozdzielania kontentu na sekcje będzie dziesiątki - a to tylko podział na sekcje; Kolejny algorytm dzieli każdą sekcję na słowa, który de facto także robi to na podstawie własnej pętli i wskaźników; Jeśli w nim znów skorzystać z PosEx - znów tracimy czas; A w jednym labelku słów może być setki, więc ma to duże znaczenie; Niestety dzielenie kontentu na sekcje i słowa to dopiero 10% procesu tokenizowania; Następnie każdą sekcję trzeba podzielić na linie (mierzyć kolejne słowa), według bieżacego stylu fontu, potem wyznaczyć punkty, w których będą zaczynać się linie; W następnej kolejności trzeba przewalić wszystkie tokeny i wydobyć informacje o linkach - pobrać regiony, w których kursor ma się zmienić, a treść linku przemalować;

To chyba tyle - jak widać kupa kodu; Kod musi być efektywny, dlatego że wszystko co opisałem wyżej, wykonywane jest po pierwsze każdorazowo przy zmianie szerokości komponentu (np. przy rozciąganiu okna z zakotwiczoną do obu boków etykietą), a po drugie - kilkakrotnie przy stworzeniu komponentu; Gdyby kod był wolny - rozciąganie komponentu powodowałoby migotanie całości i nędzny efekt;

Tak więc używam wskaźników, aby maksymalnie jak tylko potrafię przyspieszyć kod (oczywiście jeśli jest to konieczne); Większość algorytmów z modułu TSInfoUtils (z mojej biblioteki do obsługi plików TreeStructInfo) pisałem używając wskaźników, zamiast instrukcji z RTL; To pozwoliło zoptymalizować kod procedur i funkcji nawet o 50%;

Kiedyś nie przepadałem za wskaźnikami, nawet uznawałem je za zbędne; Jednak jak już je poznałem to polubiłem od razu, dlatego że pozwalają na pisanie szybkiego kodu; A jak piszę jakiś kod, to sam od siebie wymagam, aby wycisnąć z niego jak najwięcej się da :]


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
KR
"Moim błędem było przekazanie łańcucha przez wartość, dzięki czemu otrzymywałem kopię łańcucha, wskaźniki ustawiałem na znaki w skopiowanym łańcuchu, a po wyjściu z procedury referencja do łańcucha zostawała utracona (normalne zachowanie)" no i to jest właśnie ogólny problem ze wskaźnikami; bardzo mocno utrudniają analizowanie kodu pod względem poprawności i można sobie przypadkowo strzelić w stopę na 1000 sposobów. A programista to tylko człowiek i błędy robi.
flowCRANE
Może i tak, ale coś za coś ;)
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
3
Kopiuj
if (!LOG.isDebugEnabled()) {
    return pjp.proceed();
}
long time = System.currentTimeMillis();
try {
    return pjp.proceed();
} finally {
    time = System.currentTimeMillis() - time;
    LOG.debug("{}[args:{}] executed in {}ms", pjp.getSignature(), pjp.getArgs(), time);
}

pomiar czasu... debug...cóż więcej można chcieć... (kod z bratniego wschodu).


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
Zobacz pozostałe 4 komentarze
KR
Raczej nazwałbym to nieszkodliwą, defensywną optymalizacją. Wcale nie wiadomo czy pjp.getSignature / pjp.getArgs są takie szybkie i czy np. nie sklejają stringów pod spodem albo nie robią jakichś alokacji. System.currentTimeMillis też wcale nie musi być szybkie (w Oraclowym JVM jest akurat b. szybkie, ale w innych JVMach wcale nie musi). Ta optymalizacja nic nie kosztuje a daje pewność, że nic się ponad pjp.proceed nie wykona i oszczędza mi czasu na analizowanie implementacji wszystkich użytych wywołań. +1 za to, że ktoś pomyślał, a nie klepie kod byle szybko.
KR
PS. Przedwczesna optymalizacja ponoć jest źródłem wielu problemów, ale z drugiej strony jest całe mnóstwo prostych optymalizacji, które nic nie kosztują, a których brak potrafi się czasem zemścić. I uważam, że warto je stosować, jeśli nie zaciemniają/komplikują kodu. Jeżeli wiem, że mogę gdzieś nie wykonywać jakiejś niepotrzebnej pracy, to jej nie wykonuję, a nie zastanawiam się, ile na tym oszczędzę i czy warto dopisać jedną linijkę.
Koziołek
@Krolik, ale mamy XXI wiek i całkiem szybkie procesory. W szerszym kontekście nie ma sensu gdy weźmiesz pod uwagę iż całość działa w procesie zajmującym setki milisekund. Zysk żaden, a zagmatwanie kodu rośnie.
KR
Zauważ, że ten kod to kod biblioteczny, do wstrzyknięcia w dowolne miejsce. Czy będzie działać w procesie zajmującym setki milisekund, czy w procesie zajmującym 5 nanosekund - tego, z punktu widzenia tego kodu nie wiadomo. Może teraz nie robi różnicy, ale za 2 lata ktoś przyjdzie i wstrzyknie to do metody w super ciasnej pętli i te dodatkowe "prawie nic nie kosztujące wywołania" spowodują, że kompilator wygeneruje znacznie gorszy kod niż mógłby. A zaciemnienie kodu jest w tym przypadku jest bliskie zeru i nie rzutuje na resztę projektu.
KR
BTW: W optymalizacji kodu nie należy zgadywać i ta zasada działa w dwie strony. Tzn. zgadywanie, że coś się wykonuje szybko i "nic nie kosztuje", to też zgadywanie i może się zemścić równie mocno jak zgadywanie, że coś jest powolne i wymaga super sprytnej, zagmatwanej optymalizacji. A tłumaczenie, że dzisiejsze procki są szybkie to świetna droga prowadząca to ospałego kodu. Poza tym procki może nawet i są szybkie, ale ja wolę jak mi aku laptopa starcza na 7h a nie 3h.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)