06_styl_programowani..
Transkrypt
06_styl_programowani..
Styl programowania Wojciech Sobieski Olsztyn 2006-2012 Styl programowania Jedną z podstawowych zasad obowiązujących podczas pisania programów jest czytelność i przejrzystość kodów źródłowych. Dobrze napisany kod umożliwi innym programistom (a często i autorowi) późniejsze ich zrozumienie i usprawnienie. Jest to bardzo ważne gdyż raczej rzadko zdarza się napisać od razu program w wersji ostatecznej, nie wymagającej poprawek i usprawnień. Najczęściej dzieje się wręcz odwrotnie – tworzy się mały program a następnie nieustannie go ulepsza. Istnieje pewna ilość zaleceń i schematów, których przestrzeganie wpłynie na poprawność stylu pisanego kodu źródłowego. Należy jednak pamiętać, że najważniejszy jest efekt działania programu (a nie sam program) i w uzasadnionych przypadkach możne dojść do pewnych odstępstw od przyjętych reguł. Styl programowania Cechy charakteryzujące dobry program: ➔ ➔ ➔ ➔ ➔ ➔ ➔ poprawność (zgodność z wymogami użytkownika), niezawodność (dobre dane wejściowe → dobre wyniki), przenośność (łatwość instalacji na różnych komputerach), łatwość konserwacji (prosto napisany program łatwo przystosować do różnych warunków pracy), czytelność (prostota jest jedną z najważniejszych cech dobrych programów), prawidłowe wykorzystanie zasobów (pamięci, dyski, itp.), szybkość. Styl programowania Styl programowania obejmuje: • nazwy zmiennych w programie, • wielkości stałe, • liczba zmiennych globalnych, • deklaracje typów zmiennych, • komentarze, • puste linie, odstępy poziome, akapity, wcięcia, itd., • podział na sekcje, podprogramy, • uniwersalność i standaryzacja modułów, • funkcjonalność i wygoda użytkowników, • formułowanie celów, • złożoność systemu. Styl programowania 1. Nazwy zmiennych. Wybór nazw zmiennych ma pomóc w zrozumieniu ich znaczenia i zastosowania. Najlepiej jest używać nazw, które coś oznaczają, powiadamiając tym samym użytkownika (intencjonalnie) o możliwościach funkcji czy procedury, czy też wskazując sens zmiennych, itd. Z reguły języki programowania nie narzucają nazewnictwa zmiennych. Nazwy można tworzyć opierając się na typach zmiennych (np. wszystkie zmienne liczb zespolonych mogą mieć nazwę zaczynającą się od “ZESP_”), obszarach obowiązywania (np. zmienne obowiązujące w całym programie zaczynają się od “GLOBAL_”, a obowiązujące w podprogramie, procedurze lub funkcji od “LOCAL_”) lub ich funkcjach (np. zmienne sterujące są inaczej nazywane niż zmienne obliczeniowe, itd.). Styl programowania Dobrze jest stosować rzeczowniki dla oznaczania nazw wszelkich danych, czasowniki dla funkcji i procedur (rozkazy, np. dziel, dodaj itp), przymiotniki dla zmiennych logicznych (w Pascalu boolean). Generalnie można tworzyć dowolne, byle przejrzyste, zasady nazywania zmiennych – ważne jest jedynie aby te zasady przestrzegać. Zbyt długie nazwy można zastąpić ich skrótami (np. zamiast temperaturamaksymalna – tempmax lub temp_max, itp.). Jeżeli translator nie rozróżnia małych i dużych liter, powinno się pisać duże litery na początku każdego słowa (np. nazwa maksymalnatemperaturaroczna jest mniej przejrzysta niż MaksymalnaTemperaturaRoczna) - jeszcze lepiej byłoby zastosować skrót, np. TmaxRok. Tworzone skróty powinny być standardowe dla danej instytucji lub dziedziny. Styl programowania Reguły skracania nazw: • skraca się każde znaczące słowo w nazwie, • pierwsza litera musi wystąpić, • spółgłoski są ważniejsze od samogłosek, • początek słowa jest ważniejszy niż koniec, • tworzy się skróty na 6 do 15 liter. Z reguł tych wynika następujący algorytm: usuwa się od końca najpierw samogłoski potem spółgłoski, oprócz pierwszej litery, aż do osiągnięci pożądanej długości. Porządkowanie list zmiennych wg alfabetu znacznie ułatwia ich odszukiwanie i określenie typu. Styl programowania Przykłady poprawnie dobranych nazw danych (Pascal): P, Ro : Real; Vx, Vy : Real; MaxIter : Integer; Przykłady niepoprawnie dobranych nazw danych (Pascal): Dana1, Dana2 : Real; x, y : Real; n : Integer; Styl programowania 2. Wielkości stałe. Z wyjątkiem zera, jedynki i może jeszcze kilku innych stałych, nie należy wprost używać stałych w całej treści programu, w jego wnętrzu. Najlepiej zadeklarować (zgłosić) je w części opisowej, specjalnie do tego przeznaczonej, np. za pomocą słowa Pascala const. Zmiana sprzętu często powoduje idące za nią zmiany przybliżonych wartości różnych stałych. Ile czasu zmarnujemy wyszukując w programie miejsca, w których występuje stała zapisana jako liczba zmiennoprzecinkowa z dokładnością do 9 miejsc znaczących by zamienić ją na liczbę o 12 miejscach znaczących. Styl programowania Przypuśćmy, że w programie używamy tablicy, której rozmiar 100 zgłosiliśmy kilkakrotnie pisząc między innymi ciąg znaków [1..100]. Załóżmy, że zmienimy wymiar 100 wszędzie, automatycznie, za pomocą edytora tekstu, na 200, a przy okazji, całkiem nieświadomie, zamienimy temperaturę jakiegoś procesu też na 200, ale stopni. Zastosowanie pliku dołączalnego do definicji podstawowych parametrów programu (Fortran). Styl programowania 3. Zmienne globalne. Należy minimalizować liczbę zmiennych globalnych, dostępnych z całego programu. Zmiany w procedurach czy funkcjach, których jest wiele w programach, są zmianami lokalnymi. Często zapominamy przy nich o zmiennych globalnych. W ten sposób łatwo o błędy. Zmienne globalne Zmienne lokalne moduł 1 Zmienne lokalne moduł 2 Styl programowania Styl programowania Styl programowania 4. Deklaracje typów zmiennych. Wszystko, co tylko się da, należy umieszczać w deklaracjach typu, włączając w to podzakresy, definicje tablic oraz rekordów. Należy unikać deklarowania niejawnego. Źle: Dobrze (n przyjmie wartość 6,23): x=2.45 y=3.78 n=x+y write(*,*) n W tym przypadku n przyjmie wartość 6 ponieważ domyślnym typem zmiennych o nazwach i,j,k,l,m,n jest typ INTEGER. Real x,y,n x=2.45 y=3.78 n=x+y write(*,*) n Styl programowania 5. Komentarze. Są to teksty nie podlegające translacji, służące do opisu kodu źródłowego. Mają one mówić jak rozumieć program, ale nie opisywać drugi raz tego co wynika z kodu (np. komentarz “tutaj pod zmienną x podstawiamy 7”, uczyniony w miejscu x: = 7 jest niepoprawny). Powinny zawierać logiczny sens zastosowania danej sekwencji instrukcji, o ile nie jest on oczywisty podczas lektury samego kodu (nadmiar komentarzy może też zatracić przejrzystość samego kodu!). Najczęściej objaśnia się ważniejsze pętle, skoki, sprawdzanie warunków, itp. Komentarze muszą być przynajmniej równie czytelne jak kod, powinny poprawiać czytelność kodu, dlatego powinny mieć tę samą szerokość wcięcia co kod, a mogą też być wyróżnione znakami specjalnymi, ramkami, itp. Styl programowania Styl programowania Na początku programu powinien znaleźć się komentarz wstępny, zawierający: • opis działania programu, • sposób użycia - jak wywołać program, • listę i opis ważniejszych zmiennych, • opis plików WE/WY, • nazwy używanych podprogramów, • nazwy wszelkich specjalnych metod, które zostały użyte, wraz ze wskazaniem, gdzie można znaleźć dalsze informacje, • informacje o czasie działania (jeśli ma to znaczenie), • wymagania sprzętowe i systemowe, • opis specjalnych poleceń dla operatora / użytkownika, • informacje o autorach i kontaktach, • datę napisania (ew. datę ostatniej modyfikacji lub numer wersji). Styl programowania Styl programowania 6. Puste linie. Oddzielają poszczególne fragmenty programu ułatwiając późniejsze ich poszukiwanie. Puste linie (jedna, dwie) POWINNY! oddzielać różne fragmenty programu i podprogramy. Źle: Dobrze: Real x,y,z x=2.45 y=3.78 z=x+y write(*,*) z Real x,y,z x=2.45 y=3.78 z=x+y write(*,*) z Styl programowania 7. Odstępy poziome (spacje). Zwiększają czytelność kodu, w szczególności zaś wyrażeń arytmetycznych, list parametrów i itp. Źle: Dobrze: if(z.lt.0)then print '($A25)',(wartosc ujemna)' elseif(z.eq.0)then print '($A25)',(wartosc zerowa)' else print '($A25)',(wartosc dodatnia)' end if if (z .lt. 0) then print '($A25)', else if (z .eq. 0) print '($A25)', else print '($A25)', end if (wartosc ujemna)' then (wartosc zerowa)' (wartosc dodatnia)' Styl programowania 8. Wcięcia. Odzwierciedlają wzajemne powiązania instrukcji i grup instrukcji, uzewnętrzniają logiczną strukturę programu (lub danych). Źle: case n of 1: begin if i=j then k:=1 else k:=0; end; 2: begin if i=j then k:=0 else k:=1; end; end; Dobrze: case n of 1: begin if i=j then k:=1 else k:=0; end; 2: begin if i=j then k:=0 else k:=1; end; end; Styl programowania 9. Akapity. Akapitów używamy w instrukcjach złożonych. Należy do dobrego tonu podpatrzenie jak radzą sobie z tym inni. Decydując się na jakiś styl trzymajmy się go zawsze. Nie mieszajmy różnych stylów. Programy tracą wtedy na czytelności. Z czasem praktyka pokaże, że trzymanie się jednego stylu opłaca się. Tymczasem należy się do tego przyzwyczajać. Źle: Dobrze: print '($A10)', ' Podaj x: ' read(*,*) x write(*,*) ' x = ', x print '($A10)', ' Podaj i: ' read(*,*) i write(*,*) ' i = ', i print '($A13)', ' Podaj text: ' read(*,*) text write(*,*) ' text = ', text print '($A10)', ' Podaj x: ' read(*,*) x write(*,*) ' x = ', x print '($A10)', ' Podaj i: ' read(*,*) i write(*,*) ' i = ', i print '($A13)', ' Podaj text: ' read(*,*) text write(*,*) ' text = ', text Styl programowania 10. Numeracja linii (w językach których to dotyczy). Numeracja powinna być prowadzona co 10, aby można było zawsze coś wstawić w środek. Źle: Dobrze: 1 write(*,'(a)') ' a < 0' goto 4 10 write(*,'(a)') ' a < 0' goto 40 2 write(*,'(a)') ' a = 0' goto 4 20 write(*,'(a)') ' a = 0' goto 40 3 write(*,'(a)') ' a > 0' goto 4 30 write(*,'(a)') ' a > 0' goto 40 4 continue end 40 continue end Styl programowania 11. Przenoszenie słów. Nie jest zalecane. Jeżeli już jest to konieczne, to linia powinna się kończyć tak, by było widać, że logicznie nie jest zakończona i że jej kontynuacja musi następować dalej (np. w wyrażeniach arytmetycznych ostatni w linii powinien być operator, a nie operand). Źle: z=(2/3)*sin(x*x+y*y) +-(1/3)*cos(x*x+y*y) Dobrze: z=(2/3)*sin(x*x+y*y)+(1/3)*cos(x*x+y*y) Styl programowania 12. Rozmieszczenie instrukcji. Jest jednym z najważniejszych elementów stylu. Powinny one być od siebie odseparowane (ale nie za bardzo), najlepiej gdy będzie jedna instrukcja w linii. Źle: case n of 1: begin if i=j then k:=1 else k:=0; end; 2: begin if i=j then k:=0 else k:=1; end; end; Dobrze: case n of 1: begin if i=j then k:=1 else k:=0; end; 2: begin if i=j then k:=0 else k:=1; end; end; Styl programowania 13. Nawiasy. Używanie nawiasów jest bardzo zalecane, szczególnie przy długich wyrażeniach arytmetycznych. W takim przypadku błędna formuła obliczeniowa (brak lub złe miejsce wstawienia nawiasu) może być przyczyną trudnych do wykrycia błędów. Styl programowania 14. Sekcje. W przypadku dużych programów należy je dzielić na elementy według następujących zasad: • algorytm programu należy dzielić na pojedyncze zadania o ściśle określonym celu. Uwaga programisty skupia się wówczas na konkretnym problemie, nie związanym bezpośrednio z resztą programu, zmniejsza to znacznie prawdopodobieństwo popełnienia błędu. Poszczególne segmenty mogą być oddzielnie testowane, co ułatwia wyszukiwanie i usuwanie błędów w całym programie. W przypadku dużych programów, poszczególne moduły mogą być ponadto pisane przez różnych programistów. • konkretne zadanie powinno być w programie rozwiązane tylko raz. Jeżeli to tylko możliwe nie należy mieszać i powielać zadań z różnych segmentów – może to znacznie utrudnić znajdowanie błędów: nie wiadomo bowiem który segment jest odpowiedzialny za powstanie błędu. Styl programowania • segmenty powinny być uniwersalne. Oznacza to, że należy je tak budować, aby dało się je wykorzystać w innych programach. Jest to szczególnie przydatne, gdy programista tworzy aplikacje z określonej dziedziny i często musi rozwiązywać podobne problemy. Korzystanie z gotowych i przetestowanych segmentów może znacznie przyspieszyć i ułatwić pracę. • każdy segment powinien realizować swoje zadania niezależnie od innych segmentów. • należy dążyć do tego, aby jak najwięcej użytych w programie zmiennych miało zasięg lokalny (czyli obowiązywały w obrębie podprogramów, procedur i funkcji). Znacznie łatwiej jest wówczas kontrolować zawartość zmiennych, a przypadkowa i nieprzewidziana zmiana ich wartości jest mniej prawdopodobna. Styl programowania 15. Uniwersalność. Można ją osiągnąć przez stosowanie: parametryzacji, używanie standardowych bibliotek, standaryzację postaci wejścia-wyjścia, stosowanie standardów stylu. Styl programowania Parametryzacja oznacza niezależność od konkretnego zestawu danych, może być osiągnięta przez parametryzację. Pozwala to na łatwe i szybkie zmiany w programie, dlatego najczęściej używane parametry to: • wymiary tablic i list, • dane specjalne, np. stopa procentowa, podatkowa, • desygnatory urządzeń WE/WY (też ścieżki dostępu i nazwy plików). By zmienić program bez parametryzacji trzeba ręcznie pozmieniać wszystkie wystąpienia danej wartości, ale można łatwo coś przeoczyć lub zmienić coś, co ma taką samą wartość, ale odnosi się do innej zmiennej. Styl programowania Używanie standardowych bibliotek, funkcji i procedur. Są to elementy już zoptymalizowane i przetestowane, przez co zapewniają lepszą efektywność i mniejsze prawdopodobieństwo wystąpienia błędu. Oszczędność na czasie kodowania też jest olbrzymia. Styl programowania Standaryzacja postaci WE/WY musi być szczegółowo zaprojektowana przed kodowaniem. Najlepszy jest naturalny i jednorodny układ zmiennych i formatów. Styl programowania Standardy stylu. Standard stylu jest to zbiór określonych zasad pisania programów. Standardy mogą być narzucone z góry lub mogą być tworzone indywidualnie. Mają tę zaletę, że zmniejsza się możliwość nieporozumienia, jeżeli robi się tę samą rzecz za każdym razem tak samo. Potrzebny jest tylko niewielki wysiłek, by przestrzegać standardów stylu. Standardy mogą ograniczać przyszły rozwój i postęp, być zbyt krępujące lub nieporęczne. Dobre standardy nie posiadają tych cech (lecz i tak istnieją rzadkie przypadki, w których można nie zastosować się do standardu). Instytucja narzucając standardy stylu sprawia, że powstające tam programy będą jej własnością, a nie poszczególnych programistów. Styl programowania 16. Funkcjonalność i wygoda użytkowników jest obecnie popularnym hasłem zawartym w pojęciu „User friendly program”. Oznacza to, że użytkownik programu (operator) powinien mieć możliwość korzystania z programu w sposób naturalny, bez specjalnego przygotowania. Program powinien przewidywać zadania użytkownika i służyć mu podpowiedziami i pomocą, nie dopuszczając jednocześnie do wywołania błędu użytkownika. Styl programowania 17. Formułowanie celów. Musi się dokonać na początku projektowania (różne cele mogą być konfliktowe, np.: duża niezawodność, dotrzymanie terminów, minimalny koszt lub czas produkcji, efektywność w użyciu pamięci /szybkości, możliwość późniejszej modyfikacji, uniwersalność, prostota/ łatwość obsługi i konserwacji. Podstawową zasadą obowiązującą podczas formułowania celów jest zasada “skromności”: „Skromny, działający program jest bardziej użyteczny niż program imponujący, ale niedokończony”. Styl programowania 18. Złożoność. Złożoność wpływa na trudności w testowaniu, uruchamianiu i konserwacji. Mniej złożony produkt znacznie łatwiej opanować. Ograniczenie złożoności osiąga się dzięki dzieleniu programu na moduły i projektowaniu zstępującemu, co zmniejsza liczbę poziomów rozumienia. Moduły zmniejszają liczbę możliwych dróg w programie (więc łatwiej dokonywać zmian nie wpływających na inne elementy programu) oraz izolują błędy wewnątrz modułu. Dziękuję za uwagę Wojciech Sobieski Olsztyn 2006-2012