Zaloguj się

Jog Jajcusia

xmpp:jajcus@jajcus.net

Powrót na stronę główną

Coś dla nieprzekonanych do dynamicznego typowania

Natrafiłem dzisiaj na artykuł Bruce'a Eckela Strong Typing vs. Strong Testing. Autor, znawca języków programowania, znany autorytet w tej dziedzinie (autor słynnej książki Thinking in Java), opisuje w nim jak przekonał się do dynamicznego typowania mimo, że wcześniej za jedyne słuszne uznawał statyczne systemy typów. Oczywiście język z dynamicznym typowaniem, którym się zachwyca, to Python. Interesująca jest też kontynuacja tematu — odpowiedź na list profesora, który z poprzednim artykułem się nie zgadza. Blog Bruce'a Eckela dodałem do linkowni — czuję, że będę tam często zaglądał.

Miłe jest, że do Pythona przekonuje się coraz więcej znawców poważnych języków i miłe jest, że potrafią opisać czemu Python jest taki dobry — zawsze to kolejne argumenty do przekonania nieprzekonanych. Co do statycznego typowania, to też nie uważam tego za coś niezbędnego, ale raczej, że w większości przypadków przeszkadza, jednak nie jestem też przeciwnikiem wprowadzenia takich, opcjonalnych oczywiście, rozszerzeń do Pythona. Dobrze czasem jest mieć możliwość zaznaczyć w kodzie dla jakich argumentów jest on przygotowany. Często jest to istotna informacja dla innych developerów (ale tu wystarcza odpowiednia dokumentacja) i dla interpretera/kompilatora (pozwala na lepszą optymalizację krytycznych elementów kodu). Problem polega na tym, żeby wprowadzić to nie psując przejrzystości i elastyczności języka i aby nie było to nadużywane.


Komentarze

Piotr Kochański

17 marca 2005 11:47:12

Taaa, Eckelowi ostatnio się trochę poprzestawiało. Oprócz statycznego typowania wziął sobie na cel sprawdzane wyjątki w Javie, bo niby strasznie komplikują kod. Jak się ich nie umie stosować, to faktycznie komplikują, a jak ktoś słyszał o łańcuchach wyjątków, to okazuje się, że wszystko jest proste i eleganckie.<br><br>
Co do dynamicznego typowania, to używając często PHP muszę przyznać, że bardzo cierpię z powodu braku statycznego typowania. Mam jakąś funkcję/metodę w klasie, to zanim jej użyję, muszę sprawdzać print_r(...), co ona właściwie zwraca , podobnie trzeba się szarpać z argumentami.<br><br>
Oczywiście sprawę załatwia dokumentacja, tylko, po pierwsze musi być, a jeśli sami coś robimy, to musimy ją sami napisać. I tu jest zabawna rzecz. W Javie JavaDoc sam nam wygeneruje dokumentację dotyczącą typów argumentów i zwracanych wartości. W Pythonie jak te świstaki, zamiast kod pisać, to dziergamy dokumentację. Zmienimy argumenty w metodzie, to w Javie JavaDoc automatycznie to uwzględni, a w Pythonie? Poprawiamy sami, chyba, że zapomnimy<br><br>
Kolejna sprawa, to fakt, że dynamiczne typowanie jest często fikcją, o czym można się łatwo przekonać definiując w Pythonie 'tuple' z jednym elementem, robimy to tak:<br>
<pre>mojatupla = 'hello',</pre><br>
warto zwrócić uwagę na przecinek na końcu, to on wskazuje, że mamy do czynienia nie ze Stringiem a z Tuplą. Ja już wolę oznaczać typ zmiennej słowem kluczowym, niż przecinkiem, ale to już kwestia gustu.<br><br>
Wielu ludzi zapomniało, po co Java została utworzona. Nie tworzone jej, żeby można było w niej pisać programy szybko. Stworzono ją po to, żeby można pisać w niej niezawodne programy, po to statyczne typowanie, wyjątki, maszyna wirtualna itp.<br><br>
W Pythonie, żeby można mieć zaufanie do programu, to trzeba napisać kilobajty testów jednostkowych. W Javie też pisze się bardzo często testy jednostkowe (tam to już jest standard), ale przynajmniej nie trzeba napisać tego tyle, co w Pythonie, bo wiele rzeczy po prostu sprawdza kompilator. I znowu w Javie piszemy kod, a Pythonie odwalamy robotę kompilatora.<br><br>
Z tymi modami na języki programowania, to trzeba uważać... :)

Jajcus

17 marca 2005 12:30:26

„Mam jakąś funkcję/metodę w klasie, to zanim jej użyję, muszę sprawdzać print_r(...), co ona właściwie zwraca , podobnie trzeba się szarpać z argumentami.”

