Spotkałem wielu ludzi, którzy są dogmatycznie przeciwni czemukolwiek, co można uznać za „optymalizację” w ogólnym znaczeniu tego słowa w języku angielskim, i bardzo często cytują dosłownie (częściowo) cytat „przedwczesna optymalizacja jest źródłem wszelkiego zła” jako uzasadnienie ich stanowiska, sugerując, że interpretują wszystko, o czym mówię, jako „przedwczesną optymalizację”. Jednak te poglądy są czasami tak absurdalnie zakorzenione, że odrzucają praktycznie wszelkie odchylenia algorytmiczne lub struktury danych od najczystszej „naiwnej” implementacji… lub przynajmniej wszelkie odchylenia od tego, co robili wcześniej.Jak można podejść do takich osób w taki sposób, aby ponownie „otworzyły uszy” po tym, jak przestały słyszeć o „wydajności” lub „optymalizacji”? Jak omówić temat projektowania / wdrażania, który ma wpływ na wydajność, nie każąc ludziom od razu myśleć: „Ten facet chce spędzić dwa tygodnie na dziesięciu liniach kodu?”
Teraz stanowisko, czy „wszelka optymalizacja jest przedwczesna, a zatem zła”, czy nie, zostało już omówione tutaj, jak również w innych zakątkach sieci , i już dyskutowano, jak rozpoznać, kiedy optymalizacja jest przedwczesna, a zatem zła , ale niestety wciąż istnieją ludzie w prawdziwym świecie, którzy nie są tak otwarci na wyzwania związane z wiarą w antyoptymalizację.
Poprzednie próby
Kilka razy próbowałem podać pełny cytat z Donalda Knutha , aby wyjaśnić, że „przedwczesna optymalizacja jest zła” ↛ „cała optymalizacja jest zła”:
Powinniśmy zapomnieć o małej wydajności, powiedzmy około 97% czasu: przedwczesna optymalizacja jest źródłem wszelkiego zła. Nie powinniśmy jednak tracić naszych szans w tak krytycznych 3%.
Jednak, dostarczając cały cytat, ludzie ci czasami stają się bardziej przekonani, że to, co robię, to Premature Optimization ™ i kopie i nie chce słuchać. To prawie tak, jakby przeraża je słowo „optymalizacja”: Kilka razy byłem w stanie zaproponować rzeczywiste zmiany kodu poprawiające wydajność bez zawetowania ich, po prostu unikając użycia słowa „optymalizacja (e | acja)” ( i „wydajność” - to słowo też jest przerażające) i zamiast tego używa wyrażeń takich jak „architektura alternatywna” lub „ulepszona implementacja”. Z tego powodu naprawdę wydaje się, że to naprawdę jest dogmatyzm, a nie faktyczna ocena tego, co mówię krytycznie, a następnie odrzucenie go jako niepotrzebnego i / lub zbyt kosztownego.
źródło
Odpowiedzi:
Wygląda na to, że szukasz skrótów, aby nie wypróbować „najczystszej naiwnej implementacji” i bezpośrednio wdrożyć „bardziej wyrafinowane rozwiązanie, ponieważ wiesz wcześniej, że naiwna implementacja tego nie zrobi”. Niestety, rzadko to działa - jeśli nie masz twardych faktów lub argumentów technicznych, aby udowodnić, że naiwne wdrożenie jest lub będzie zbyt wolne, najprawdopodobniej się mylisz, a to, co robisz, to przedwczesna optymalizacja. A próba kłótni z Knuthem jest przeciwieństwem trudnego faktu.
Z mojego doświadczenia wynika, że będziesz musiał najpierw ugryźć kulę i wypróbować najpierw „naiwną implementację” (i prawdopodobnie będziesz zaskoczony, jak często jest to wystarczająco szybka), albo przynajmniej dokonasz przybliżonej oceny czasu pracy, na przykład:
„Naiwnym wdrożeniem będzie O (n³), a n jest większe niż 100 000; to potrwa kilka dni, podczas gdy niezbyt naiwne wdrożenie będzie działać w O (n), co zajmie tylko kilka minut” .
Tylko przy takich argumentach masz pewność, że Twoja optymalizacja nie jest przedwczesna.
Jest tylko jeden wyjątek od IMHO : gdy szybsze rozwiązanie jest również prostsze i czystsze, powinieneś użyć szybszego rozwiązania od samego początku. Standardowym przykładem jest użycie słownika zamiast listy, aby uniknąć niepotrzebnego kodu pętli do wyszukiwania, lub użycie dobrego zapytania SQL, które daje dokładnie jeden rekord wyniku, którego potrzebujesz, zamiast dużego zestawu wyników, który musi być filtrowane później w kodzie. Jeśli masz taki przypadek, nie kłóć się o wydajność- występ może być dodatkową, ale najprawdopodobniej nieistotną korzyścią, a kiedy o nim wspomnisz, ludzie mogą ulec pokusie użycia Knutha przeciwko tobie. Dyskutuj o czytelności, krótszym kodzie, czystszym kodzie, łatwości konserwacji - nie musisz tutaj niczego maskować, ale ponieważ te (i tylko te) są tutaj poprawnymi argumentami.
Z mojego doświadczenia wynika, że ten drugi przypadek jest rzadki - tym bardziej typowym jest to, że najpierw można wdrożyć proste, naiwne rozwiązanie, które jest lepiej zrozumiałe i mniej podatne na błędy niż bardziej skomplikowane, ale prawdopodobnie szybsze.
I oczywiście powinieneś znać wymagania i przypadek użycia na tyle dobrze, aby wiedzieć, jaka wydajność jest akceptowalna i kiedy sytuacja staje się „zbyt wolna” w oczach użytkowników. W idealnym świecie klient otrzymałby formalną specyfikację wydajności, ale w rzeczywistych projektach wymagana wydajność jest często szarą strefą, coś, co użytkownicy powiedzą tylko wtedy, gdy zauważą, że program zachowuje się „zbyt wolno” w produkcji. I często jest to jedyny działający sposób stwierdzenia, kiedy coś jest zbyt wolne - informacja zwrotna od użytkownika, a następnie nie trzeba cytować Knutha, aby przekonać członków zespołu, że ich „naiwne wdrożenie” nie było wystarczające.
źródło
Zadaj sobie to:
To są powody do optymalizacji. Więc jeśli ludzie są przeciwni, po prostu pokaż im specyfikację i wróć do nich i wyjaśnij, że musimy zoptymalizować, ponieważ nie spełniamy specyfikacji. Poza tym trudno byłoby przekonać innych, że optymalizacja jest konieczna.
Myślę, że głównym punktem cytatu jest to, że jeśli nie masz problemu, nie przeprowadzaj niepotrzebnej optymalizacji, ponieważ czas i energię można by wydać gdzie indziej. Z perspektywy biznesowej ma to doskonały sens.
Po drugie, dla tych, którzy obawiają się optymalizacji, zawsze wykonuj kopię zapasową wyników za pomocą wskaźników. O ile szybszy jest kod? Jak bardzo poprawiła się wydajność w porównaniu do poprzednich? Gdyby spędzić dwa tygodnie tylko na poprawieniu kodu o 2% w stosunku do poprzedniej wersji, gdybym był twoim szefem, nie byłbym szczęśliwy. Te dwa tygodnie można było poświęcić na wdrożenie nowej funkcji, która może przyciągnąć więcej klientów i zarobić więcej pieniędzy.
Wreszcie większość oprogramowania nie musi być wysoce zoptymalizowana. Tylko w kilku wyspecjalizowanych branżach szybkość jest naprawdę ważna. Tak więc przez większość czasu można z powodzeniem korzystać z istniejących bibliotek i frameworków.
źródło
Zacznij od wspólnych zasad, które opierają się na strategicznym kierowaniu twoją grupą.
Moje zasady:
Moje osobiste zasady pisania kodu polegają najpierw na poprawności w moim programie, a następnie na jego profilowaniu i ustaleniu, czy wymaga optymalizacji. Sam profiluję swój kod, ponieważ inni programiści są potencjalnymi odbiorcami mojego kodu - i nie będą go używać, jeśli jest wolny - dlatego w moim kodzie prędkość jest cechą.
Jeśli Twoi klienci są klientami, powiedzą Ci, czy potrzebujesz szybszego kodu.
Istnieją jednak znane, wyraźnie lepsze wybory w kodzie, które można dokonać. Wolę to zrobić w moim pierwszym projekcie z kilku powodów:
Zakładając, że potrzeba optymalizacji jest poprawna
Zakładając, że jest to naprawdę ważna część twojego kodu, która wymaga optymalizacji, możesz opowiedzieć przypowieść o malarzu Schlemiela lub podkreślić resztę cytatu:
Zważyć koszty dodatkowej złożoności
Czasami istnieje realny koszt w zakresie utrzymania dodatkowej złożoności. W takim przypadku możesz zachować dodatkową implementację w innej funkcji lub podklasie i zastosować do niej te same unittests, aby nie było wątpliwości, że jest poprawna. Później, jeśli wyprofilujesz swój kod i stwierdzisz, że naiwna implementacja stanowi wąskie gardło, możesz przełączyć swój zoptymalizowany kod i wyraźnie ulepszyć swój program.
Przywództwo
Czasami problemem jest ego - niektórzy woleliby używać nieoptymalnego lub błędnego kodu, niż gdyby ktoś miał więcej racji niż oni. Prawdopodobnie chcesz uniknąć pracy z tymi ludźmi.
Przywództwo, szczególnie gdy nie masz pozycji nad ludźmi, polega na przedstawianiu rozsądnych sugestii i prowadzeniu innych do konsensusu. Jeśli nie możesz poprowadzić swojego zespołu do spotkania umysłów, być może nie warto tego naciskać. Prawdopodobnie są większe ryby do smażenia.
źródło
Droga naprzód polega na zapomnieniu o aktualnym cytacie i różnych interpretacjach - tak czy inaczej dogmatyzm tak bardzo koncentruje się na konkretnym cytacie guru. Kto powiedział, że Knuth i tak ma zawsze rację?
Zamiast tego skup się na projekcie pod ręką, oprogramowaniu, które rozwijasz wraz ze współpracownikami, z którymi się nie zgadzasz. Jakie są wymagania dotyczące akceptowalnej wydajności dla tego oprogramowania? Czy to wolniejsze niż to? Następnie zoptymalizuj.
Nie musisz nazywać go „optymalizacją”, możesz nazwać to „naprawieniem błędu”, ponieważ z definicji jest to błąd, jeśli implementacja nie spełnia wymagań.
Mówiąc bardziej ogólnie, istnieją dwie możliwości optymalizacji:
Zoptymalizowany kod jest także krótszy, łatwiejszy do zrozumienia i łatwiejszy w utrzymaniu.
Zoptymalizowany kod jest bardziej skomplikowany do zrozumienia, zajmuje więcej czasu na pisanie i testowanie, lub byłby bardziej skomplikowany do zmiany w przyszłości, jeśli wymagania zmienią się w nieoczekiwany sposób.
W przypadku (1) nie musisz nawet kłócić się o optymalizację. Ale jeśli tak jest (2), wówczas podejmujesz decyzję o kompromisie . W rzeczywistości jest to decyzja na poziomie biznesowym, a nie wyłącznie decyzja techniczna. Musisz porównać koszt optymalizacji z korzyścią. Aby nawet przyniosła korzyść, nieefektywność musi być przede wszystkim problemem, albo ze względu na złe wrażenia użytkownika, albo znacznie wyższy koszt sprzętu lub innych zasobów.
źródło
Myślę, że pełny cytat w kontekście jest pouczający. Skopiuję z posta napisanego na Reddit na ten temat:
- Donald Knuth, Programowanie strukturalne za pomocą go to Statement , ACM Computing Surveys, tom 6, nr 4, grudzień 1974, str. 268
Chodzi o to, że należy martwić się o wiele ważniejszymi rzeczami niż zbyt wcześnie zwracać uwagę na optymalizację. Oczywiście, powinieneś dokładnie rozważyć swoje struktury danych i algorytmy (jest to w 3%), ale nie powinieneś się martwić, czy odejmowanie jest szybsze niż modulo (to jest w 97%), dopóki nie stanie się jasne, że optymalizacja niskiego poziomu jest niezbędny.
Ten pierwszy niekoniecznie oznacza optymalizację w tym sensie, o czym myślą Twoi koledzy, ale jest optymalizacją w tym sensie, że źle dobrane algorytmy i struktury danych są nieoptymalne.
źródło
Z mojego doświadczenia wynika, że jeśli regularnie spotykasz się z takim sprzeciwem wobec optymalizacji , ludzie tak naprawdę nie narzekają na optymalizację. Narzekają na to, co poświęcasz w imię optymalizacji. Zwykle jest to czytelność, łatwość konserwacji lub aktualność. Jeśli Twój kod zostanie dostarczony w tym samym czasie i równie łatwo go zrozumieć, ludzie nie będą się przejmować, jeśli korzystasz z wydajniejszych struktur danych i algorytmów. Sugeruję w tym przypadku, aby uczynić kod bardziej eleganckim i łatwym w utrzymaniu.
Jeśli masz do czynienia z takim sprzeciwem w stosunku do kodu innych osób, zwykle dzieje się tak dlatego, że sugerujesz znaczną ilość przeróbek. W takich przypadkach naprawdę potrzebujesz rzeczywistych pomiarów, aby pokazać, że warto, lub spróbuj zaangażować się wcześniej na etapie projektowania, zanim zostanie napisany kod. Innymi słowy, musisz udowodnić, że wynosi on 3%. Gdybyśmy przepisali cały kod, który nie był dokładnie taki, jak nam się podobało, nigdy nie osiągnęlibyśmy niczego.
źródło
Deque
Ze standardowej biblioteki Java, aby zastąpić ogromną ilość logiki zbudowanej wokółArrayList
stosu podczas pracy nad kodem ... i to oznaczono dla zmiana w przeglądzie. Innymi słowy, recenzent chciał mieć więcej kodu, który jest również wolniejszy i bardziej podatny na błędy, ponieważ nie był zaznajomionyDeque
.W istocie jest wiele nieporozumień dotyczących tego cytatu, więc najlepiej cofnąć się i spojrzeć na rzeczywisty problem. Problem nie jest tak duży, że nigdy nie powinieneś „optymalizować”. Chodzi o to, że „optymalizacja” nigdy nie jest zadaniem, które powinieneś podjąć. Nigdy nie powinieneś budzić się rano i mówić sobie „hej, powinienem dzisiaj zoptymalizować kod!”.
Prowadzi to do zmarnowanego wysiłku. Wystarczy spojrzeć na kod i powiedzieć „Mogę to zrobić szybciej!” prowadzi do wielu wysiłków, by stworzyć coś szybszego, co było wystarczająco szybkie. Możesz być dumny z mówienia sobie, że czterokrotnie przyspieszyłeś trochę kodu, ale jeśli ten kod był obliczeniem, które nastąpiło po naciśnięciu przycisku, i zajęło mu 10 milisekund, zanim wyświetlił się ludzkiemu użytkownikowi, nikt nie cholera.
Jest to „przedwczesna” w „przedwczesnej optymalizacji”. Kiedy to nie jest „przedwczesne”? Kiedy klienci mówią: „To jest zbyt cholernie wolne, napraw to!” Wtedy kopiesz kod i próbujesz go przyspieszyć.
To nie znaczy, że powinieneś wyłączyć mózg. Nie oznacza to, że powinieneś przechowywać 10 000 rekordów klientów na pojedynczo połączonej liście. Zawsze powinieneś rozumieć wpływ na wydajność tego, co robisz, i postępować odpowiednio. Ale chodzi o to, że nie spędzasz dodatkowego czasu celowo, próbując przyspieszyć. Po prostu wybierasz bardziej wydajny wybór spośród innych, równych wyborów.
źródło
Możesz albo robić rzeczy w niewłaściwy sposób, albo robić to we właściwy sposób.
Często rzeczy są robione w niewłaściwy sposób, a kod jest refaktoryzowany, aby działał we właściwy sposób. Jeśli masz zamiar napisać nowy kod i wiesz, że możesz robić rzeczy we właściwy sposób bez poważnej kary, popełniłbym błąd, robiąc to we właściwy sposób. (Pamiętaj, że po przetestowaniu wydajności itp. Niektóre rzeczy mogą wymagać zmiany - ale to jest w porządku. Alternatywnie, całkowicie naiwna implementacja rzadko, jeśli w ogóle, jest właściwa).
Optymalizacja niekoniecznie jest przedwczesna, jeśli a) wiesz, że to pomoże w przyszłości lub b) wiesz, że ścieżka nieoptymalna doprowadzi do problemów na drodze. To naprawdę gra w szachy.
Myślę, że ludzie będą chcieli robić rzeczy dobrze, a nie źle. Użyj tego, gdy omawiasz alternatywne strategie z rówieśnikami.
źródło
Wydaje się, że to problem z komunikacją, a nie problem z programowaniem. Spróbuj zrozumieć, dlaczego ludzie czują się tak, jak robią, i spróbuj skrystalizować, dlaczego uważasz, że Twoja droga byłaby lepsza. Kiedy to zrobisz, nie rozpoczynaj sprzeczki, w której twoim celem jest powiedzenie innym, dlaczego się mylą, a ty masz rację. Wyjaśnij swoje myśli i uczucia i pozwól ludziom na to zareagować. Jeśli nie możesz osiągnąć żadnego konsensusu i uważasz, że jest to bardzo ważny problem, prawdopodobnie masz poważne problemy w zespole.
Bardziej skoncentrowany na rzeczywistym programowaniu, nie marnuj czasu na długie kłótnie o coś, co po prostu ma przeczucie, że jest „szybsze”. Jeśli zobaczysz, że ktoś pisze metodę, która jest wywoływana raz na żądanie w aplikacji internetowej i ma złożoność czasową O (n ^ 2), gdy WIESZ, że to naprawdę problem z czasem O (log (n)), to na pewno, jeśli jest taka bez zastanowienia, śmiało.
Pamiętaj jednak, że jako ludzie, my, programiści, jesteśmy naprawdę źli (i mam na myśli SŁUPIE) zgadywanie, które części naszych aplikacji będą wąskie gardło. Eric Lippert pisze o tym interesującym temacie w tym poście na blogu. Zawsze sprzyjaj łatwości konserwacji. Wszelkie problemy z wydajnością, które zostaną ostatecznie znalezione, można łatwo (cóż, względnie) naprawić, gdy masz więcej informacji.
źródło