Scripting Games 2012–Odliczanie: 10…
Za dziesięć dni rozpocznie się święto miłośników PowerShella – Scripting Games. Dwa tygodnie przepełnione pisaniem skryptów (uczestnicy) i ich czytaniem/ testowaniem (sędziowie). W tym roku mam zaszczyt znajdować się w tej drugiej kategorii, nie mam więc szans, by obronić tytuł z zeszłego roku. Aby więc laur zwycięzcy pozostał w kraju nad Wisłą postanowiłem się podzielić moimi spostrzeżeniami odnośnie Scripting Games. Przede wszystkim: wyedukować, czy raczej – podzielić się kilkoma uwagami, które mogą pomóc uniknąć błędów. Później: zachęcić, wszak każdy lubi, gdy jego wysiłek jest stosownie (wy)nagrodzony. Wreszcie: pomóc wybrać odpowiedni poziom. Ale po kolei. Dziś:
10 rzeczy, które powinno się robić.
Dla wielu spośród uczestników będą to banały, ale czasem lepiej pewne rzeczy powtórzyć, bo a nuż widelec komuś się to czy owo “zapomniało”…
10… Zaawansowane funkcje.
W kategorii “początkujących” może się to wydawać lekką przesadą. I naturalnie, nie ma sensu “pakować” w stosowne dekoracje kodu, który zajmuje jedną linię. Z drugiej strony [CmdletBinding()] to tylko 17 znaków, a dają nam sporo w zamian. Naprawdę, funkcja korzystająca z $args trąci myszką. PowerShell daje nam tę elastyczność, ale jeśli piszemy coś na konkurs, to lepiej pokazać, że znamy się na temacie. Kundelki są śliczne, ale na wystawę psów ich nikt (chyba?) nie prowadzi. Zaawansowana funkcja, to funkcja “rasowa”. W rękach wprawnego skrypciarza – medalowa wręcz.
9… Obiekt na wyjściu.
Funkcja w PowerShellu zwraca obiekty. KROPKA. Jeśli napisałeś ostatnio funkcję, która robi coś innego – przepisz to zdanie 100 razy na tablicy. Jeśli funkcja nie zwraca obiektów, to jest jednorazowa. Jeśli zwróci obiekt – można ją wpleść w zgrabną rurkę i mieć z niej pożytek jeszcze wiele razy. Warto też przyjrzeć się parametrom, szczególnie w kategorii zaawansowanej. Jeśli jest sens, by jakiś parametr “pobierał” obiekty (lub też ich właściwości) z rurki – grzechem zaniedbania będzie pominięcie tego. Znów: troszkę się trzeba z tym “naklikać”, ale późniejsze użycie może się okazać po wielekroć przyjaźniejsze użytkownikowi.
8… Comment Based Help.
Jeśli piszesz funkcję i wymagasz, by wszyscy przejrzeli Twój skrypt by się dowiedzieć co robi (lub co gorsza: zakładasz, że na pewno odgadną co autor miał na myśli), to właśnie strzeliłeś komuś w stopę. Co gorsza: tym kimś możesz być Ty, za kilka miesięcy, o trzeciej nad ranem desperacko próbujący rozwiązać jakiś problem przy pomocy tej właśnie funkcji. Jak myślisz, co pomyślisz o tym leniu, któremu zabrakło energii, by funkcję wyposażyć w zrozumiałą i kompletną pomoc? Przecież to raptem kilka linii komentarza. W zasadzie podstawowy opis, do tego kilka przykładów – i pomoc gotowa. Get-Help to o wiele bardziej przyjazna metoda zapoznawania się z komendami w PowerShellu, niż notepad.
7… Write-Verbose i Write-Debug.
Mamy funkcję zaawansowaną (mamy, prawda?), więc skorzystajmy z tego, co ona nam oferuje. Robisz w funkcji coś “przełomowego”, gdzie potencjalnie może coś się nie udać? Daj szansę użytkownikowi wyświetlić informację, co próbujesz zrobić. Wyrzucenie informacji Verbose/ Debug zawierającej wartości zmiennych, parametrów, czy po prostu informujące o stopniu zaawansowania przydadzą się nie tylko w czasie testowania skryptu, ale również później, gdy nagle coś przestanie działać. Ponieważ domyślnie te informacje są ukryte, to nie zaśmiecamy nikomu konsoli. Dopiero gdy sam o to poprosi – robimy się wylewni. Złoty środek.
6… Obsługa błędów.
Błędy czasem można przewidzieć. Jeśli przewidujesz błąd – obsłuż go. Straszenie ludzi, że dzieje się coś złego, gdy w istocie dzieje się coś przewidywanego i naturalnego jest marnym pomysłem. Narzędzia zbyt hałaśliwe i zbyt “płochliwe” mogą zniechęcić każdego. Jeśli więc da się obsłużyć jakiś błąd – zróbmy to. I nie mam tu bynajmniej na myśli:
try { # kod naszej funkcji } catch {}
To nie obsługa błędów, to proszenie się o kłopoty.
5… Testuj na “gołym” PowerShellu.
Maszyna miłośnika skryptów to często swoisty bazar. Moduły, funkcje, skrypty i profile pałętają się po całym twardym dysku i nigdy nie wiadomo, który akurat “wyręczy nas” przy definiowaniu elementów wykorzystywanych w naszym skrypcie. Problem polega na tym, że sędziowie skrypt będą raczej testować na innym komputerze i nagle skrypt zasypie ich stronami niezrozumiałych błędów. Jak tego uniknąć? powershell.exe –noprofile, to najlepsza możliwa odpowiedź. Najlepiej (na wszelki wypadek) uruchomić go ponownie tuż przed ostateczną kontrolą. Jeśli jak ja – od dawna macie na swoim komputerze PowerShella 3 – możecie zechcieć dorzucić tam też przełącznik “-version 2”. Chyba że faktycznie chcecie skrypt pisać pod wersję trzecią – pamiętajcie wtedy jednak o parametrze #requires. Pamiętajcie też: skrypt raz wrzucony na poshcode pozostanie niezmienny, zawsze więc przed opublikowaniem tam: testujemy, testujemy, testujemy.
4… KISS.
Prosto. Jeśli da się cmdletem – nie twórzmy klas w .NET. Jeśli da się parametrem – nie filtrujmy przy pomocy Where-Object. Dobry skrypt nie musi być długi, więcej nawet – często to właśnie te krótsze są o wiele lepsze, gdyż łatwiej je ogarnąć i zrozumieć ich logikę. Sam wiele razy popełniałem ten błąd, więc wiem co mówię. Nie dać się ponieść, skupić się na zadaniu, upraszczać by zwiększyć przejrzystość. Prosto do celu.
3… Stosować cmdlety, jeśli istnieją.
Troszkę wpisuję się to w ideę KISS, ale tu bardziej chodzi o nie odkrywanie na nowo koła. Pisanie funkcji, która zrobi to samo co istniejący cmdlet (tylko gorzej) mija się z celem. Po to Bozia dała nam Get-Command, byśmy mogli w razie czego poszukać gotowego narzędzia, które wykona za nas najcięższą robotę. Nikt nie nagrodzi nas za napisanie na nowo Get-Member, szczególnie gdy nasze zadanie dotyczy kompletnie innych rzeczy.
2… Brać sobie do serca komentarze/ artykuły sędziów.
Skrypt opatrzony przez sędziego komentarzem daje nam możliwość pracowania nad swoimi umiejętnościami. Zakładam oczywiście, że komentarz ma sens (co jest raczej regułą). Dodatkowo w zeszłym roku kilku sędziów w czasie trwania SG publikowało na swoich blogach wskazówki, które pomagały uniknąć błędów innych (przynajmniej w kolejnych zadaniach). W tym roku pewnie będzie podobnie. Te dwa źródła informacji mogą pomóc tu i teraz (przy kolejnych konkursowych skryptach) jak i w przyszłości (w czasie pisanie skryptów “produkcyjnych”).
1… Porównać swoje rozwiązanie z rozwiązaniami innych.
Takie porównanie pozwala często dostrzec rysy we własnej logice, oraz wskazać inne drogi (być może skuteczniejsze, bądź wydajniejsze) prowadzące do tego samego celu. Warto przyjrzeć się zarówno skryptom uznanym za najlepsze, jak i tym, które uzyskały noty najniższe: to pozwoli nam samodzielnie ocenić: na którym miejscu na skali znajdują się obecnie nasze umiejętności. Na koniec gier pojawiają się też rozwiązania ekspertów. I choć sam kilka razy nie do końca zgadzałem się z rozwiązaniami, które tam można było znaleźć, to dobrze jest móc porównać swoją pracę, z pracą ekspertów. Dzięki temu wyciśniemy z Scripting Games ostatnie soki.
Podsumowanie
Czas leci… Dziś przyjrzeliśmy się temu, co robić należy. Za dwa dni: 8 rzeczy, których należy unikać. Naturalnie, jeśli niebo nie zawali mi się na głowę.
Witam:)
Może to trywialne pytanie ale jak sprawdzić czy dana funkcja jest zwracana jako obiekt?
Bardzo dobre pytanie… 🙂
Generalnie naprościej jest prześledzić jej wynik poleceniem Get-Member.
Get-Foo | Get-Member
Poprawna funkcja zwróci obiekty jednego typu (albo typów „podobnych”, jak to ma miejsce w przypadku Get-Service). Błędna – albo nie zwróci nic, albo mieszankę, albo System.String, albo różnego rodzaju formatki. Hm… chyba warto o tym napisać króciutki wpis, z konkretnymi przykładami. Dzięki za sugestię! 🙂