To tylko źle świadczy o bibliotece która udostępnia tę funkcję. To co ona zwraca powinno być oczywiste (istnieją pewne konwencje), albo opisane w dokumentacji lub w przykładach.

„Kolejna sprawa, to fakt, że dynamiczne typowanie jest często fikcją, o czym można się łatwo przekonać definiując w Pythonie 'tuple' z jednym elementem, robimy to tak:
mojatupla = 'hello',”

1. Co to ma do dynamicznego typowania? Odbiedy coś może ze słabym typowaniem, ale właściwie to kwestia składni.
2. To powinno być: mojatupla = ('hello',)
(to że się da inaczej, to wynika ze "specjalnego przypadku", który jest przydatny w innych sytuacjach)

„W Pythonie, żeby można mieć zaufanie do programu, to trzeba napisać kilobajty testów jednostkowych. W Javie też pisze się bardzo często testy jednostkowe (tam to już jest standard), ale przynajmniej nie trzeba napisać tego tyle, co w Pythonie, bo wiele rzeczy po prostu sprawdza kompilator”

Załóżmy, że mamy funkcję, która ma mnożyć dwie liczby całkowite:

Żeby to dobrze sprawdzić w Javie należałoby w testach uwzględnić mnożenie jakichś charakterystycznych liczb, np.:

funkcja(0,0) == 0
funkcja(5,0) == 0
funkcja(5,1) == 1
funkcja(5,5) == 25
funkcja(5,-5) == -25
funkcja(-5,-5) == 25

Ten zestaw testów sprawdzi najważniejsze cechy mnożenia.
A w Pythonie? W Pythonie będzie dokładnie taki sam zestaw testów. Bo sprawdzamy tę samą funkcjonalność. Jeśli program jest poprawny, to poprawnie wykonuje to czego od niego chcemy. W Javie najwyżej część błędów wykryłby już kompilator, ale dopiero zestaw testów może zaświadczyć o poprawności programu. W Pythonie żaden dodatkowy test z powodu dynamiczności nie jest potrzebny.

A teraz potrzebujemy funkcję mnożącą dwie liczby zmiennoprzecinkowe...

W Javie trzeba napisać nową funkcję (prawdopodobnie przy użyciu cut&paste) i nowy zestaw testów do niej.

W Pythonie wystarczy dopisać testy dla argumentów rzeczywistych i poprawić odpowiednio tę funkcję, żeby z nowymi testami też działała. Najprawdopodobniej nic nie będzie trzeba poprawiać. Dla liczb zespolonych też nie.

To oczywiście bardzo prosty przykład, ale tak podobnie to działa dla większych projektów.

Jajcus

17 marca 2005 12:31:13

PS. nie znam Javy. Jeśli w powyższym rozumowaniu popełniłem błąd z tego wynikający, to przepraszam.

mmazur

17 marca 2005 18:36:28

Hehe. Nie wiedziałeś, że Eckel lubi Pythona? :)

Jajcus

17 marca 2005 18:40:02

mmazur: nie. W ogóle wiele o nim nie wiedziałem. Słyszałem o Thinking in Java, o Thinking in C++, które podobno od tego pierwszego gorsze... i tyle. Dopiero jak dzisiaj trafiłem na te artykuły, to dowiedziałem się coś więcej i chyba polubiłem gościa :-)

str()

18 marca 2005 13:20:03

Troszkę dziwią mnie przykłady Eckela. Narzeka on na konieczność zachowania zgodności poprzez rzutowanie w górę i że jest to czaso/pracochłonne i mu się cykle marnują. Z całą pewnością jest autorytetem w dziedzinie programowania (TIJ jest świetnie napisana), ale mam podejrzenie, że nie tworzył nic dużego w PHP - z całą pewnością doceniłby upcasting. Z resztą, nie trzeba od razu budować klas, wystarczyłby mu
interface Gadatliwy { public void gadaj() throws Chrypa; }
oraz class Dog implements Gadatliwy.

Silne typy są nie do przecenienia. Doceniam to ilekroć zastanawiam się czy metoda zwróci NULL, FALSE czy array(). A siedzimy przecież z co-koderem dwa metry od siebie i wystarczy zapytać. Tylko pytać trzebaby było co chwilę i tu widać, że siła dobrego języka i środowiska polega nie tyle na udostępnianiu jakiejś killer-funkcjonalności, tylko eleganckim i wygodnym połączeniu drobnych udogodnień jak wyjątki, silne typy, interfejsy, iteratory, itd.

Czekając z utęsknieniem aż przeniosą mnie w firmie na PHP5 wyglądam w kierunku następnych wersji, w których chętnie widziałbym _obowiązkowe_ silne typy z _możliwością_ zrelaksowania ich ogólnym typem mixed lub object.

