Zwykłego użytkownika od power usera dobrze odróżnia sposób radzenia sobie z powtarzalnymi zadaniami. Perspektywa zmiany nazwy N plików, skonwertowania N obrazków czy skatalogowania N utworów muzycznych jest odstręczająca już dla niewielkich wartości N, jeśli mielibyśmy wykonywać te czynności ręcznie. Zaawansowany użytkownik w tym celu zakasze jednak rękawy i wysmaży odpowiedni skrypt, który może nie będzie działał od razu, ale za to w końcu poradzi sobie z zadaniem całkowicie automatycznie. Niekoniecznie musi to w sumie zająć mniej czasu niż procedura ręczna, ale na pewno będzie mniej męczące :)
Dlatego też niemal zawsze staram się wybierać programową automatyzację. Wiąże się z tym jednak pewien problem. Otóż języki powłok systemowych (shelli) to nie jest coś, z czym koder ma intensywny kontakt na co dzień. Należą one raczej do obszaru zainteresowań administratorów. W związku z tym wyprodukowanie jakiegoś działającego kawałka skryptu jest często poprzedzone co najmniej krótkim przypominaniem sobie składni i semantyki danego języka. Zasadniczo jest to strata czasu lub – wyrażając się nieco inaczej – czynnik zwiększający minimalną wartość N, od której automatyzacja ma sens.
Ale jeśli nie języki shellowe, to co? Ano to, czego używamy na co dzień, czyli zwykłe języki programowania. Tu niestety nie ma sprawiedliwości: niektóre z nich nadają się do zadania nieporównywalnie lepiej niż inne. Część tych drugich ma swoje interpretowane, skryptowe wersje; przykładem jest choćby javowy BeanShell. Ich odpowiedniość do wersji pełnych nie jest jednak wcale zapewniona. Inne języki zwyczajnie nie mają podobnych narzędzi i zostawiają nas z koniecznością wyprodukowania kompletnego programu.
Tutaj ujawnia się przewaga Perla, Pythona, Ruby’ego i podobnych im języków interpretowanych, które nie wymagają do uruchomienia niczego poza plikiem z “czystym” kodem. Jest to dokładnie taka sama sytuacja, jak w przypadku basha czy innych języków powłoki. Korzyść jest jednak oczywista, jeśli tylko któryś z tych języków jest nam znany: nie ma tu bariery składniowej.
Nie znaczy to oczywiście, że jeśli ktoś potrafi jednym zaklęciem złożonym z ls
, xargs
i grep
a przetworzyć tysiąc plików tekstowych, to powinien porzucić tę sztukę i zwrócić się ku Prawdziwemu Programowaniu™. Zapewne też dobry programista będzie potrafił w końcu wyprodukować ową magiczną formułę, pod warunkiem spędzenia odpowiednio długiego czasu nad stronami mana. Jeśli jednak alternatywą jest napisanie kilkunastu linijek w znanym sobie języku, które zrobią to samo, będą miały spore szanse działać za pierwszym razem i zajmą w sumie co najwyżej kilka minut… to czemu nie? Warto korzystać ze swoich umiejętności nie tylko w ich ściśle ograniczonym obszarze zastosowań.
A jeśli przypadkiem ktoś właśnie zechciał akurat nauczyć się któregoś z wymienionych ze mnie języków, to… tak, polecam Pythona :)
Neal Ford w ” The Productive Programmer” też dotyka tematu skrypty vs “prawdziwe programy” i chyba w ostateczności zajmuje neutralne stanowisko, ale podaje dwa argumenty które mnie przekonują że jednak lepiej napisać mini program niż skrypt:
1. programy łatwiej/chętniej się wersjonuje. Bardziej chodzi o aspekt psychologiczny, ale coś w tym jest – wersjonowanie programów jest naturalne, skryptów nie zawsze.
2. Programy łatwiej się integruje, tzn mogą stać się częścią większego systemu. Nie chodzi o to, że taki kod można użyć w głównym programie (bo to jest rzadko), ale spokojnie można przerobić taki program na solidny moduł współpracujący z resztą systemu. Sklejanie elementów skryptami w systemie produkcyjnym jest rozwiązaniem trochę “na sznurkach”.
A, zapomniałem – lektura obowiązkowa dotycząca podobnych problemów: http://helion.pl/ksiazki/przetwarzanie-danych-dla-programistow-greg-wilson,przeda.htm
“Przetwarzanie danych dla programistów” zawiera sporo oczywistych oczywistości, ale ogólnie może się przydać.
A ja jestem zdania, że powinno wykorzystać się narzędzie, które ma ci jak najbardziej ułatwić takie zadanie i często efektywność takiego narzędzia to sprawa drugorzędna.
Co z tego, że napiszę miniprogram do przetworzenia masy plików, gdzie wpierw muszę znaleźć bibliotekę do np. C, która umożliwi mi obsługę danego formatu. Potem muszę napisać program używający tej biblioteki, a więc muszę otworzyć tutorial jak ją używać. Oczywiście nic nie mówię o problemach z pamięcią w wypadku programów średniego poziomu. I po wszystkim okaże się, że napisanie takiego miniprogramu zajęło mi więcej czasu niż ręcznie bym obrobił te dane, a program okazuje się być bezużyteczny, bo był jednorazowy. A napisanie skryptu to 3 linijki, a więc program jest gotowy po kilku minutach. A na serio zdarzają się takie sytuację.
Dlatego narzędzia powinny być zastosowane adekwatnie do aktualnej sytuacji, więc warto nauczyć się jakiegoś języku skryptowego w stylu Python/Perl/Ruby, który ułatwi nam to działanie, a pozwoli się zaprogramować w zrozumiałej składni, a nie Bash, który wymaga całkowicie innego myślenia.
@zwierzak: No i właśnie o tym mówię :)
@viroos. Zdecydowanie zgadzam się z punktem (2). Zintegrowanie rozwiązania napisanego nawet w innym języku programowania (uwzględniając w tym ewentualne jego przepisanie na inny język) jest prostsze niż ciągu komend narzędzi GNU czy czegoś w tym stylu. A poza tym, jeśli mówimy o kodzie napisanym przez programistę, to mimo bycia “zhackowanym na szybko”, ma on większe szanse bycia elastycznym i rozszerzalnym – choćby przez prosty fakt wydzielenia stałych czy funkcji.
@viroos: z punktem pierwszym się zgadzam; poza tym pisanie takich programów to jak pisanie wprawek – zawsze można się czegoś nauczyć/przypomnieć. Jednak oprócz wymienionych wcześniej zastosowań typu zamiana nazw dużej liczby plików, tak naprawdę skrypty pisze się do bardziej wyspecjalizowanych zadań, które często nie mają szans znaleźć szerszego zastosowania i jednocześnie nie ma sensu ich wdrażać do głównego systemu. Poza tym i wspomniane programy i skrypty trzeba w jakiś sposób przed faktycznym wdrożeniem przerobić aby spełniały normy systemu, a może to nawet prowadzić do przepisania kodu.
IMO jeśli programista chce się dowiedzieć/sprawdzić czy dałby radę napisać taki program używając systemowego API to jak najbardziej ma do tego prawo. Jednak w przypadku gdy byłoby to dla niego jedynie użyciem znanych już od dawna funkcji to narzut związany z kompilowaniem (wersjonowaniem) itp zdaje się bez sensu.
Dla mnie dobry jest PHP. I tak mam go zainstalowanego na kompie, a przykładowo zmiana nazw plików, to kilka linijek kodu.
@Zwierzak, równie często, a nawet częściej zdarza się, że używam C/C++/Obj-C do napisania małego konwertera właśnie dla tego, że mam już gotową bibliotekę, wystarczy utworzyć strukturę/obiekt, wypełnić co trzeba i gotowe. Oczywiście takiego programu zazwyczaj się nie używa samodzielnie, a np. ze skryptami. Ten sposób w sumie chyba jest najlepszy (mieszany). Języki skryptowe są niewygodne w przetwarzaniu plików binarnych, są raczej przygotowane do obróbki wysokopoziomowej (wczytywanie, manipulacja grafiką) lub przetwarzania danych tekstowych i tutaj świetnie uzupełniają języki kompilowane.
Łączenie może nie jest zbyt eleganckie ale można uzyskać bardzo dobre rezultaty, w bardzo krótkim czasie.
@Kacper, każdy używa to co lubi, kolega również często korzysta z PHP, a nawet tworzy drobne narzędzia w JS i spełniają swoją rolę w 200%. :)
A shell nie jest taki straszny. Fakt, że trzeba się przestawić trochę z myśleniem (zwłaszcza jeśli chcemy lub musimy przeprowadzać obliczenia) ale do sporej ilości zadań jest lepsze niż prawdziwy język programowania, problem tak naprawdę w tym, że shell jest za prosty i trzeba korzystać z innych dodatkowych narzędzi.
Z jeszcze innej beczki, czasami wolę dziabnąć narzędzie w języku nieskryptowym, bo po prostu kompilator i silna typizacja oszczędza mi czasu na wykrywaniu błędów (o niewidocznych różnicach wcięć w Pythonie nawet nie wspominam ;)).
I jeszcze jeden przykład na przydatność mieszania narzędzi to Octave, można dziabnąć sobie skrypcik generujący aproksymacje jakiejś zadanej funkcji i potem wykorzystać to przy optymalizacji. Często też korzystam z tego przy modelowaniu funkcji, której później używam w programie/grze i można od razu wykonać wizualizację co pomaga zrozumieć lub wytropić błędy. ;)
Fajnym środowiskiem do “hakowania na szybko” jest też coraz popularniejszy node.js. Gdy już się zrozumie specyficzny sposób działania javascriptu stwarza on świetną alternatywę dla basha. Przy okazji można w kilku linijkach postawić serwer :P
Frizi: świetną alternatywą dla basha jest prędzej perl, ruby i python niż javascript bo mają więcej bibliotek które wspierają system operacyjny i różne pierdołowate sprawy jak np. automatykę instalacji usług. Nie mówiąc o tym że mimo tego całego markietingowego buzzu jaki słyszysz od developer rockstars w javascript większe projekty pisze się jeszcze dość paskudnie. Nie mówiąc już nawet o tym że async może trochę utrudniać zrozumienie tego co się dzieje w programie a w przypadku administracyjnych rzeczy nie zawsze jest to pożądane(Mimo oczywistych plusów w postaci przyspieszenia działania) a kod musi być bardzo deterministyczny/transakcyjny. Ale jeśli masz napisać na szybko jakiś mały serwer api – nadaje się całkiem dobrze.