Wpis z mikrobloga

Skoro takie pojawiło się zainteresowanie tematem, to jedziemy.

Ja wiem, że pierwsze tematy mogą być nudne, smutne i mało interesujące dla kogoś, kto cośtam już umie i wie. Niemniej jednak uwazam, że nie byłoby to kompletne bez wspomniania paru oczywistości.

Na poczatku parę uwag:
0. Tekstu będzie raczej dużo.
1. Po raz kolejny przestrzegam, że nie zależy mi na pisaniu w stylu "uczta się pajtona to będzie 15k" albo "naucz się springa w emfałce". Moim celem jest spojrzenie na szeroko pojęty problem wytwarzania oprogramowania, rozwianie paru mitów, pokazanie paru innych, a przede wszystkim pokazanie, że programowanie to tak naprawdę filozofia w ujęciu ścisłym.
2. Niestety, albo i stety, w szeroko pojętej informatyce króluje język angielski i zwroty angielskie będę tu wciskał często. Nie na siłę, ale po prostu dlatego, że tak jest łatwiej, tak się mówi, tak ja mówie. Purrystów językowych zapraszamy, ale nie liczcie na wprowadzanie w życie waszych uwagi. Thanks.
3. Prezentowane są tutaj moje i tylko moje poglądy.
4. Nie zależy mi na byciu ścisłym - nie tym razem, nie o to tutaj chodzi. Jesli napiszę, że i++ jest szybsze niż ++i, a w rzeczywistości jest odwrotnie - to przepraszam, ale chodzi o porównanie a nie o szczegóły implementacji.
5. Mimo nieco krętej drogi zawodowej od pewnego czasu pracuje głównie w Scali/Javie - z domieszką Pythona i łebówki - więc siłą rzeczy bliżej mi do tej strony mocy niż innej. Ale patrz punkt 4.

Zacznę od początku, czyli problemu języków programowania. Oraz dlaczego nie lubie stwierdzeń, że warto się uczyć X a nie Y, czyli dlaczego z pewnego punktu widzenia język jest tylko dodatkiem.

Program, czy programowanie, to w rzeczywistości sprawa bardzo prosta. Komputery, przynajmniej koncepcyjnie, są proste. Procesor, pamięć. Sekwencyjna lista rozkazów, krok po kroku. Czy piszemy w Haskellu, Javie czy C - wszystko prędzej czy później staje się instrukcją procesora. To sprawia, że w gruncie rzeczy wiekszośc języków jest do siebie podobna, a koncepcje nie różnia się - bo i różnić się nie mogą. Bazuja wszak na prostym modelu logicznym.
Sam bardzo często wyobrażam sobie swój kod sprowadzaony do roli prostych, pojedyńczych instrukcji - krok po kroku. Pętla po pętli, funkcja po funkcji. Żmudnę, ale daje rezultaty. Projektując algorytm nie zastanawiam się, czy warunek będzie w nawiasie czy nie i czy porównam typy zmiennych, czy tylko ich wartość (ach to PHP...)..

Ale szybki przegląd podstaw:
Zmienne - Każdy język ma zmienne (no, w Haskellu to różnie z tym bywa). Prosta sprawa. Zmienne mają nazwy. W różnych językach reguły są różne - ale nazwa zmiennej jest zwykle dowolna. Poza nazwą jest wartość. I typ.
W Pythonie zmiennym po prostu przypisuje się wartość, typ niejako przydzielany jest automatycznie. W Javie - trzeba typ podać wprost. Ale w JavaScripcie - typu podawać nie trzeba, ale za to jest keyword var. C#? Prosze bardzo - generalnie składania Javowa, acz dochodzi auto.

Typy danych - Zmienne mają typy. I języki mają typy. I tak naprawdę kazdy język ma nieśmiertelny zestaw - stringi, liczby, booleany. Tutaj chyba nie trzeba nic tłumaczyć. W każdym języku dodawania działa tak samo, podobnie operacje na stringach - wszędzie można je połaczyć i porównać. Inne ciekawe typy to kolekcje - tutaj tez cięzko o zaskoczenie - wszędzie jest coś ala tablica/lista/wektor. Python ma listy i tuple. Java ma dorosłe, typowane kolekcje, w różnych implementacjach. C ma o ile kojarzę jeno tablice. Zasada działania - wszędzie ta sama. Ot, pojemnik.