mmazur

18 marca 2005 15:03:46

Jeśli interesuje cię rozróżnienie na NULL, False i pustą/pełną tablicę, to znaczy, że język jest okdr. W pythonie zawsze po prostu piszę if not cośtam.

I owszem, statyczne typowanie pewnie czasami jest przydatne, ale nie w standardowych zastosowaniach, gdzie znacznie wygodniejsze są odpowiednie konstrukcje języka + standardowe operatory jakie można przeciążać przy obiektach (iteracja, odwołanie do elementu, sprawdzanie czy pusty, etc. etc.).

Jajcus

18 marca 2005 15:12:00

mmazru: pisanie zawsze „if not cośtam” niekoniecznie jest dobrym pomysłem. Brak napisu i napis o długości 0 to dwie różne sprawy. Więc, jeśli interesuje Ciebie czy coś jest None, to piszesz „if cośtam is None”. Przy okazji to będzie szybsze.

Ale jeśli nie jest oczywiste, czy funkcja zwraca NULL, False, czy pustą tablicę, to gdzieś jest problem. A jeżeli podobna rozterki pojawiają się co chwilę, to znaczy że jest bardzo duży problem z konkretnym API — jest niekonsekwentne i niedodokumentowane. Nawet przy ścisłej, statycznej kontroli typów tak utrzymywane API będzie powodować problemy. Bo jeśli będziemy nawet mieli podane na „tacy” że argumentem jest tablica napisów, to niekoniecznie z tego wynika co te napisy oznaczają. Poza tym, zadaniem kompilatora/interpretera nie jest przecież wymuszanie dokumentacji.

D-

20 marca 2005 00:33:57

Że Eckel lubi Jave i Pythona to rozumiem.
Ale on nawet PHP lubi, a tego to ja już nijak nie rozumiem
:-\

s

21 marca 2005 14:14:46

Niewątpliwie BE jest geniuszem wszechczasów ale imho
"znawcą języków programowania" nazwać go nie można.
Mimo najlepszych chęci.

str()

22 marca 2005 13:17:10

mmazur, Jajcus: PHP jest okdr. W tym konkretnym przypadku jest nawet bardzo. Nawet gdyby przyszedł jakiś faszysta i określił jasno API, to i tak łowienie błędów będzie utrudnione, no bo przecież wg. interpretera PHP array("ściema") == TRUE, itp. A tu właśnie chodzi o testowanie i poprawianie - gdzie przyszła zła dana, która przeleciała przez pół systemu i zabiła proces Postgresa.
Dlatego czekam na type hinting w PHP5.
A poza tym lubię ten język mimo jego fatalnych braków i felerów. Dzisiaj np. potrzebowałem użyć statycznej zmiennej składowej - Rasmus, Zeev i Andi musieli byś ostro pijani gdy to projektowali.
mmazur: Zgodzę się, że dynamiczne typowanie może być przydatne. Również jestem zdania, że słabe typowanie należy stosować tylko tam, gdzie jest to absolutnie niezbędne, ew. gdy oszczędzamy sporo kodu i staje się on czytelniejszy. W projekcie, który liczy (clickety click, grep grep) 1790 klas to prawdziwa udręka przy debugowaniu.

mmazur

22 marca 2005 17:40:21

1790 klas? A to oby na pewno sens trzymać to wszystko w jednej aplikacji? Bo jeśli przyjąć założenie, że beztypowość pythona powoduje, że nadaje się on co najwyżej do aplikacji średniej wielkości, to wniosek jest automatycznie taki, że python zniechęca do tworzenia zajebiście dużych monolitów. I to jest prawdę mówiąc good thing.

Jezuch

22 marca 2005 20:14:29

A ja dziś w pracy wklepałem w Intranecie komentarz do zadania: "Jeszcze jedno zadanie z PHP i zastrajkuję". Jestem tam, do diabła, zatrudniony jako programista Java! Czy to oznacza że jestem taki genialny, że wszystko zrobię w każdym języku? :>

str()

23 marca 2005 13:06:06

O dużych projektach i programistach interesująco i z doświadczenia MiMaS: http://mimas.ceti.pl/tarpit/wpis/1111477702

str()

23 marca 2005 13:07:02

Eeeh, pomyłka: http://mimas.ceti.pl/tarpit/wpis/1111059734

str()

23 marca 2005 13:11:08

Eeeh, pomyłka: http://mimas.ceti.pl/tarpit/wpis/1111477702

Dodaj nowy komentarz

Dostępne jest formatowanie Textile

Podpis:
Treść:
Strona WWW (opcjonalnie):
Wpisz kod:code
 
 

Śledzenie komentarzy (RSS) TrackBack URI


[szpieg] Jesteście obserwowani...