10 pytań przyszłych programistów

Nie, nie chodzi mi o kolejny z tysięcy poradnik o tym, jak nauczyć się Rubiego w 5 minut (nie da się nauczyć Rubiego w 5 minut) albo jak zostać programistą w tydzień (nie da się zostać programistą w tydzień). Zauważyłem jednak w naszym środowisku, tak Eltenowym jak poza-Eltenowym, pewną ciekawą tendencję, którą sprowadzę do twierdzenia "umiem programować". I fajnie, ale… No właśnie, ale.
Nie wiem, czy to stereotyp niewidomego informatyka, czy też fakt, że wymusza się na nas nieco większą wiedzę o zawiłościach komputerowych w stosunku do przeciętnego użytkownika widzącego, czy też inne czynniki, ale świadomość komputerowa bywa dość spora. Pewna garstka z nas, bo jednak grupa ta nie jest bardzo liczna, zaczyna myśleć o nauce programowania. I w tym momencie dzieje się coś dziwnego.
Mamy więc ludzi, którzy naprawdę zdobyli jakąś wiedzę, ale na tym się skończyło, bo albo mają wspaniałe teorie rewolucji świata, które nikną w zderzeniu z rzeczywistością, albo poświęcają pięć lat na wspaniały projekt, który jakoś nigdy nie doczekuje się światła dziennego, albo wciąż czekają na wenę/inspirację/motywację, te jakoś jednak nie przychodzą. I w rezultacie, gdy myślę o niewidomych programistach, prawdziwych programistach, na myśli mam tylko kilka nazwisk.
Pomyślałem sobie więc, że napiszę serię artykułów (ha ha ha, naprawdę wierzycie, że będę miał wenę na pisanie kolejnych), które poświęcę temu, jak zacząć swoją przygodę z programowaniem. Nie chcę, by był to kolejny tutorial w stylu "najpierw naucz się C", ale garść konkretnych porad wynikłych z mojej obserwacji tematu.
Nie mam jeszcze tyle doświadczenia w branży programowania, ile bym chciał. Z wyjątkiem jednak Grzegorza Złotowicza, chyba na Eltenie styczność z tematem miałem największą. Mam za sobą i duży projekt (tu Elten), i kilka mniejszych, także różne zlecenia płatne i współprace nad kodem. I w oparciu o to nasuwa się mi kilka wniosków.
Od razu uczulam, że wpis może być zbyt techniczny, nie przestraszcie się tego. Zakładam jednak, że jako osoby tematem zainteresowane, wiecie już, co to jest C++, innymi słowy to nie jest wpis dla osób, które nie mają o temacie zielonego pojęcia, tu wymagane jest przynajmniej seledynowe. 🙂
Na początek chciałbym odpowiedzieć na 10 najczęstszych pytań, które albo się gdzieś po forach zadaje, albo w domyśle ma się na myśli, albo które mi na myśl przychodzą. Przy założeniu, że pojawią się jakieś komentarze, a mi pomysł z głowy nie wyparuje, w następnym wpisie chciałbym odpowiedzieć na wasze uwagi i skupić się na dziesięciu najczęściej popełnianych na początku błędach.
Dobra, spróbujmy.

1. Czy programista musi być dobry z matematyki?

To pytanie staje się niemal tak nudne, jak szablonowe "How are you", ale wciąż jest kwestią sporów. Kwestią zupełnie dziwną o tyle, że odpowiedź jest po prostu oczywista. Przykro mi, ale tak.
Wiem, że pojawią się pewnie osoby, które zaczną argumentować, że to bzdura, że one sobie radzą, że… Nie, programista musi dobrze sobie radzić z matmą. I nie chodzi tu nawet o rozwiązywanie układów równań różniczkowych, choć na pewnym poziomie zagadnienia np. teorii sygnałów i taka zdolność się przyda. Chodzi jednak o pewną wyobraźnię.
Nie jest ważne, czy programować będziecie w C, czy w Pythonie, na jakim poziomie złożoności i w jakiej branży, elementy logiki, systemu binarnego, obliczeń i oszacowań po prostu okażą się w waszym wypadku niezbędne. Na pewno traficie czasem na potrzebę oszacowania złożoności danego algorytmu albo podzielenia zadania na wątki. Nie ma rady, komputery są na matematyce zbudowane i od matematyki nie uciekną.
Oczywiście pytaniem innym jest, co znaczy "bycie dobrym z matematyki". Znam osoby, które miały z matury rozszerzonej z matematyki naprawdę wyniki średnie, a rozwiązywały od ręki takie zadania, nad którymi ja musiałbym posiedzieć przynajmniej kilka godzin. Znam też osoby, które uzyskiwały świetne wyniki z testów, ale kiedy stawały przed prawdziwym obliczeniem (nie schematycznym zadaniem ze szkoły), pojawiał się problem.
Ale matematyka jako taka jest w programowaniu niezbędna.

2. Od jakiego języka zacząć?

Od jakiegokolwiek, naprawdę. Najbardziej bawi mnie sytuacja, gdy dana osoba zamiast zabrać się do nauki, spędza pół roku na rozważaniu za i przeciw różnych technik, zaczyna jedno i zaraz przerywa, coś tam napisze w języku A, by przejść na B, C i D.
Jedyne ważne jest to, by był to język mainstreamowy, najlepiej należący do najpopularniejszych. Wg portalu Toward’s Data Science, w roku 2020 najpopularniejsze języki to, w kolejności, JavaScript, Python, Java, Go, TypeScript, C++, Ruby, PHP, C# i C. W tej mainstreamowości chodzi o to, by łatwo było znaleźć poradniki i przykłady danego języka, a nie męczyć się z szukaniem odpowiedzi, jak napisać coś w języku znanym przez trzydziestu ludzi w Polsce.
Jako programiści i tak będziecie musieli w praktyce poznać przynajmniej kilka języków biegle, a znośnie właściwie ze 10-20. Będzie jeszcze czas na wybranie tych ulubionych, tym czasem zastanawianie się, co wolicie na samym początku, początek ten tylko oddala.
Są kłótnie i spory, czy lepiej zaczynać od języków strukturalnych czy obiektowych, poznać najpierw podstawy, czy zrobić od razu coś dużego i do podstaw wrócić. Szkół jest tyle, że i tak nie zadowolicie wszystkich, więc spróbujcie po prostu zadowolić siebie.

3. Ile muszę się uczyć przed napisaniem pierwszego programu?

Jak najmniej, bo to pisząc się uczy. I nie ma na to innego sposobu. Nigdy nie poznacie programowania tak naprawdę, jeśli nie wydacie pierwszego, drugiego, dziesiątego projektu. Jeśli spojrzycie na swój kod z przed trzech lat i nie powiecie sobie "Jaki głupek to pisał?", to znaczy tylko tyle, że niczego się nie nauczyliście.
Fakt, dobrze jest rozplanować pracę, ale nie stworzycie dobrego planu bez doświadczenia. W programowaniu są różne wzorce projektowe, struktury danych, rozwiązania i biblioteki. Ale nie ma żadnego poradnika, który dokładnie wam wyjaśni, jakie rozwiązanie pasuje do jakiego problemu.
Po pierwsze dlatego, że taka książka miałaby z milion stron, a po drugie, że to także od waszego indywidualnego stylu będzie zależało.

4. A ten pierwszy program, to co to ma być?

Coś małego, użytecznego, ale prostego. Często słyszę o programistach (choć akurat widzących), których gubią nadmierne ambicje co do pierwszego projektu.
Jeśli zaczniecie od pisania na przykład nowego edytora dokumentów PDF albo klienta Facebooka, to raczej daleko nie zajdziecie. A przecież są inne, małe zadania, które można sobie uprościć.
I co, że na początek program będzie pisany w konsoli? Ważne, by działał.
Jeśli macie komu, pokażcie kod, bądźcie otwarci na sugestie. A potem napiszcie coś nowego. I nowego. Z biegiem czasu przyjdzie czas i na interfejs graficzny, i większe wyzwania.

5. Z innej bajki, jaki edytor na początek?

A nawet niech będzie to i Notatnik. To nieśmiertelne rozwiązanie, które będzie wam towarzyszyło do szybkiego szkicowania już na zawsze. O nowym edytorze czas pomyśleć wtedy, gdy pojawi się taka potrzeba. Na początek macie się nauczyć programowania, a nie obsługi złożonych narzędzi.
A jeśli wam jednak mimo wszystko od razu zależy na profesjonalnym wyglądzie albo już tego następnego narzędzia szukacie, to ja zdradzę, że pracuję w Visual Studio Code oraz Vimie.

6. Czego jeszcze trzeba się nauczyć, prócz języka programowania?

To dość złożone zagadnienie. Generalnie zanim sięgniecie głębiej do istoty tematu, naprawdę uznajcie, że coś umiecie. Analiza złożonych przypadków bez ogólnego pojęcia w temacie jest jak uczenie się gramatyki języka bez słówek.
Nie odkładajcie tego jednak też zbyt daleko. Pewne wzorce, struktury i pomysły w programowaniu powstawały przez lata nie w celu utrudnienia, ale uproszczenia wam życia. I nauczenie się poprawnej implementacji gotowych rozwiązań nie tylko wam uprości pracę, ale i sprawi, że będzie ona czytelniejsza dla innych.
Z drugiej strony nic na siłę. Często widuję kody początkujących programistów, które są tak na siłę budowane wedle wzorców projektowych, że wyglądają jak jakieś przykłady encyklopedyczne, a nie gotowe aplikacje, a ich czytelność, miast zyskiwać, traci. To po prostu kwestia wprawy, kiedy coś się przyda, a kiedy trzeba machnąć na to ręką.
Jak już wydacie kilka projektów z GUI, na pewno polecam zapoznanie się z tematem najpopularniejszych szablonów aplikacji (MVC, MVVM, MVP), jak również z najważniejszymi wzorcami projektowymi i strukturami danych. Gorąco też polecam książkę pt. "Programowanie współbieżne i rozproszone" autorstwa panów Zbigniewa Weis oraz Tadeusza Gruźlewskiego, która w moim wypadku była bardzo ważnym podręcznikiem dobrych praktyk algorytmicznych.

7. Kiedy używać tych klas, interfejsów?

Dość często zauważam, że osoby uczące się programowania, nie do końca łapią się w tym, kiedy stosować które narzędzia. Dostajemy więc aplikacje napisane np. w C++ zawierające 80 funkcji i ani jednej klasy, z jakimiś dziwnymi zmiennymi albo, najgorsza praktyka z możliwych, tablicami, w których elementy o danym indeksie oznaczają dany zasób, ale schemat tworzenia ich występuje naturalnie tylko w głowie twórcy.
Czasami jest to zachowanie korzystne, ale w zdecydowanej większości przypadków nie. Dlatego warto eksperymentować z nowo poznawanymi elementami programowania obiektowego lub strukturalnego. Wszystko się jakoś samo poukłada, kiedy zauważycie, co pomaga, a co nie.

8. Ile plików ma mieć mój program?

To jest generalnie ciekawe zagadnienie i nie ma na nie dobrej odpowiedzi. Zależy to od ilości plików, pomysłu na organizację kodu i preferencji twórcy. Czasem wygodniej jest mieć pliki giganty, czasem lepiej mieć dużo karłów.
Na pewno jednak należy unikać dwóch skrajnych sytuacji, gdy program ma 10 plików po 10 linijek albo jeden plik zawierający linijek 38520. Generalnie na początku najlepszą praktyką jest dzielenie programu wg zastosowania.
Jeśli piszę więc kalkulator, jeden plik może odpowiadać za interfejs graficzny, drugi za obliczenia, a trzeci za przekazywanie informacji między jednym a drugim. I tak, to jest klasyczny przykład schematu MVC typu 2, mówiłem, że szablony i wzorce są przydatne.

9. Optymalizować, czy nie optymalizować?

Oto jest pytanie!
Współcześnie bardzo się zaciera granica między tym, kiedy kod lepiej optymalizować, a kiedy dbać o jego czytelność. W czasach, kiedy platforma Dotnet używa wirtualnej maszyny do wykonywania kodu, naprawdę sprawa staje się złożona.
Z jednej strony, kiedy mamy za zadanie posortowanie gigantycznej listy, na pewno będziemy zastanawiać się nad najlepszym algorytmem. Zwłaszcza, gdy w grę wchodzi przycinanie się programu.
Z drugiej strony mamy na przykład wybór większej wartości. Załóżmy, że mamy dwie liczby i zastanawiamy się, która z nich jest większa. Pokażę to na przykładzie zmiennych a i b, chcemy w zmiennej x zapisać większą z nich.
Najprościej zrobić to tak:
Jeśli a jest większe od b, zapisz x równe a,
w przeciwnym wypadku zapisz x równe b.
W języku C++:
if(a>b) x=a;
else x=b;
Czy można zrobić to wydajniej? Oczywiście!
Zapiszemy, że x jest równe różnicy a oraz wartości powstałej z iloczynu bitowego różnicy a i b oraz różnicy a i b przesuniętej bitowo o rozmiar w prawo.
x = a – ((a-b) & ((a-b) >> sizeof(x)*8-1));
Gratuluję! Właśnie stworzyliśmy wspaniale wydajny kod! Wydajny w każdym razie dla komputera, bo jak za tydzień będziemy go czytać, spędzimy na pewno dobrych kilka sekund zastanawiając się, jak to ma działać, co robić i obiecując sobie, że od tej pory będziemy programować tylko na trzeźwo.
Dla jasności, są sytuacje, gdy takie sztuczki naprawdę się przydadzą. Jeśli dysponujemy ograniczoną pamięcią lub mocą obliczeniową, bez nich się nie obędziemy. A to nie jest aż tak nieprawdopodobne, wszak mikrokontrolery są wszędzie, a rzadko który przekracza 4kB pamięci RAM i 16MHz.
Ale po pierwsze, wtedy stosuje się makra, a po drugie… Uznajmy, początkujący programiści nie piszą oprogramowania dla mikrokontrolerów.

10. Jak się ćwiczyć w programowaniu?

To chyba najważniejsza sprawa. Programowanie to przede wszystkim gra wyobraźni. Trzeba się nauczyć algorytmicznego myślenia, odruchowego rozwiązywania kłopotów.
Wiele jest żartów o programistach, które jednak doskonale to lustrują. Ja przytoczę dwa.
Pierwszy z nich: Jak zająć programistę? Dać mu kartkę z napisem:
Przeczytaj poniższą linijkę.
Przeczytaj powyższą linijkę.
Drugi natomiast: Żona do męża programisty:
– Kup chleb, a jak będą jajka, kup 10.
Nasz programista wchodzi więc do sklepu i pyta: "Są jajka"?
– Są – odpowiada ekspedientka.
– To poproszę dziesięć chlebów.
Komputer to taka maszyna, która robi tylko i dokładnie to, co jej każemy. A początkujący programiści mają taką skłonność do myślenia po ludzku, nie zaś po komputerowemu. I z tego wynika masa błędów.
Z drugiej strony doświadczeni programiści mają skłonność odwrotną i… też bywa ciekawie.
Na koniec pozostawiam was z zagadką logiczną, którą powinno się zadawać na pierwszych zajęciach z programowania, a jakoś się tego nie robi.
Jasiu dostał pięć jabłek i zjadł dwa. Ile jabłek ma Jasiu?
Zapraszam do odpowiadania w komentarzach.
Ufff, przebrnęliśmy przez to. Wiem, że wpis był nieco chaotyczny, ale mam nadzieję, że dla kogoś będzie jakąś tam podpowiedzią.
Zapraszam do zadawania wszelkich waszych pytań w komentarzach, spróbuję na nie odpowiedzieć, a będą one tylko motywacją do napisania jednak tego następnego wpisu.
Jeśli będę widział zainteresowanie, następnym razem omówię 10 grzechów głównych początkujących programistów na Eltena i Eltenowiczów przykładzie. 🙂
Z pozdrowieniami,
Dawid Pieper
Chociaż raczej powinienem napisać
446177696420506965706572

