Programowanie wymaga myślenia!

Programowanie, optymalizacja i myślenie...

Sztuka programowania łączy w sobie właśnie te trzy sfery, a umiejętne ich wyważenie staje się dobrym wyznacznikiem dla programisty. Bez jakiejkolwiek z nich, traci on swój potencjał i staje się zwykłym koderem klepiącym bez namysłu kod. No cóż, tacy "robotnicy" są również potrzebni przemysłowi, aby wszystko kręciło się dalej.

Optymalizacja jest złem! Takie sformułowania można znaleźć w każdym zakątku sieci związanym z programowaniem, bądź wypowiadany z ust znanych postaci inżynierii oprogramowania. Czy naprawdę optymalizacja jest tym wielkim "mitycznym" złem?

Dwie podstawie reguły optymalizacji programu według Michaela A. Jacksona mówią:

The First Rule of Program Optimization: Don't do it.
The Second Rule of Program Optimization (for experts only!): Don't do it yet.

Czy, aby na pewno najlepiej tego nie ruszać?

Osobiście nie do końca mogę się z tym zgodzić. Ale tak, jak to w życiu bywa, to zależy...

Wiele zależy również od zdefiniowania umownej granicy między prawdziwym błędem a tą samoistnie zachodzącą optymalizacją w czasie pisania aplikacji. Brak przewidywania i myślenia już na etapie pisania kodu często prowadzi do wielu błędów, często uznawanych za błędy projektowe lub jeszcze inne wymysły. A przecież sklecenie kilku linijek kodu ze złożonością przekraczającą możliwości dzisiejszych maszyn, to tak naprawdę brak optymalnego myślenia i tej minimalnej samonarzucającej się optymalizacji już w czasie pisania samego kodu.

Ostatnio całkiem przypadkiem trafiłem na paskudny, dosyć popularny błąd, często popełniany przez początkujących. Mowa tutaj o iterowaniu tablicy znaków w pętli wraz ze zliczaniem jego długości w każdym kroku:

for (int i = 0; i < strlen(buf); i++) {
...
}

Kod ten znalazłem w pewnej bibliotece, która na pewno nie jest pisana przez początkujących! W nim iteracja stringa, mająca w zamyśle mieć złożoność stałą równą 1-2, osiąga wartości kosmiczne, rosnące liniowo do długości iterowanego ciągu (+1).

Trudno uwierzyć co?

Najbardziej powszechna implementacja funkcji strlen wygląda następująco (w uproszczeniu):

int strlen(const char* str) {
	int len = 0;
	while (*str++) len++;
	return len;
}

Nasz wczesniejszy kod zamiast jednej iteracji wykonuje ich miliony! Niepotrzebnie!
[Choć w rzeczywistości nie będzie tak bardzo źle, bo wielce prawdopodobne jest to, że kompilator dokona tutaj pewnych optymalizacji.]

A można byłoby tylko trochę się wysilić, minimalnie pomyśleć i zastanowić, a wszystko osiągnęlibyśmy w jednej iteracji ciągu znakowego, nawet bez narzutu wywoływania różnych "zewnętrznych" funkcji. Przecież na litość boską wystarczyłaby jedna pętelka i nawet nie trzeba znać rozmiaru stringu:

while (*buf) {
	...
	++buf;
}

No tak, ale żeby na to wpaść trzeba myśleć! A to przecież tak bardzo ciężko ludziom przychodzi.

Nie optymalizować nie oznacza nie myśleć, a niestety dla wielu "programistów" tak właśnie jest.

I tutaj pojawia się mały problem, czy to jest rzeczywiście błąd? A może brak optymalizacji? Ciężko jednoznacznie określić, a zdania są podzielone. Jednak ja bardziej skłaniam się ku stwierdzeniu, że to podchodzi już pod optymalizację. Może nie taką stricte wielką optymalizację, ani przedwczesną, ale w jakimś małym kawałku jest to jednak optymalizacja, która powinna być już wrodzona w wielu podobnych przypadkach.

Jak widać, w programowaniu nie można "wyłączyć" optymalizacji i myślenia, kosztem tworzenia paskudnego kodu. Wszystko musi być wyważone w odpowiednich proporcjach, inaczej popadamy z jednej skrajności w drugą. Co nie oznacza, że mamy o wszystkim zapomnieć, bo jest to złe.

Dużo osób argumentuje to tym, że przecież mamy takie "wypasione" kompilatory, które za nas wszystko zrobią. Zrobią wiele, ale na pewno nie wszystko. Nie będą za Ciebie myśleć!

Ktoś inny może powiedzieć, że po co optymalizować, skoro koszt procesora/pamięci/dysku maleje w szybkim tempie, a koszt pracy programisty drożeje. Prawda, ale jakież było wielkie oburzenie po opublikowaniu wymagań nowego systemu Microsoftu - Visty, który niby wymagał "kosmicznych" zasobów. Ale, chwileczkę, przecież koszt tych zasobów jest niski, więc o co chodzi?!

Wszystko jest potrzebne, ale w rozsądnych ilościach i granicach. Optymalizacja w minimalnym wydaniu nie jest złem, ale olanie całkowite optymalizacji i złożoności tworzonego systemu jest wielkim błędem.

Brak optymalizacji nie zwalnia z myślenia!

3 thoughts on “Programowanie wymaga myślenia!”

  1. int strlen(const char* str)
    {
    	int len = 0;
    	while (*str) len++;
    	return len;
    }

    Kolego, masz tutaj błąd – to nie ma prawa zadziałać, bo należy jeszcze dodać 1 do wskaźnika, sam operator wyłuskania nie zrobi tego

    Poprawny kod:

    int strlen(const char* str)
    {
    	int len = 0;
    	while (*str++) len++;
    	return len;
    }

    Pozdrawiam.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *