Mam malować?

Jak kończy prawdziwy programista

Dobrego programistę poznajemy po tym, jak zaczyna i jak kończy... blok instrukcji. Otóż najpierw wpisuje znaczniki początku i końca (Begin ... End lub otwierający i zamykający nawias klamrowy - w zależności od języka), a dopiero potem zapełnia je zawartością. Ostrożność taka wynika z przykrych doświadczeń z przeszłości polegających na poszukiwaniu o czwartej nad ranem związków między początkami a końcami rozwlekłych i wielokrotnie zagnieżdżonych instrukcji warunkowych i pętli. Programista po takich przejściach jest zdania, że szkoda w ten sposób marnotrawić życie i w obronie własnej najpierw kreśli szkielet każdej rozpoczynanej instrukcji złożonej. Z takich też powodów nie pisze monolitycznych ciągów instrukcji, starając się dzielić je na krótsze, bardziej zrozumiałe i czytelne, fragmenty funkcjonalne.

Gdy kiedyś pracowałem przez półtora roku w małej firmie utrzymującej się wyłącznie ze sprzedaży własnego oprogramowania, miałem wiele okazji, aby na własnej skórze poznać "uroki" pewnych trywialnych błędów wynikających z braku właściwych nawyków programistycznych. Była to dla mnie prawdziwa zawodowa szkoła przeżycia. Po takiej ilości "wklepanego" kodu można rzeczywiście nabrać twardych przyzwyczajeń do końca swej kariery zawodowej. Gdy zmieniłem firmę i programowaniem zajmowałem się nadal, chociaż już nie z taką drapieżną intensywnością, mój młodszy kolega, spozierający nieraz na mój monitor, przyznał po pewnym czasie, że właśnie ode mnie nauczył się tej maniery tworzenia pustego szablonu Begin...End.

W niektórych językach programowania (C, Pascal, PHP, Java) operatory przypisania wyraźnie różnią się w zapisie od operatorów porównania, stąd starzy wyjadacze mają zwyczaj zapisywać w instrukcjach porównania zmienną po prawej stronie, np. if (1==x) zamiast if (x==1). Wzięło się to stąd, że dosyć nieprzyjemne w skutkach było napisanie pojedynczego znaku równości zamiast podwójnego, co porównanie zamieniało w przypisanie. Nie dotyczyło to programistów Pascala, gdzie dla odmiany porównanie to jeden znak równości, natomiast przypisanie to znak równości z dwukropkiem. W stanie obecnym te pomyłki nie są już tak groźne, gdyż kompilatory generują stosowne ostrzeżenia, a graficzne środowiska IDE wręcz prześcigają się w bieżącej kontroli jakości formalnej kodu.

Warto zwrócić uwagę na optymalność zaproponowanego rozwiązania, np. ile razy w pętli wywoływana jest pomocniczo funkcja badająca długość napisu. Przypuszczam, że dobry kandydat będzie w stanie podjąć merytorycznie właściwą dyskusję na ten temat. Nie należy do rzadkości, a można wręcz z dużą dozą prawdopodobieństwa stwierdzić, że jest niemal regułą, iż napisany w trakcie testu rekrutacyjnego fragment kodu zawiera błędy. Wszak pisanie kodu na kartce papieru nie jest zadaniem zbyt przyjemnym i mało kto w takich warunkach potrafi zaimprowizować bezbłędnie działający algorytm przy jednoczesnym braku możliwości sprawdzenia jego fizycznej realizacji i wniesienia ewentualnych korekt. Bywają błędy mniejszego lub większego kalibru. Do tych drugich zaliczyć należy błędy logiczne. Regułą bywają pomyłki w naliczaniu wartości granicznych pętli. Tylko bardzo wprawieni programiści potrafią "od strzału" założyć ilość przebiegów pętli z dokładnością do jednego. U mniej doświadczonych przeważnie występuje niedokładność rzędu plus minus jeden.

Mam malować?

Do programowania i projektowania wymagana jest wyobraźnia, jak zresztą do wszelkiej twórczej działalności. A oprócz tego wymagana jest głowa na karku. Można stwierdzić, czy kandydat spełnia te warunki, prosząc go o zaprojektowanie czegokolwiek, nawet niezwiązanego z informatyką. Jeśli na przykład poprosimy go o rozplanowanie punktów świetlnych w pomieszczeniu, a on z miejsca zabierze się do rysowania tego na papierze, to nie rokuje najlepiej. Można jednak przez chwilę z niewzruszoną cierpliwością przyglądać się temu dziełu, jak w prostokącie obrazującym pokój zaznacza lampę na suficie, potem lampki boczne, nocne i co tam jeszcze zdoła wymyślić. Gdy projekt jest niemal zakończony, stwierdzamy (zapewne z nutką satysfakcji, bo znowu racja jest po naszej stronie), że przecież miało to być pomieszczenie służące magazynowaniu wędlin w warunkach chłodniczych. Projektant sam sobie winien, jeśli nie skonkretyzował założeń. Prawdopodobnie projekty software'owe w jego wykonaniu będą odbywać się według podobnego scenariusza.

Na potrzeby stwierdzania takiej właśnie rozwagi projektowej można wymyślać zagadnienia różnej klasy abstrakcji. Czasami jednak zdarzy się, że kandydat zabłyśnie jakimś niecodziennym pomysłem, na który jeszcze nikt nie wpadł. Stawiając problem do rozwiązania, zwłaszcza jeżeli nie zalicza się on do klasy problemów trywialnych, a wymagający pewnych zabiegów projektowych, nie należy spodziewać się, że dobry programista zacznie z miejsca zapisywać kod w preferowanym języku. Tak robi tylko zły programista. Nieraz pewne przedsięwzięcia wymagają najpierw naszkicowania na papierze zasady działania algorytmu, pomagając tym samym osiągnąć klarowność na poziomie pojęciowym.

Dopiero potem można wziąć się za wklepywanie kodu. Co prawda niektórzy mają niezgorszą wyobraźnię przestrzenną i potrafią sobie wyobrazić krok po kroku wzmiankowane wcześniej procesy odwracania tekstu lub listy połączonej. Są to jednak wyjątki, a w kontekście stresu towarzyszącego przecież walce o miejsce pracy i te zmysły mogą zawieść.

Należy unikać pytań zbyt szczegółowych, o encyklopedycznym charakterze. Informatyka to nie farmacja. Czy lepszy jest kandydat, który wie dokładnie, jaka jest różnica między typem danych int2 a int4 w bazie PostgreSQL, od kandydata, który jedynie przypuszcza, że są to liczbowe typy całkowite, o określonej w bajtach pojemności? Pierwszy z nich zna doskonale zagadnienie, więc pewnie niejedną tabelę zaprojektował, ale nie wiadomo z jakim skutkiem. Drugi natomiast nie ma akurat praktyki przy implementacji tych baz, ale ma dobre umiejętności analityczne i ogólne rozeznanie w tematyce. To, co wie pierwszy z nich, można w jednej chwili sprawdzić w dokumentacji. Walory drugiego kandydata czynią go elastyczniejszym i zgodnie z tym, co już było powiedziane wcześniej, lepiej wskazywać na pretendentów radzących sobie z problemem, niż znających rozwiązanie na pamięć.

Pierwszą część tekstu Piotra Kowalskiego na temat naboru pracowników ("Życiorysy ładnie piszą") opublikowaliśmy w CW nr 39/2005.

1) asembler jest ściśle powiązany z listą rozkazów procesora i architekturą jednostki centralnej.

2) Assembler is not for Dummies - asembler nie jest dla bałwanów.

3) refaktoring (refactoring) jest techniką wewnętrznej restrukturyzacji kodu programu bez naruszania jego zewnętrznej funkcjonalności.

4) pojęcie kultu cargo wzięło swój początek od aborygenów, którzy po II wojnie światowej konstruowali lotniskopodobne budowle, oczekując, że znowu z nieba dostarczone im zostaną kontenery z dobrami doczesnymi, jak miało to miejsce podczas wojny. Generalnie zjawisko oczekiwania na dary niebios lub przybycie bogów znane jest na Ziemi od dawna, na czym nie najlepiej wyszli Aztekowie, początkowo upatrujący w konkwistadorach długo oczekiwanych białych bogów zza oceanu.

5) RAD (Rapid Application Development) - technika szybkiego tworzenia oprogramowania, umożliwiona dzięki odpowiednim narzędziom programistycznym (tzw. narzędzia RAD - wspomagające i automatyzujące tworzenie kodu).

6) styl węgierski jest notacją nazewniczą, polegającą m.in. na tym, że nazwy zmiennych zaczynają się zawsze od liter określających typ zmiennej (np. lpszFile, hwndItem). Notację wprowadził (w firmie Microsoft na użytek języka C) Charles Simonyi, Węgier z pochodzenia. Warto dodać, że niektórym programistom nazwy zmiennych oparte na tej konwencji przypominały nieco egzotyczne, węgierskie brzmienie, stąd też określenie tej notacji wydaje się być w dwójnasób celne.


TOP 200