20 komentarzy

  1. Nie. Bo nie wiemy, ile Jasiu na początku miał jabłek. 😀
    To w programowaniu klasyczny błąd niezerowanej pamięci. Można coś takiego zobaczyć na przykładzie takiego prostego kodu w C.
    #include <stdio.h>
    int num;
    int main(void) {
    num+=5;
    num-=2;
    printf("%d", num);
    return 0;
    }
    W tym przykładzie do zmiennej num dodajemy 5 i odejmujemy 2. Na wyjściu jednak możemy dostać cokolwiek, czasem 3, czasem 5812311.
    Niezerowanie zmiennych to jeden z najczęstszych błędów w programowaniu niskopoziomowym i chyba nie ma projektu pisanego w C, w którym nie zdarzył się choć raz, wliczając w to kod Eltena.
    Oczywiście mówię tu o bardziej złożonym przykładzie błędu. Rzadko się zdarza coś aż tak oczywistego i dotyczy niemal wyłącznie programów początkujących programistów.
    Ale niewyzerowanie pamięci struktury, nieprzeniesienie tzw. nullowej terminacji ciągu znaków albo przekazywanie nieczystych danych do funkcji bibliotecznych? Ojjj, to w programowaniu bardzo częsty błąd.

  2. wyobraźnia matematyczna, zgoda. Sama matematyka w postaci wzorów, twierdzeń, w grach i innych tego typu produkcjach. Ale sama matematyka jeszcze bardzo pomaga przy zrozumieniu podstaw podstaw działania komputera. Chociaż dzisiejszy przeciętny programista nie potrzebuje się wgłębiać aż tak bardzo, aż do samego dna. Dziś w pewnym sensie programowanie jest dużo łatwiejsze.

  3. Pytanie brzmi, co uznasz za matematykę. Bo jednak wyobraźnia wyrażenia x%y też nie jest tak oczywista.
    Matematyk mógłby przekonywać, że matematyka stoi za każdym ifem. Za to inna osoba, że to wszystko naciągane.
    Faktem jest, że w każdym aspekcie wyobraźnia matematyczna jest konieczna. Wzory i definicje to sprawa drugo albo i trzecioplanowa.

  4. A to jest dobry przykład. Ale zapomniałeś o tym, że Elten ma własne enkodery Opusa i Vorbisa, oczywiście pisane w oparciu o libopus i libvorbis, ale bez matematyki i tak się nie obyło. 😀
    Pomijając je jednak, na pewno w oskryptowaniu dźwięku, gdzie pojawiła się trygonometria. Zwłaszcza tego dużo w powstającym komunikatorze, gdzie pewne pomysły wymusiły nieco przestrzennego podejścia do sprawy.
    No i cała klasa do opisu mapek trygonometrią stoi.
    Logarytmami posiłkowałem się przy niektórych projektach. Nie ma ich w kodzie, ale szacowałem wydajność algorytmów sortujących np. przy sortowaniu wątków. W skrajnym wypadku Elten potrafi tych wątków pokazać na chwilę obecną 4983 i okazało się, że wbudowana w Rubiego funkcja sort dość mało wydajnie sobie z tym radzi, generując dobre trzy czy cztery sekundy zawieszenia, musiałem implementować sortowanie we własnym zakresie, gdzie właśnie logarytmika posłużyła do oszacowania wydajności różnych podejść do sprawy.
    Matematyka, a konkretniej logika rozmyta, stoi za funkcjami najpopularniejszych wątków i blogów wśród znajomych, gdzie obliczenia są wykonywane z pomocą algorytmu KNN.
    Pewnie coś jeszcze by się znalazło. Ale jak na 6 lat, nie ma tego bardzo dużo.

  5. Bo trzeba być dobrym z matematyki, a nie ze wzorów. Chociaż jestem przekonany, że przynajmniej raz w programowaniu przydała Ci się trygonometria. Albo dwa. Albo… No, dużo razy.
    Właściwie każdy program w jakikolwiek sposób bazujący na przestrzeni (czy to dźwięku 3d, czy planie miasta, czy będący grą), w pewnym momencie stawia pytanie o kąty i odległości.
    Podobnie podstępnie potrafią atakować logarytmy i silnie. 😀

  6. Co do "bycia dobrym z matematyki" uważam, że kwestia jest nieco bardziej złożona i skomplikowana, niż to tutaj przedstawiłeś.
    Faktycznie, wymagana jest wyobraźna matematyczna i przede wszystkim logiczne myślenie, ale jakby nie patrzeć matematyka, której uczą nas w szkołach opiera się głównie na kuciu do głowy formół, wzorów, dowodów i twierdzeń, a w dzisiejszej dobie wszelkiego rodzaju portali typu Stackoverflow czy MSDN, umiejętność zapamiętania dwudziestu stron tekstu w trzy minuty jest tylko przyjemnym dodatkiem do całości, a nie rdzeniem.
    Ja z kolei przy początkach mojej nauki z programowaniem miałem inną wątpliwość, a mianowicie "czy ja kurwaj estem do tego stworzony"? I to w sumie nęka mnie do dziś. Pytanie, ile predyspozycji do bycia "dobrym programistą" ma się od urodzenia a ile można po prostu nabyć wraz z doświadczeniem, ergo ukończonymi projektami.
    Dalej mam wrażenie, że na programowanie jestem po prostu "za głupi", ale czasem ten schemat niejako mi się wyłącza, kiedy udaje mi się wyłamać z konwencji i zrobić coś ciekawego, o chodźby do szuflady, jak na przykłąd wtyczkę VST w Pure Basicu. Strach jednak pozostaje.

Dodaj komentarz

EltenLink