Instrukcje warunkowe - Zasada jest dokładnie ta sama co ze zmiennymi - wszędzie działają tak samo! Jeśli wyrażenie jest prawdziwe, wykonuje się A, jeśli nie - to B. Czy zapiszesz je w nawiasach jak w Javie, czy z dwukropkiem na końcu jak w Pythonie - to dalej stare, dobre IFy. Czy blok oznacza się wcięciem, klamrami czy jeszcze inaczej - kwestia wtórna.

Pętle - zgadliście - dokładnie to samo. Wszędzie tak samo - wykonywanie w kółko tego samego. A, że raz zapisane jako for(;;), a innym razem jako while()? Kwestia składniowa. Poznałeś pętle w Pythonie? Brawo - umiesz robić pętle w większości języków! Przy pętlach zwykle następuje pierwsze zetknięcie z magią, lukrem czy syntax sugar - w Pythonie można wygodnie przeiterować po kolekcji, podobnie w Javie. Ale z tego co kojarze, już nie w C. Cóż - magia nie istnieje, tymbardziej nie istnieje ona w programowaniu - są to zwykle mniej lub bardziej zawoalowane sposoby na ukrycie nudnego kodu.

KLASY!
Tutaj tak naprawdę pojawiają się jakies większe różnice między językami - część po prostu takich koncepcji nie ma (C), część praktycznie nie ma nic innego (Java). Można w tym miejscu pisać rozprawki o różnych mechanizmach klas, dziedziczenia, obiektowości, prototypach, polimorfimie i tak dalej. Wszystkie ważne i istotne.
W życiu codziennym klasa to po prostu zbiór metod i danych. Czy pełna i poprawna, z getterami i setterami klasa w Javie, czy wszystkiepolawidoczne klasa w Pythonie - cel ich istnienia jest taki sam i pomaga rozwiązac z grubsza ten sam problem. Praktycznie wszedzie występuje tez np. pojęcie konstruktora - wiesz, jak działa kontruktor w C# - brawo, rozgryzłeś podstawy konstruktorów w Pythonie, Javie czy Objectve C. Pisze podstawy bo tutaj pojawia się wiecej różnic.
Niemniej jednak - idea konstruktora czy klasy jest taka sama wszedzie. Jeśli umiesz napisać klasę w Javie - dasz rade zrobić to w Pythonie. Albo C#.

Wyjątki - praktycznie wszystkie języki obecnie mają mechanizm wyjątków - wszystkie wywodzą się chyba z C++ - i zasakakująco najmniej jest tutaj różnic - poza składniowymi, proces wygląda, rzekłbym, identycznie. Raz rzucony wyjątek podróżuje bezkreśnie aż ktoś go złapie.

