14 paź 2009

Przedwczesna optymizacja

Przeglądając stronę wikipedii dotyczącą eXtreme Programming znalazłem wśród praktyk programistycznych następujące zalecenie: 'leave optimization till last'. No i faktycznie zdaje się, że jest to dość uznana zasada. Przywołuje na myśl znane zdanie Donalda Knutha
Premature optimization is the root of all evil.
Z drugiej strony zwinne metodyki zalecają utrzymywanie projektu przez cały czas jego rozwoju w stanie gotowości do wdrożenia. Scrum nazywa to potentially shippable product - na koniec każdej iteracji przygotowujemy więc wszystko co niezbędne, żeby produkt tej iteracji można było wdrożyć (nie dlatego, żeby to faktycznie co iterację robić, tylko dlatego, by utrzymywać taką możliwość i dać klientowi prawo do decyzji co do tego kiedy chce aplikację wdrożyć, zaprezentować użytkownikom itp. Poza tym robiąc to jesteśmy pewni, że projekt jest cały czas zintegrowany, i że nasz system CI i proces tworzenia oprogramowania są dobre. No i jeszcze kwestia morale zespołu, gdy wie, że projekt jest non-stop w stanie jakościowo gotowym na produkcję).

Wracając do zostawiania optymizacji na koniec, zupełnie nie zgadzam się z tym. To klasyczny przypadek zostawiania gdzieś praktyk fazowych (waterfall'owych). Jak można nazwać aplikację potencjalnie gotową do wdrożenia, jeśli nie jest wystarczająca wydajnościowo?
Tak więc optymizujmy kod w czasie jego rozwijania. Może nawet warto dodać do Definition of Done zadań zespołu warunek akceptowalności pod względem wydajnościowym.

Oczywiście we wszystkim należy zachować umiar. Ważne jest, by wydajność była akceptowalna / zadowalająca. To może oczywiście oznaczać bardzo rygorystyczne warunki np. dla systemów RT. Szczegółowy fine-tuning wydajności jakichś elementów aplikacji można jednak faktycznie zostawić na później. To znaczy jak się już okaże, że faktycznie jest problem wydajnościowy i będzie wiadomo dokładnie gdzie. Oczywiście nie sądzę, żeby było dobrym pomysłem czekanie aż okaże się to w środowisku produkcyjnym - dla aplikacji dla których wysoka wydajność jest ważna można ją kontrolować stale w czasie rozwoju aplikacji w przeznaczonym do tego środowisku CI z automatycznymi testami wydajnościowymi. Natomiast powinniśmy dbać o nieograniczanie (głównie architektonicznie) naszych możliwości optymizacji.

Z resztą powyższy cytat z Knuth'a nie jest kompletny (a większość programistów zna tylko ten jego fragment). Kompletny brzmi tak:
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

3 komentarze:

Łukasz Lenart pisze...

Wymagana wydajność powinna być określona przez klienta, aby nie robić optymalizacji tylko dla samej optymalizacji. Albo optymalizować te obszary, które nie interesują klienta.

Fakt, nie ma sensu optymalizować czegoś co przynosi mały zysk.

Marcin Niebudek pisze...

Warunki wydajnościowe jako część Definition of Done, to coś co najbardziej mi się podoba. Wtedy mamy taką optymalizację "just enough".

Tyle, że istotne jest posiadanie przynajmniej wizji co zrobimy jak będzie trzeba więcej z aplikacji wycisnąć. Co nie oznacza oczywiście, żeby taki stan utrzymywać w ramach potencjalnie wdrażalnego produktu.

Paweł Lipiński pisze...

Dokładnie tak, Marcin. Dlatego napisałem, że trzeba dbać o to by zostawić sobie opcje poprawy wydajności. To tak naprawdę jest bardzo trudne, bo nie zawsze można przewidzieć gdzie potencjalnie może pojawić się problem. A one zgodnie z prawem murphy'ego zawsze nie tam gdzie się ich spodziewaliśmy... Więc warto dbać o taki design, by zawsze były jakieś Real Options.