Programowanie wymaga myślenia!

Programowanie, optymalizacja i myślenie...

Sztuka programowania łączy w sobie te trzy sfery, umiejętne ich wyważenie staje się dobrym wyznacznikiem dla programisty. Bez jakiegokolwiek z nich traci on swój potencjał i staje się zwykłym koderem, klepiącym bez namysłu kod jaki inni mu każą. 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 wielkim 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ć. Tak jak w życiu bywa wszystko zależy od wielu czynników.

Wiele zależy rownież od zdefiniowania granicy miedzy błędem a optymalizacją w czasie pisania aplikacji. Brak przewidywania i myślenia w czasie pisania kodu często prowadzi do błędów 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 minimalnej 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. Jak w ogóle mogło do tego dojść?!

W takim kodzie 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ć?

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 kod zamiast jednej iteracji wykonuje ich miliony! Niepotrzebnie!

A można byłoby tylko trochę, minimalnie pomyśleć, a wszystko osiągnęlibyśmy w jednej iteracji ciągu, 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) {
...
}

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

Nie optymalizować nie oznacza nie myśleć, a niestety dla dużej ilości "programistów" tak właśnie jest.

I tutaj pojawia się mały problem, czy to 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 optymalizację, ale w jakimś małym kawałku już tak.

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 wszystko na pewno nie. 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.

Jakie wielkie było 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 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 przemyślenia nt. „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 *