I tyle- z grubsza. Są oczywiście i inne koncepcje - chociażby generics, czy szablony w C++. Ale znowu, po odarciu ich ze składni - jest to w założeniach prosta koncepcja ułatwiająca typowanie - czasem tylko w czasie kompilacji (types erasure, klasyka rozmów o pracę w Javie), czy gdzieś głębiej (C#) - idea podobna.

Pozostałe rzeczy to szczegóły - i to one stanowią o różnicach między językami. Tutaj można zaczać długi wykład o jawnym i niejawnym przekazywaniu kontekstu, lokalnych obiektach (self w Pythonie vs this w Javie). O tym, który język przekazuje przez wartość a który przez referencje, gdzie stringi stały się wręcz częscią jezyka, a gdzie tylko trochę - bardziej (Java), lub mniej (C), jak porównuje się obiekty, jakie mamy implementacje list w bibliotece standardowej i tak dalej, i dalej i dalej.
Gdzieś słyszałem, że z nauką jezyków obcych jest tak, że pierwszego ciężko się nauczyć, drugi już łatwiej, a trzeci i kolejne to po prostu mieszanka konceptów poznanych wcześniej - podobnie jest w przypadku języków programowania. Tu z własnego doświadczenia powiem, że po nauczeniu się, jak działa przekazywanie przez wartość, a jak przez referencje - zawsze znajdziesz któraś z tych opcji w aktualnym języku. Koncepcje zaczynają się powtarzać, mechaniki są podobne.
Sam tak miałem przy okazji konieczności zagłębienie się w C# niedawno. Po 5 minutowym wstepie do składni byłem w stanie tworzyć całkiem sensowny kod - jedynie sprawdzając co chwila w manualu jak się robi Liste czy w jakim pakiecie szukać czegoś ala Random. Efekt był taki, że poza ponarzekaniem na złe nazewnictwo (serio, zaczynanie pól z wielkiej litery jest głupie...) koledzy od C# niebardzo mieli się gdzie czepić - bo LOGICZNIE wszystko było OK.

Drugą, skoro już tak się rozpisuje, rzeczą o której warto w tym temacie wspomnieć to
MAGIA NIE ISTNIEJE
Cokolwiek by nie pokazywały wam magiczne tutoriale, jak wiele sztuczek nie widać po słynnym "Blog in 20 minutes" w Ruby On Rails - magia nie istnieje. Nie w programowaniu. Bardzo często spotykam ludzi, któzy nie potrafią rozwiązac prostego problemu ze Springiem - bo zawiodła ich "magia" i bezradnie rozkładają ręce. Bo kontroler nie został wywołany i oni nie wiedzą dlaczego.
Dlatego raz jeszcze - magia nie istnieje. Każdy, ale to każdy, kod, akcja, ma swój początek. I jest to dokładnie, z góry określony początek. Każdy program w C zaczyna się od main(), każdy skrypt w Pythonie zaczyna się wykonywac linijka po linijce (tak, importy to też częśc kodu).
Każdy framework webowy ma dokładnie określony entry point - czy to Railsy, Django czy Spring MVC - zawsze jest jakieś miejsce startu. Prawie zawsze jest ono obsłużone przez biblioteke/framework. I w każdym języku/bibliotece krok po kroku można to prześledzić. W tym biznesie nic nie dzieje się "samo".
Dobry, doświadczony programista z pamięci powie, gdzie może leżeć problem. Trafi, albo nie. Lepszy zakasa rękawy i prześledzi cały kod aż znajdzie problem.
I wicie, czemu ten drugi jest lepszy? Bo zna tych kilka koncepcji które opisałem - i posadzony przed czymś, co widzi pierwszy raz w życiu - dojdzie do problemu.

Powiedzmy, że tyle marudnego wstepu. Ale pewne rzeczy trzeba było sobie wyjaśnić.
W nastepnym odcinku chciałbym dokończyć temat poprzez odrobinę smucenia nt. bibliotek standardowych, platformy do "uruchamiania" programów w danym języku oraz krotka opowieść o dobieraniu rozwiązania do konkretnego problemu - tj. czemu nie lubie dużych projektów w Pythonie ;)

Chwilę tez myslałem jak to wszystko rozplanować - po omówieniu wspomnianych tematów chciałem przejśc na dobre do "inzynierii aplikacji", czyli popisać nieco o wymaganiach, planowaniu aplikacji z poziomu zupełnie nie-programownia.
Następnie przekuć te wymagania na solidną, już bardziej programistyczną aplikację, jakie wydzilać sobie warstwy, a zwieńczyć to wszystko testami - mając solidnie podstawy wymagań biznesowych i poprawnie, hm, zarchitekturowanego (!?) kodu.

Kolejne wpisy pod tagiem #abstrakcjaprogramowania !

Wszelkie uwagi mile widziane.

No i wołam zainteresowanych!
@GlenPL: @Sacramoni: @kuite22: @Kain_to_Charlie_a_Delta_to_Kain: @Kapitan_Neuropa: @BuMRK: @kitke: @Gotomb: @Insurgent: @onomatobeka: @unster: @nihil_novi: @CichyGlosZTyluGlowy: @tomek_wcale_nie_tomek: @lubaszka: @Rabusek: @Furious: @kocham_jeze: @rzezimieszek_: @pit0k: @austra:
  • 7