Biorę kurs pośrednich struktur danych jako warunek wstępny do programu CS MS na uniwersytecie, o którym wszyscy w Ameryce słyszeli. Jeden wiersz kodu, który został napisany w klasie, przykuł moją uwagę:
if (a > 33 | b++ < 54) {...}
To nie przejdzie przeglądu kodu w moim miejscu pracy. Gdybyś napisał taki kod w wywiadzie, byłby to znaczący atak przeciwko tobie. (Oprócz bycia warunkowym z efektami ubocznymi, jest sprytny kosztem przejrzystości).
W rzeczywistości nigdy nie widziałem warunku z efektami ubocznymi, a Googling też się nie pojawia. Kolejny uczeń został też po zajęciach, żeby o to zapytać, więc nie jestem jedynym, który uważał to za dziwne. Ale profesor był zdecydowanie nieugięty, że był to akceptowalny kod i że napisałby coś takiego w pracy. (Jego praca FT jest jako główny SWE w firmie, o której wszyscy słyszeliście.)
Nie wyobrażam sobie świata, w którym ten wiersz kodu byłby kiedykolwiek akceptowalny, a tym bardziej pożądany. Czy się mylę? Czy to jest ok? Co z bardziej ogólnym przypadkiem: warunki warunkowe z efektami ubocznymi? Czy to jest w porządku?
źródło
Odpowiedzi:
Jest jeden pół-warunkowy efekt uboczny, o którym myślę, że jest w porządku:
while(iter.MoveNext())
To powiedziawszy, myślę, że należy to głównie do kategorii „ nigdy nie jest naprawdę wielkim kwalifikatorem”. Mogę wymyślić kilka rzadkich przypadków, w których widziałem, że jest to akceptowalne, ale ogólnie jest to podłe i należy tego unikać.
Nie mogę również wymyślić scenariusza, w którym ta konkretna linia byłaby do zaakceptowania, ale nie mogę również wymyślić scenariusza, w którym ta konkretna linia byłaby przydatna , więc trudno jest wyobrazić sobie kontekst, w którym się znajduje.
źródło
while(v = *p++)
skanowanie w stylu C / C ++ poprzez tablicę zakończoną zerem (np. Łańcuch C) jest dość powszechne i powszechnie akceptowane.while(c = input.read() != '\n')
za dość idiomatyczne.W moim świecie odczyt z pamięci można uznać za efekt uboczny (np. IO zmapowane w pamięci).
Teraz rozważ następujące kwestie:
I porównaj do:
Czy uniknięcie efektu ubocznego (odczyt) w tym stanie pomogło w czytelności; czy po prostu zduplikował kod i dodał bałaganu?
Nie jest dozwolone, aby warunek miał skutki uboczne (jeśli to sprawia, że kod jest mniej czytelny), a także warunek może mieć skutki uboczne (jeśli to sprawia, że kod jest bardziej czytelny). Kluczowym czynnikiem jest „czytelność”. Cała reszta to reguły tworzone przez głupców w nieudanej próbie poprawy czytelności (choć często mają odwrotny skutek).
źródło
Jak zawsze w przypadku takich pytań, jest to kwestia stopnia. Gdyby istniał jednoznaczny dowód, że jakikolwiek efekt uboczny w
if
wyrażeniu zawsze prowadzi do gorszego kodu, tworzenie takich wyrażeń byłoby niezgodne z prawem. Projektanci języków mogą być ideosynratycznymi, omylnymi ludźmi, ale nie są aż tak głupi.To powiedziawszy, jakie są przykłady uzasadnionych skutków ubocznych w obrębie
if
? Załóżmy na przykład, że jesteś prawnie zobowiązany do rejestrowania całego i dowolnego dostępu do nieruchomościP
jednostkiE
do celów audytu. (Wyobraź sobie, że pracujesz w zakładzie wzbogacania uranu, i istnieją bardzo ścisłe prawne kontrole tego, co twój kod może robić i jak powinien to robić.) Wif
takim razie sprawdzenie, czy ta właściwość spowoduje efekt uboczny dziennik kontroli jest rozszerzany.Jest to dość wyraźna kwestia przekrojowa, nie wpływa ona na twoje rozumowanie na temat stanu programu (bardzo), i możesz go wdrożyć, aby był całkowicie niewidoczny i nie rozpraszał, gdy przeglądasz linię za pomocą
if
(ukryty w akcesorium, a jeszcze lepiej przez AOP). Powiedziałbym, że to całkiem wyraźny przypadek efektu ubocznego, który nie stanowi problemu. Podobne sytuacje można sobie wyobrazić, gdy po prostu chcesz policzyć wykonania gałęzi do celów profilowania itp.Im bardziej te okoliczności łagodzące znikną, tym bardziej obcy stanie się konstrukt. Jeśli określony typ pętli (np.
if((c = getc()) == 'x') { quit(); }
Jest dobrze znany i akceptowany przez społeczność językową, oznacza to o wiele mniejszy problem niż wtedy, gdy wymyślisz go spontanicznie itp. Twój przykładowy wiersz nie spełnia tego standardu, ale mógłbym sobie wyobrazić dużo, dużo bardziej okropne, których nawet nie będę pisać, są takie okropne.źródło
Chociaż naprawdę śmierdzący kod, ma tę zaletę, że jest prostszy (i być może szybszy, jeśli nie masz dobrego kompilatora optymalizującego) niż jego odpowiednik
if (a > 33 | b < 54) {b++; ...} else b++;
ale oczywiście można zoptymalizować go w następujący sposób (ale uważaj! ten ma inne zachowanie w przypadku przepełnienia!):
b++; if (a > 33 | b < 53) {...}
źródło