Od długich lat trwają w różnych środowiskach ożywione dyskusje na temat zalet i wad poszczególnych języków programowania. Naturalnie dywagacje tego typu dotyczą także Perla (o dziwo najczęściej prowadzą je programiści Pythona, którzy wiecznie poszukują uzasadnienia, że Python jest lepszy od Perla :) ). Nie zamierzam tutaj analizować pojawiających się argumentów, skupie się jedynie na zestawie subiektywnie wybranych aspektów, których omówienie może dostarczyć postronnemu czytelnikowi pewnych praktycznych wskazówek.
Zastosowania
Programiści Perla oczywiście powiedzą, że Perl nadaje się do wszelakich zastosowań. Trzeba przyznać, że stwierdzenie to jest całkiem bliskie prawdzie. Nie oznacza to jednak, że język ten sprawi się równie dobrze w każdym scenariuszu. Według mnie, Perl stanowi dobry wybór do masowego przetwarzania danych (także w modelu współbieżnym i rozproszonym), czynności administracyjnych (głównie pod systemami Unix/Linux), wszelkich operacji na plikach, komunikacji sieciowej, aplikacji webowych (mod_perl), aplikacji serwerowych. Nie używałbym natomiast Perla do budowy aplikacji desktopowych (napisanych np. w Perl/Tk), choć widziałem już udane projekty tego typu. Po prostu inne technologie sprawdzą się w tym zadaniu lepiej - m.in. ze względy na szybszy i łatwiejszy proces produkcji. Nie jest prawdą, że w Perlu nie można programować obiektowo. Otóż z powodzeniem można, ale OOP stanowi tylko swoiste rozszerzenie tego języka i nie wynika z jego założeń, jak w przypadku choćby C#.
Perl został stworzony jako wolne oprogramowanie pod systemy unixowe, ale od dawna dostępny jest także na inne platformy - Win32 (jest też wersja x64), Mac OS czy Solaris. Odpowiednio napisany kod, w który zrezygnujemy z elementów platform-specific, będzie więc bardzo łatwo przenaszalny. W Perlu obserwuje się ostatnio dynamiczny rozwój skrzydła Win32 - i rzeczywiście trzeba przyznać, że interpreter działa na Win32 zarówno stabilne (w skali Windowsa), jak i niewiele mniej wydajne niż w przypadku systemów spod znaku pingwina.
Istotną siłę Perla stanowi bogactwo dostępnych modułów zgromadzonych w CPAN (Comprehensive Perl Archive Network,
http://cpan.org). Programowanie w Perlu sprowadza się więc najczęściej do umiejętności wyszukiwania i wykorzystywania poszczególnych modułów, gdyż na 90% ktoś napisał już to, co jest nam potrzebne :) Co więcej - napisał to nieźle. Akurat pod względem ilości dostępnych bibliotek z Perlem nie może się równać żaden inny język skryptowy, a jest to na pewno jedna z tych cech, które powinny mieć spory udział w decyzji o zastosowaniu konkretnego języka programowania.
Składnia
Składnia Perla jest jedną z tych cech, która czyni ten język bardzo specyficznym, bywa też często krytykowana. Podnoszony jest m.in. argument, że przez możliwość zapisania takiego samego polecenia na szereg różniących się i mało intuicyjnych sposobów kod traci na przejrzystości. Z drugiej strony składnia Perla daje deweloperom swobodę kreowania kodu według własnych potrzeb i umiejętności. Istotnie, dla przeciętnego programisty losowy fragment kodu napisany w Perlu będzie trudniejszy do zrozumienia niż w przypadku C#, Javy czy Pythona. Powiem więcej, składnia Perla wręcz zachęca do pisania trudnego w utrzymywaniu kodu, którego później nie zrozumie nawet jego twórca. Nie oznacza to jednak, że w Perlu nie można pisać porządnie - otóż można. Krytyka języka (zwłaszcza ze strony amatorów języków bardzo przejrzystych składniowo - np. Pythona) opiera się na założeniu, że każdy programista jest niechlujem i prędzej czy później pójdzie na totalną łatwiznę na zasadzie "byle działało". Rzeczywiście, jeżeli mamy takich programistów w zespole, to Perlem zrobią krzywdę i sobie i projektowi. Jeżeli natomiast będziemy trzymali się wcale znowu nie trudnych do wdrożenia zasad, pisali kod w ustalony sposób, z komentarzami itp. - na pewno nie ma się o co obawiać. Perl jest trudniejszy w opanowaniu niż inne języki z Pythonem na czele - ale nie ma nic za darmo. Wolność musi mieć swoją cenę, a nie jest ona znowu jakoś przesadnie wysoka.
Wiele konstrukcji i koncepcji językowych, jak choćby domyślne zmienne, są właściwe praktycznie wyłącznie Perlowi. Krytyka tego typu rozwiązań jest jak najbardziej dopuszczalna - każdy może mieć swoje zdanie. Nie jest dopuszczalne natomiast podawanie nieprawdy za argument na poparcie swych tez. Wiele razy widziałem już tendencyjne porównania składni, gdzie podana była implementacja prostej operacji w kilku językach. Najczęściej kod reprezentujący Perla napisany był w jakiś zupełnie kosmiczny i dysfunkcjonalny sposób, podczas gdy istniała zupełnie standardowa konstrukcja realizująca określone zadanie. Przykładowo: ktoś dowodził, że w Perlu w ogóle nie da się w prosty sposób kontrolować ilości parametrów przekazanych do metody (zapisał więc szereg warunków sprawdzających istnienie poszczególnych parametrów), nie mając widać w ogóle pojęcia o możliwości zastosowania zmiennej tablicowej @_.
Szybkość działania
Oczywiście generalne porównywanie szybkości działania aplikacji napisanych w różnych językach ma taki sam sens, jak dyskusja o wyższości jednych świąt nad innymi. Wszystko zależy przecież od przeznaczenia aplikacji, jej architektury wewnętrznej, platformy sprzętowej itd. Perl jest językiem interpretowanym, aplikacje napisane w tym języku najczęściej nie występują więc w formie skompilowanej do kodu maszynowego, a w formie kodu źródłowego (skrypty) lub kodu pośredniego (bytecodu). Dwie z ostatnio wymienionych form wymagają istnienia w systemie operacyjnym zainstalowanego interpretera.
Kompilacja skryptu Perla do kodu maszynowego jest jak najbardziej możliwa, ale trzeba pamiętać, że odbywa się w specyficzny sposób. Kompilowany jest tak na prawdę kod C z osadzonym kodem Perla (często zaszyfrowanym) oraz całym interpreterem i potrzebnymi modułami w postaci bibliotek ładowanych dynamiczne. Podczas działania takiego skompilowanego programu następuje pełne rozpakowanie kodu Perla do pamięci, a następnie oddanie go pod kontrolę interpretera. Model taki jest więc podatny na wszelkie próby reverse engineeringu w dużo większym stopniu, niż np. skompilowana aplikacja C/C++. Koncepcja ta jest w założeniach podobna do wirtualnej maszyny Javy i zapewnia analogiczne bezpieczeństwo kodu oraz co do zasady podobną wydajność działania aplikacji. Wszystko więc tak na prawdę zależy od tego, jak szybko interpreter Perla (czyli perl - pisany z małej litery) wykonuje określonego typu operacje. A niektóre z nich wykonuje tak samo wydajnie albo nawet wydajniej, niż skompilowana do kodu maszynowego aplikacja C. Należą do nich m.in. operacje na tekście (zaawansowane wyrażenia regularne), niektóre operacje na strukturach danych oraz na plikach. Perl ma jeszcze jedną zaletę, krytyczne fragmenty kodu mogą być zaimplementowane w czystym C za pomocą modułu Inline::C, dowolne funkcje C mogą być także wywoływane za pomocą interfejsu PerlXS. Wymienione sposoby otwierają Perla na bardzo bliską współpracę z C i nie powinno to dziwić - interpreter Perla (perl) jest bowiem programem C.
Odpowiednio napisana aplikacja Perla może więc być tak samo szybka, jak natywna aplikacja C. Pomysł polega na tym, że zaimplementowanie niektórych funkcjonalności w Perlu zajmuje kilka razy mniej czasu niż w przypadku pisania wydajnego kodu C (a tak właśnie jest w większości przypadków, do których Perl został namaszczony). Mamy więc taką samą szybkość działania aplikacji, której stworzenie zajęło kilka razy mniej czasu. Implementowanie skomplikowanych algorytmów wykorzystujących wyrażenia regularne w C stanowiłoby w pewnym sensie ponowne odkrywanie Ameryki, gdyż podobne zadania zostały już porządnie przemyślane i wykonane w interpreterze Perla. Powyższe dywagacje powinny uzmysłowić, że umiejętnie wykorzystanie Perla może dać bardzo pozytywne efekty w kwestii wydajności. Nawiasem mówiąc, swego czasu robiłem pewne testy porównawcze między Perlem i C# w klasycznym scenariuszu deduplikacji danych (
kliknij tutaj). Program w Perlu okazał się ok. 50% szybszy od swojego odpowiednika w C#, przy bardziej zaawansowanym algorytmie różnica szybkości byłaby pewnie znacznie większa.
To be continued...