Original Article:
"http://www.allegro.com/papers/htpp.html"

Jak kodować: Pascal

Stan Sieler

Allegro Consultants, Inc.

sieler@allegro.com

0. Wstęp

Niniejszy dokument dotyczy, jak napisać jakości kodu Pascal. Nacisk kładzie się na aspektach kodujących pisania kodu Pascal.

Przykładowy program: roman.p.txt, program do konwersji liczb rzymskich na liczby arabskie.

Próbka złe Kod: przycinanie, rzeczywisty kawałek świata rzeczywistego złego kodu.

Jak poprosić o pomoc programistyczną: tutaj.

Uwaga: ten artykuł korzysta Pascal/iX, Pascal na 3000 komputerze HP, ale prawie wszystkie punkty mają zastosowanie do każdego wariantu Pascal, a większość stosuje się do innych języków programowania, jak również.

Chcę dyskusje w tym dokumencie na pokrycie czterech P programowania: filozofię, wydajność, problemy i przenośność. Uważałem próbuje podzielić ten papier na cztery rozdziały, po jednym dla każdego z P, ale sobie sprawę, że dla wielu tematów, które chciałbym umieścić w jednym rozdziale, równie dobre argumenty mogą zostać podniesione za wprowadzenie go do drugiego. Tak więc, zamiast jednego rozdziału za P, mam zorganizowała papier do rozdziałów: styl, Kodowanie wybór, problemy z wydajnością i mobilnością.

W każdym rozdziale, 4 P stosowane są jako zasad leżących u podstaw zbiór wytycznych. Te proponowane przepisy nie powinny być postrzegane tak, jakby były 10 (lub 12% lub $) Przykazań. Są to moje zasady, te, które mam używane (w różnych formach w różnych językach) w piśmie z dnia ponad milion linii kodu. Wytyczne powinny rosnąć, podobnie jak osoby. Mogę patrzeć na programy pisałem w 1970 roku i zobaczyć zmiany w stylu w kolejnych latach. Pomimo zmian, ogólny wygląd pozostał ten sam.

Głównym celem tego artykułu jest zachęcenie czytelników do refleksji na temat różnych aspektów stylu i tworzą własne zasady kodowania. To jest ważne, stanowiącymi podstawę do pisania programów w Pascalu jakości ... lub dowolnym języku.

Napisałem ponad milion linii kodu źródłowego w języku wysokiego poziomu od 1970 roku tym, oczywiście, zawiera kilka pustych linii, linie komentarza i linie, sklonowanych z innych plików. Niemniej jednak, to tło nauczyło mnie, że "wygląd" (lub wygląd) programu jest niezwykle ważne, aby zrozumieć, co kod jest.

0.1 Kod wyrzucane

Wytyczne:

# 1-1. Nie ma czegoś takiego jak kod jednorazowego użytku. W związku z tym, swoje wytyczne stosuje się do wszystkiego, co napisać. Zwłaszcza "wyrzucenie" lub programy "jednorazowe".

Komentarz:

# 1-1. Zauważyłem, że prawie zawsze ponownie wykorzystać moje podobno wyrzucenie lub jednorazowych programów. I, jeśli mam na skróty na przetwarzanie moich wytycznych zawsze mam za to zapłacić później.

1. Styl

Styl, lub jego brak, może znacząco wpłynąć na jakość programu. Kod jakości muszą być napisane tak, że jest ona poprawna, wydajny i utrzymaniu. Wybór i po, zwłaszcza styl może zwiększyć prawdopodobieństwo, że każdy z tych trzech celów zostały osiągnięte. Sekcja ta omówi najpierw zmienne a następnie resztę programu.

1.1 Nazwy: Podstawy

Jednym z kluczy do sukcesu programu jest odpowiedni dobór nazwisk.

Sukces programu leży w Pascal właściwego zrozumienia danych program manipuluje. To zrozumienie jest odzwierciedlone w wyborze struktur danych i zmiennych używanych przez program.

W niniejszym artykule wyrażenie "nazwy", stosowany bez eliminacji, odnosi się do nazw zmiennych, stałych, typów, procedur i funkcji.

Wytyczne:

# 1-11. Używaj rzeczowników dla zmiennych, stałych i typów; używają zwrotów czasownika dla procedur i funkcji.

# 1-12. Rodzaje zazwyczaj powinny mieć "_type" na końcu nazwy.

# 1-13. Nazwy powinny być wyłącznie małe litery, znaku podkreślenia ("_") oddzielające słowa (np: card_counter).

Komentarz:

#1-11.Poniższy przykład jedna linia powinna wystarczyć, aby pokazać znaczenie tej wytycznej:

if card_count = 52 then

Czy "card_count" Zmienna całkowita lub funkcja?Różnica jest krytyczna dla zrozumienia programu.Tylko wytyczna czytelnik może można mieć to jego / jej znajomość angielskiego. (Zasada kapitalizacji nie wystarczyło!)

Ważne jest, aby pamiętać, że inni ludzie będą czytania kodu w przyszłości. ("Inne" ludzie obejmuje Cię dzień Po napisaniu kodu!) Będą potrzebowali "wskaźniki", aby pomóc im właściwie zinterpretować kod ich czytanie.

Według wytycznych # 1-11, "card_count" jest zmienną. Jeśli miało to być funkcja, to jego nazwisko powinno być coś takiego jak "count_the_cards".

#1-12. Niektórzy programiści PREPEND "t_", "typ_", lub "type_". Inne dołączyć "_t", "_typ" lub "_type". Kilka błędne dusze zostały tak zachwycona tym pomysłem, że przygotowałeś "t_" i dopisać "_type" do każdego typu.

Podstawowym założeniem jest to, aby wyraźnie odróżnić nazwy typów zdefiniowanych przez użytkownika od zmiennych i procedury (lub funkcje).

#1-13. Wytyczna ta odzwierciedla fakt, że jesteśmy Anglików. Jeśli Byliśmy niemiecki Głośniki, nasze programy powinny prawdopodobnie używać wielkich liter na początku każdej zmiennej. Zauważ, jak wiele trudniej odczytać to jest?

Widzę trzy powody, dla pierwszej litery (lub wszystkie) z niektórych rodzajów nazw. Brak jest warto:

Czy wybrał ubogich nazw zmiennych, i myślę, że kapitalizacja zrekompensuje. ... nie będzie.

nie jesteś pewien, kompilator wie, że nazwa jest zmienną, jeśli nie są aktywowane w danym stylu.

Niespodzianka: kompilator jest mądrzejszy niż jesteś!

(głównie dla programistów C) chcesz zdolność dokładnie mylić czytelnika przez dwóch niezależnych zmiennych, które różnią się tylko w przypadku ich nazw (np: int foo; char FOO).

... więcej szanownych ścieżki do bezpieczeństwa pracy istnieje.

1.2 Nazwy: Więcej szczegółów

Nazwy typów powinny być opisowe, i powinny być łatwo rozpoznawalne jako typów, tak aby stać się w przypadku stosowania w rodzaju przymusu lub "sizeof" wyrażeń.

Wytyczne:

#1-21. Ogólne typy, które są pakowane tablice char powinien mieć nazwę "pac" z liczbą znaków.

type

pac8 = packed array [1..8] of char;

pac80 = packed array [1..80] of char;

#1-22. Typy, które są tablice powinny mieć "tablicy" w nazwie. (Wyjątek: pac nazwy typu ## (patrz # 1-21).)

#1-23. Typy, które są wskaźniki powinny mieć "ptr" w nazwie. Typy, które są długie wskazówki (64 bity) powinien mieć "lptr" w nazwie. (W Pascal / iX, zwykłe wskaźniki są 32 bity szerokości ... "długi" wskaźnik jest taki, który może wskazać dowolnego miejsca w pamięci.)

#1-24. Zapisy powinny mieć nazwy pól z prefiksem, który odzwierciedla rekord są one częścią.

#1-25. Typy proste nie powinien zazwyczaj odzwierciedlają ich "wielkość".

#1-26. Staraj się unikać korzystania z "prawda" i "fałsz" dla wyników funkcjonalnych. Użyj typu jak "good_failed_type" zamiast.

Komentarz:

#1-21. Język Pascal posiada specjalne zasady dla zmiennych, które są zapakowane tablice char z dolnej granicy 1. Reguły te zostały dodane w celu uczynienia standardem Pascal nadające się do manipulacji tekstem. W rezultacie, większość implementacji Pascal patrz "PAC" jako zmienną (lub typu), który jest pakowany tablica char, w dolnej granicy 1. W związku z tym, jest to wygodne, aby odzwierciedlić tę standaryzację w naszych własnych typów.

Należy pamiętać, że ta wskazówka powiedział typów generycznych. Gdy używam TurboIMAGE (DBMS na HP 3000), i chcesz utworzyć typ, który odpowiada pozycji IMAGE, postaram się dać wpisać nazwę, która jest podobna do nazwy jest:

{IMAGE items: }

{ cust_name x20;}

type

cust_name_type = packed array [1..20] of char;

W powyższym przykładzie, użyłem "20" w deklaracji typu tylko dlatego, że był bezpośrednio oczywiste wartości (podane komentarz o pozycji obrazu). Nigdy nie używać stałą "20" w dalszej części programu. Jeśli muszę odnieść się do "20", chciałbym użyć Pascal / iX budowy "sizeof (cust_name_type)" i chciałbym dodać "const cust_name_len = 20" i używać stała zadeklarować rekord.

#1-24. Wytyczna ta sprawia, że pola rekordu natychmiast rozpoznawalne, gdy są używane w "z" oświadczeniem. Przykład:

Złe:

type

hpe_status = record {name matches MPE/iX's usage}

info : shortint;

subsys : shortint;

end;

hpe_status_ptr_type = ^ hpe_status;

...

var

hs_status_ptr : hpe_status_ptr_type;

...

with hs_status_ptr^ do

begin

info := my_info;

subsys := my_subsys;

end;

A dobrze:

type

hpe_status = record {name matches MPE/iX's usage}

hs_info : shortint;

hs_subsys : shortint;

end;

...

with hs_status_ptr^ do

begin

hs_info := my_info;

hs_subsys := my_subsys;

end;

W zły przykład, czytelnik, który nie zna kodu nie będzie wiedział, że pola wskaźnika są zmieniane. W dobrym przykład, jest oczywiste.

#1-25. W SPL (podobny ALGOL języka programowania), jest to dość powszechne w użyciu przyrostek lub przedrostek oznaczający "type" zmiennej. (Przykład: podwójne ktr'd). Z ograniczeniami Pascala na odpowiadających typów jest to znacznie mniej konieczne.

#1-26. "true" i "false" niewiele znaczą same. Przykłady:

Złe:

function open_files : boolean;

...

open_files := false;

...

if open_files then

...

A dobrze:

 

type

good_failed_type = (failed, good);

 

function open_files : good_failed_type;

...

open_files := good;

...

if open_files = failed then

...

W zły przykład, czytelnik nie ma pojęcia, czy "open_files" powrocie do prawdziwej wartości jest dobry czy zły.

Ta wskazówka jest jeszcze bardziej istotne przy programowaniu w środowisku wielojęzycznym, ponieważ różne języki (i różne systemy operacyjne) mają dziwne pomysły na temat tego, czy "0" (lub "false") oznacza, dobre lub złe.

1.3 Zamawianie Źródło

Uporządkowanie kodu źródłowego może znacznie wpłynąć na czytelność programu. Zamawianie wytyczne można podzielić na trzy obszary: typy i stałe, zmienne i procedury i funkcje.

Wytyczne:

#1-31. Proste stałe powinny być umieszczone na początku obszaru deklaracji, a następnie typów, stałych strukturyzowanych, a następnie przez zmienne. W każdej grupie, identyfikator powinien być umieszczony w pewnym porządku. Jeśli żadna inna kolejność przedstawia się, alfabetycznej należy stosować. Przykład:

const

max_queues = 10;

type

aardvark_quantity_type = 0..9;

queue_name_type = packed array [1..8] of char;

queue_names_type = array [1..max_queues] of queue_name_type;

zoo_fed_arrdvarks_type = array [aardvark_quantity_type] of integer;

#1-32. Co najwyżej jednej instancji "type", a "var" jest potrzebne, a do dwóch przypadków "const" (jeden dla prostych stałych i jednej dla stałych strukturyzowanych).

#1-33. Identyfikatory w strefie deklaracji (stałe, typy, zmienne) powinny zostać uznane za jedno w linii, w jakimś celu. Alfabetycznej jest domyślna. Jeżeli stosowana jest inna kolejność, należy wyjaśnić, z komentarzem.

#1-34. Identyfikatory w strefie deklaracji należy wpisać tak, że "=" znaki są ustawione na stałe i rodzajów, a ":" znaki są dostosowane do zmiennych i pól rekordów.

#1-35. Typy rekordów, które zawierają zagnieżdżone rekordy nigdy nie powinna zostać uznana za "anonimowych typów". Przykłady złych i dobrych praktyk są:

Złe:

type payment_record_type = record

pay_date : date_type;

pay_time : time_type;

pay_style : (paid_cash, paid_check, paid_charge);

end;

A dobrze:

type

payment_style_type = (paid_cash, paid_check, paid_charge);

 

payment_record_type = record

pay_date : date_type;

pay_time : time_type;

pay_style : payment_style_type;

end;

#1-36. "Nawał" zapisów należy unikać, chyba że konieczne do szczelnego wypełnienia pól zastępuje one powodować utratę skuteczności.

Pascal/iX obsługuje "nawał rekord", rozszerzenie poza prostą "zapakowany rekordu". W nawał rekordu, są *no* nieużywane bity. Jeśli zadeklarujesz nawał rekord z pola 1 bit, a następnie przez pole 8-bitowy, a następnie w polu 1 bit, a następnie cała płyta będzie zajmować 10 bitów, a 8-bitowe pole będzie wymagać dodatkowego kodu do ładowania / zapisu.

#1-37. Duże zewnętrzne zmienne bloku (> 256 bajtów) powinny być zgłoszone w ubiegłym, mimo że narusza wytyczne # 1-33. (Podobnie duże zmienne lokalne powinny być zgłoszone w pierwszej kolejności.) (Uwaga: to jest wierzchołek wydajność Pascal/iX ... inne kompilatory innych maszyn prawdopodobnie robić rzeczy inaczej)

#1-38. Procedury i funkcje są mieszane (czyli: nie oddzielne procedury z funkcji).

#1-39. Procedury i funkcje) (powinno zostać uznane w jakimś celu (alfabetyczna jest domyślnie).

#1-40. Więcej niż jeden poziom zagnieżdżonej procedury należy unikać.

#1-41. Intrinsics powinna zostać uznana za jeden raz, na poziomie zewnętrznym, po wszystkich stałych, typów i zmiennych, a przed wszelkimi "zewnętrznych", "do przodu", lub właściwych procedur. ("Wewnętrzna" jest odniesienie do rodzaju pre-kompilowane "zewnętrznej" deklaracji procedury, obsługiwany przez większość języków na HP 3000)

#1-42. Intrinsics powinny być w porządku alfabetycznym, w zestawieniu istotnych plików. Przykład:

Function ascii : shortint; intrinsic;

Function binary : shortint; intrinsic;

Procedure quit; intrinsic;

W powyższym przykładzie, dwie przestrzenie zostały wprowadzone po wyrazie "Function", tak, że nazwy wszystkich intrinsics będzie wyrównana, niezależnie od tego, czy były to funkcje lub procedury. Szkoda, że Pascal pozwala nam udowodnić kompilator, że znamy typ funkcjonalny co wewnętrzne.

Uwaga dużej litery "P" i "F" w powyższym przykładzie. To jest jeden przypadek bardzo przydatne dyscypliny kodowania, że opisana w wytycznych #1-45 poniżej.

#1-43. Wszystkie procedury i funkcje powinny być zadeklarowane w deklaracji "do przodu", które są w porządku alfabetycznym.

#1-44. Typy, które są "wypełniacze" powinna być uznana za "całkowitą" lub "bajt" (gdzie "bajt" jest zadeklarowana jako 0..255), a nie jako "char" dla ich typów podstawowych.

#1-45. "do przodu", "zewnętrzne" i "wewnętrzne" procedura (i funkcji) deklaracje powinny wykorzystać pierwszą literę "wewnętrzny" i "Function".

Komentarz:

#1-34. I ogólnie wyrównać "=" dla typów i consts w kolumnie 31 ":" w dziedzinach w rodzaju również w kolumnie 31 i ":" dla zmiennych w kolumnie 19. Jeżeli zmienne mają wystarczająco długie nazwy, ja "będziesz często po prostu wyrównać ":" w kolumnie 31. I zastosować tę dostosowanie do ":" użyte w deklaracji parametrów, takich, że nazwa zmiennej zaczyna się w kolumnie ??:

procedure parse_gribbitz (

a_token : str80;

var status : boolean;

anyvar stuff : char)

option default_parms (

stuff := nil);

W powyższym przykładzie, należy pamiętać, że nazwy parametrów są wyrównane. (Oczywiście, nie zawsze jest to możliwe, zwłaszcza jeśli parametr $ $ wyrównanie informacji podano). (Uwaga: "anyvar" jest ponownie w 2-9 poniżej)

#1-35. Zmienne (i pola rekordów), które są anonimowe typy nie mogą być przekazywane przez odniesienie (jako parametry "var") do zwykłych procedur. Rzeczywiście, najczęściej anonimowe zapisy nie mogą być przekazywane przez wartość w procedurach.

#1-36. Dostęp do pola "nawał" rekordy może trwać do trzech razy ilość instrukcji, które były wymagane, jeśli rekord nie był nawał. Rozważmy następujące dwa rodzaje:

type

bad_type = crunched record

bad_misc : shortint; {Bytes 0, 1}

bad_status : integer; {Bytes 2, 3, 4, 5}

end; {Total size: 6 bytes}

 

good_type = record

good_misc : shortint; {Bytes 0, 1}

good_status : integer; {Bytes 4, 5, 6, 7}

end; {Total size: 8 bytes}

Gdy "bad_status" pole jest dostępne, Pascal/iX emituje trzy instrukcje (LDH, LDH i DEP). Gdy "good_status" pole jest dostępne, Pascal/iX emituje jedną instrukcję (LDW).

#1-37. Pascal/iX może skutecznie uzyskać dostęp tylko pierwsze 8192 bajty globalne lub *last* 8192 bajtów zmiennych lokalnych. Pascal/iX przydziela zmienne w (mniej więcej) w pierwszym widać, pierwszej przydzielonej sposób. Tak więc, dla zmiennych globalnych umieszczenie mali pierwszy i dużych, drugi wydaje się być bardziej skuteczna. Dla zmiennych lokalnych, stawiając duże te pierwsze i te mniejsze drugie są bardziej wydajne.

Ponieważ Pascal/iX przydziela zewnętrzny blok ("global") zmienne w kolejności odwrotnej niż zmiennych lokalnych, regułą jest:

  • W zewnętrznej bloku, zadeklarować małe zmienne pierwszy, a twoje duże zmienne sekundę;

  • W procedur / funkcji, zadeklarować duże zmienne pierwszy i małe zmienne sekund.

Rozważmy następujące przykłady:

Złe:

var {outer-block variables}

big_array : array [0..9999] of integer; {40,000 bytes}

ktr : integer;

...

procedure foo;

var

ktr2 : integer;

big_array_2 : array [0..9999] of integer; {40K bytes}

 

A dobrze:

 

var {outer-block variables}

{small variables...}

ktr : integer;

 

{big variables...}

big_array : array [0..9999] of integer;

...

procedure foo;

var

{big variables...}

big_array_2 : array [0..9999] of integer; {40K bytes}

 

{small variables...}

ktr2 : integer;

 

W złym przykładem, Pascal/iX będzie korzystać z dwóch instrukcji, aby uzyskać dostęp " ktr" i "ktr2". W dobry przykład, Pascal/iX wykorzysta pojedynczą instrukcję, aby uzyskać dostęp " ktr" i "ktr2".

#1-38. Zróżnicowanie Pascala funkcji w porównaniu procedur jest niefortunne, co najlepsze. Nie powinny zachęcać projektantów językowych uwiecznić tę lukę.

#1-39. Pascal/iX "$locality" oświadczenie może być używany, aby powiedzieć łącznik do procedur grupy określone razem, niezależnie od ich kolejności w kodzie źródłowym.

#1-40. Pascal pozwala procedury mają być zgłaszane w ramach procedur, które są zadeklarowane w ramach procedur, które są ...

Procedury zagnieżdżone zapłacić karę wydajności w czasie wykonywania, gdy dostęp do zmiennych globalnych z nich, które są lokalne do okolicznych procedur.

Procedury zagnieżdżone więcej niż w sumie dwa głębokie (np: z "poziomu zewnętrzna" procedury i jednej procedury wewnętrznej) zwykle oznacza, że ​​inne problemy projektowe istnieje.

Niektóre debuggery mają trudności ustawienie punktów w procedurach zagnieżdżonych.

#1-43. Ta dodatkowa praca często opłaca się dobrze pisząc "modułu", który będzie połączony z innymi programami. Często umieścić wszystkie moje "do przodu" deklaracji do pliku, a następnie użyć polecenia po QEDIT do generowania pliku z "zewnętrzne" deklaracje dla innych modułów do $include:

t myfile.forward

c "forward"(S)"external"@

k myfile.external

(QEDIT jest powszechnie stosowane edytor na HP 3000)

#1-44. Debug/iX's Format wirtualnej polecenia (FV) będzie produkować bardziej czytelne wyjście dla losowych danych, gdy typ bazowy jest numeryczne zamiast znaku. (Debug/iX jest debugger pakiecie z MPE/iX na HP 3000)

#1-45. Dzięki tej wytycznej i powiązanym jeden w następnej sekcji, polecenie QEDIT jak:

l "procedure" (s)

wyświetli pierwszą linię każdej deklaracji procedury. Należy pamiętać, że tylko rzeczywisty oświadczenie zostaną wymienione, a nie "do przodu" lub "zewnętrzne" deklaracje, ponieważ nie zostały uznane przez duże "P" w "Procedure".

Uwaga: nie mów edytor automatycznie zmieni bieg cały tekst będzie wyszukiwanie (np: Ustaw okno (UP) w QEDIT), jako że będzie sprzeczna z celem tej wytycznej.

1.4 Kod wykonywalny

Ta sekcja omawia style kodowania dla kodu wykonywalnego ramach programu Pascal.

 

Wytyczne:

 

#1-50. Cały kod powinien być małe.

 

#1-51. Komentarze powinny być w języku angielskim, a powinny być w małych liter, tak jak jest to praktyka w języku angielskim.

 

#1-52. Komentarze powinny pojawić się w jednym z dwóch stylach, w zależności od ich wielkości:

 

  • ustawione pod wybranym kolumnie na prawo od kodu (a więc oko może rozróżnić kodu i komentarz).

  • wyrównane 6 miejsc na prawo od obecnego kodu wcięcia, z pustą linią powyżej i poniżej.

 

Przykład:

 

{the following loop looks for a null character}

 

null_index := -1; {-1 will mean "not found"}

test_inx := 0; {index of first char}

done := (len = 0); {don't loop if no data}

 

while not done do

begin

{see if current character is null...}

if buf [test_inx] = chr (0) then

begin {found a null!}

null_index := test_inx; {remember location}

done := true; {terminate loop}

end

 

else

begin {incr inx, check end}

test_inx := test_inx + 1;

if test_inx >= len then {inx is 0-based}

done := true;

end;

end; {while not done}

 

#1-53. Komentarze Wielu linii mogą być napisane "{" i "}" w każdej linii, albo z "{" i "}" pojawia się tylko raz, w liniach.

 

#1-54. "{" I "}" znaki są używane, aby rozpocząć i zakończyć komentarzy, nigdy "(*" i "*)" par.

 

#1-55. "{" Nie jest typowo następnie po spacji, ani nie jest "}" zazwyczaj poprzedzone miejsca (chyba że jest to w celu dostosowania jej przed Line "}").

 

#1-56. Linie nie powinny być dłuższe niż 72 bajtów być, choć Pascal/iX umożliwia dłuższe linie wejściowe.

 

#1-57. Puste linie kosztować nic w czasie wykonywania, i powinien być używany obficie na oddzielne sekcje kodu. Przykład:

 

if ktr > max_ktr then

max_ktr := ktr; {remember new high water}

 

done := false;

while not done do

begin

...

 

#1-58. "end" oświadczenie nie musi mieć komentować. Pascal nigdy nie sprawdza, że ​​twój komentarz odpowiada rzeczywistości, w każdym razie.

 

#1-59. Podstawową jednostką wgłębienia wynosi 3, a nie 4 lub 2.

 

#1-60. Tiret "begin" s 3 miejsca więcej niż na początku poprzedniej linii. Kod po "begin" (włącznie z "end") jest na tym samym poziomie, co "begin".

 

#1-61. Linie podtrzymujących wcięciem 6 ponad początkiem pierwszej linii.

 

#1-62. "then" z "if/then" oświadczenie jest zwykle na tej samej linii, co reszta wyrażenia logicznego, a nie na następnej linii samo (o ile nie jest odstępem, a następnie jest wcięty 6), i nigdy się na sama linia, rachunku po "then".

 

#1-63. "else if" konstrukt może być traktowany tak, jakby to były nowe Pascal konstrukt: "elseif". (Tj: "if" następuje "else" na tej samej linii.)

 

#1-64. "Goto 999" jest akceptowanym sposobem rozgałęzienia na końcu procedury (funkcja).

 

#1-65. Brak innych "goto" s są konieczne.

 

#1-66. Staraj się, aby procedury poniżej pięciu stron (300 linii).

 

#1-67. Nigdy nie używać słowa "procedure" lub "function" w komentarzu dokładnie wszystkich małych liter. Zamiast tego należy użyć "routine" lub "PRocedure" lub "FUnction".

 

#1-68. Zawsze zakończyć procedurę lub funkcję z komentarzem w postaci:

 

end {nameofroutine proc};

 

#1-69. Wstaw spację pomiędzy nazwą procedury / funkcji oraz "(" parametru listy.

 

#1-70. Umieść puste po każdym przecinku w liście parametrów.

 

#1-71. Wstaw spacje wokół operatorów (np: ":=", "+", "-"), a przed nawiasach lewej (" [").

 

Komentarz:

 

#1-52. Wyrównane komentarze dokonać neater Kod wygląd. Praktyka ta umożliwia czytelnikowi łatwo odczytać kodu lub komentarze.

 

#1-55. Praktyka zawsze po "{" i przestrzeni z poprzedniego a "}" odpady cennego miejsca na linii.

 

#1-56. Długie linie nie będą również listy na większości terminali, ani też nie są do przyjęcia dla wszystkich redaktorów.

 

#1-58. Ja umieścić komentarz na "end" oświadczenie, gdy jest więcej niż około 10 linie z odpowiednią "begin".

 

#1-60. Wartość "3" i nakaz przeciwko "podwójnym wcięciem" oszczędza miejsce i sprawia, że wynik był bardziej czytelny. Rozważmy następujące dwa przykłady:

 

Złe:

 

for i := 1 to 10 do

begin

buf [i] := 0;

foo [i] := 0;

end;

if ktr = 0 then

begin

if not done then

begin

...

 

A dobrze:

 

for i := 1 to 10 do

begin

buf [i] := 0;

foo [i] := 0;

end;

 

if ktr = 0 then

begin

if not done then

begin

...

 

Wiele Pascal programiści widziałem "wcięcia" styl dwukrotnie, ponieważ profesor za UCSD Pascal (po roku 1970), stosowane w tym stylu. Należy pamiętać, że był przede wszystkim nauczycielem, nie programistą.

 

#1-61. Przykład:

 

if (card_counter = max_card_counter) and

all_cards_accounted_for then

begin

...

 

Celem wcięcia wierszy kontynuacji jest, aby było jasne dla czytelnika, że przed linia ciągłego do następnego wiersza. Jeżeli nie stosuje się dodatkowe wcięcie, to trudno jest określić różnicę pomiędzy kolejnego zestawienia i kontynuacji obecnego rachunku.

 

Kiedy mam kompleks "and/or", staram się zrobić to czytelne, gdy robi wierszy kontynuacji:

 

Złe:

 

if ((card_counter = prior_card_counter) and ((number_of_cards_left

> cards_for_book)) then

begin

 

A dobrze:

 

if ( (card_counter = prior_card_counter)

and (number_of_cards_left > cards_for_book) ) then

begin

 

W zły przykład, zauważyć, jak "begin" zaciera się "and", począwszy od tej samej kolumnie.

 

#1-62. Słowo "then" jest lukrem składniowym: nie tuczy listę, a nie wartość odkupieńczą. Gdy czytelnik widzi "if", on lub ona automatycznie wie, że "then" nadchodzi, w końcu. Wcięcia sam wystarczyłoby powiedzieć czytelnikowi, że "to" oświadczenie zostało znalezione. Przykłady:

 

Złe:

 

if card_counter = max_card_counter

then done := true

else ...

 

A dobrze:

 

if card_counter = max_card_counter then

done := true

else

...

 

W powyższym zły przykład, czytelnik musi psychicznie przesiać przez nadmiar słownictwa ("then") przed "done :=", aby zrozumieć wpływ z "true" wyrażenia logicznego. W dobry przykład czytanie lewej stronie aukcji wystarczy.

 

#1-63. "else if" konstrukcje zazwyczaj znajdują się w jednej z dwóch sytuacji:

 

  • "run-on", "if/then/else". Na tej konstrukcji, "else if" na tej samej linii jest naturalnym zwiększy ich czytelność.

  • zagnieżdżone "if/then/else". Na tej konstrukcji, "else" z "if" wcięty w następnej linii jest naturalne.

 

Przykładem "run-on" "if/then/else":

 

if token_check ('EXIT') then

wrapup

else if token_check ('LIST') then

do_list

else if token_check ('PRINT') then

do_print

else

writeln ('Unknown command: ', token);

 

Uwaga: w powyższym stylu, będę często umieścić 5 dodatkowych spacji przed pierwszym "token_check", tak, że polecenie QEDIT jak LIST "token_check" pokaże wszystkie trzy "token_check" frazy ładnie wyrównane.

 

Przykładem zagnieżdżone "if/then/else":

 

if card_counter = max_card_counter then

if done then

...

else

discard_current_card

else

if current_card = joker then

try_best_wildcard

else

calculate_score;

 

Styl odradzam jest następujący:

 

if token_check ('EXIT') then

wrapup

else

if token_check ('LIST') then

do_list

else

...

 

Powyższy styl ma poważne konsekwencje, jeśli w porę czytelność "Strona wysuwania" występuje w wykazie pomiędzy "else" i następnego wiersza "if" linii.

 

#1-64. Pascal brakuje "exit" oświadczenie. Zarówno C i SPL mieć jakąś formę "Powrót z tej procedury w tej chwili" oświadczenia. Jest to jedyne miejsce, używam "goto" w Pascalu.

 

#1-67. Wytyczna ta oznacza, że redaktor "znaleźć" i "lista" polecenia szuka "procedure" i "function" nigdy nie przypadkowo znaleźć komentarz linie zamiast. (Patrz także #1-45).

 

#1-68. To sprawia, że bardzo łatwo znaleźć koniec każda (lub wszystkie) procedury (ów) z poleceniem "find".

 

#1-69/70/71. Blankiety aby zwiększyć czytelność kodu, tak jak robią angielskie bardziej czytelny. Uwaga puste po przecinka w zdaniu poprzednim. Przykład:

 

Złe:

 

fid:=fopen(filename,3,0);

 

A dobrze:

 

fid := fopen (filename, 3, 0);

 

2. Kodowanie wybór

 

Ta sekcja dotyczy wyborów dokonywanych na piśmie kod wykonywalny.

 

Wytyczne

 

#2-1. Zdecyduj, czy Twój styl jest mieć funkcji, które zwracają błędy, lub procedury, które mają parametry stanu (lub oba), a następnie trzymać się go.

 

#2-2. Nie używaj "with" do prostego wskaźnika deferencing. Należy używać tylko "with", jeżeli indeksowania do tablicy.

 

#2-3. Staraj się unikać "repeat" pętli, przy użyciu "while" pętli zamiast.

 

#2-4. Staraj się unikać "escape" poza zakresem w "try/recover" bloku.

 

#2-5. Unikaj "string" s za PAC. PAC jest Pakowane Array Char w dolnej granicy 1.

 

#2-6. Rozszerzenia Pascal/iX, kiedy to możliwe, chyba że przenośność jest głównym celem.

 

#2-7. "try/recover" budowy w Pascal/iX jest bardzo przydatne do łapania błędów: niespodziewane i celowo spowodował. (try/recover mechanizm jest nieco podobny błąd do połowu połowu / rzucać się w niektórych innych językach)

 

#2-8. Użyj $type_coercion 'representation'$. Nigdy nie należy używać noncompatible poziomu typu przymusu.

 

#2-9. "Anyvar" typ parametru jest przydatna. Rozważ używanie go, gdy chcesz przekazać różne typy zmiennych do jednej procedury.

 

#2-10. "Uncheckable_anyvar" opcja dla procedury powinny być stosowane, gdy są deklarowane parametry "anyvar", chyba że wyraźnie chce Pascal/iX przekazać ukrytą "actual size" parametr.

 

#2-11. Podczas korzystania z "anyvar", upewnij się, że formalny typ parametru odpowiada ograniczeń wyrównanie oczekiwanych rzeczywistych typów. Czyli: jeśli parametr formalny jest zadeklarowana jako "integer", a następnie Pascal/iX zakłada, że ​​wszystkie adresy przeszły do ​​tego parametru są wielokrotnością 4. Korzystanie z "char" (lub innego rodzaju bajtowi) jako formalny typ parametru Jeśli chcesz przekazać wszelkiego rodzaju adresów bezpiecznie.

 

#2-12. "Default_parms" opcja procedura powinna być traktowana jako środek tworzenia długi rzeczywisty parametr wymienia krótszy (dla zwykłych przypadkach).

 

Komentarz:

 

#2-1. Czasami wracam szybki ogólny wynik z "good_failed_type", oraz szczegółowy błędu w parametrze stanu. Przykład:

 

function open_files (var status : hpe_status) : good_failed_type;

...

if open_files (status) = failed then

report_status (status);

 

#2-2. Pascal zapewnia "with" oświadczenie, które może, w niektórych przypadkach, zapewnić kompilator z nutą, w jaki sposób zoptymalizować instrukcje emituje w kodzie. Dodatkowo, "with" Oświadczenie można zapisać kolejny pisać.

 

Przykładem bezużyteczne "with" jest:

 

var

ptr : hpe_status_ptr_type;

...

with ptr^ do

begin

hs_info := 0;

hs_subsys := 0;

end;

 

To jest "bezużyteczny", ponieważ kompilator i optymalizator prawdopodobnie zrobić tylko tak dobrej roboty emitowania optymalny kod gdybyśmy powiedzieli:

 

ptr^.hs_info := 0;

ptr^.hs_subsys := 0;

 

Należy pamiętać, że kod brał pięć linii przy użyciu "with" oświadczenie oraz dwie linie bez niego.

Wreszcie fakt, że "hs_info" i "hs_subsys" są rzeczywiście pola rekordu wskazywanego przez "ptr" jest trochę przesłonięta, gdy "with" jest używany.

 

Przykładem użyteczne "z" jest:

 

var

statuses : array [0..9] of hpe_status_type;

...

with statuses [k] do {optimize hs_@ fields}

begin

hs_info := 0;

hs_subsys := 0;

end;

 

Uważam, że ten przykład "użyteczne", ponieważ optymalizator miałby więcej pracy stara się opracować optymalny kod równoważne nie ze stwierdzeniami:

 

statuses [k].hs_info := 0;

statuses [k].hs_subsys := 0;

 

W powyższych przykładach, jest to kuszące, aby wyrównać ":=" s z prawej większości ":=" z bloku instrukcji przypisania. Kiedyś często to zrobić, gdy miałem cztery lub więcej podobnych zadań z rzędu.

 

Zaletą jest zwiększona czytelność ponieważ czynią oczywistym fakt, że dane są podobne (z powodu dopasowane ":=" s).Wadą jest to, że proste polecenie QEDIT zaprojektowane do listy gdzie "hs_info" pole jest zmieniona (np: lista "hs_info :=") nie powiedzie się. I okazało się, że możliwości wyszukiwania-for-zleceń przeważają-danych jest związanego korzyści, dla mnie.

 

#2-3. Gdy "repeat" pętla spotkałem, czytelnik nie wie, co jest warunkiem zakończenia, aż wiele więcej linii źródła programu są czytane. Oznacza to, że on lub ona nie będzie mógł sprawdzić odpowiednie ustawienie stanu zakończeniu. "while" pętelka pozwala uniknąć tego problemu, ponieważ warunek zakończenia jest wyraźnie podany w górnej pętli.

 

Powtarzania pętli może być zazwyczaj zmieniane w pętli while łatwo:

 

before:

 

repeat

begin

...

end

until

buf [inx] = 0;

after:

 

done := false;

while not done do

begin

...

done := (buf [inx] = 0);

end; {while not done}

 

#2-4."non-local escape" kosztuje tysiące cykli czasu procesora do wykonania. Krótko mówiąc, nigdy nie planujesz używać tej struktury jako normalnego sposobu powrotu z procedury. Przykłady:

 

Złe:

 

procedure do_work; {note: no status parameter!}

...

if problem then

escape (i_failed);

...

 

A dobrze:

 

procedure do_work (var status : hpe_status_type);

label

999;

...

if problem then

begin

status := my_failure_status;

goto 999; {exit}

end;

...

999:

 

end {do_work proc};

 

#2-5. Struny ukryć ogromną ilość powolny i nieco nieprawidłowego kodu generowane przez kompilator. Konkatenacji ciąg, w szczególności, może spowodować "wycieki pamięci", gdzie proces zabraknie miejsca sterty. PAC to Messier do czynienia, ale o wiele bardziej efektywne. Jest to wydajność w porównaniu do estetyki kompromis.

 

#2-6. Pascal/iX jest bardzo przydatne język właśnie dlatego, że ma duży korpus rozszerzeń do standardowego Pascal. Jeśli unikają korzystania z nich, można byłoby lepiej, programowanie w ANSI C lub C ++.

 

#2-7. "Try/recover" nie jest gwarantowane, aby złapać wszystkie błędy, które występują w nim. Nieoczekiwane błędy (np: nieważne indeksowe, złe wirtualny adres) wywołania rutynowego systemu operacyjnego o nazwie trap_handler który będzie "chodzić" z powrotem przez swoich markerów stosu szukasz najnowszej "spróbować / odzyskać" bloku. To "zaledwie" może nie, jeśli stos jest uszkodzony, i "try/recover" nie będzie można znaleźć. Jeśli tak się stanie, a jeśli to właściwe obsługi pułapki (np: XCODETRAP) nie został uzbrojony, twój proces zostanie przerwany.

 

#2-8. Rodzaj przymusu jest jednym z najlepszych rozszerzeń w Pascal/iX. To zapewnia kontrolowane sposób nadrzędnymi typu sprawdzanie Pascala. Dyrektywa $type_coercion mówi Pascal/iX, jaki poziom typu przymus chcesz zezwolić w programie. Istnieje około pięciu różnych poziomach. Poziom Gorąco polecam to przedstawienie. Poziom ten pozwala na ekspresję jednego typu do zmuszany (traktowane jako) innego typu, wtedy i tylko wtedy, gdy oba rodzaje są dokładnie tej samej wielkości (w jednostkach bitów, a nie bajtów).

 

Poziom noncompatible mówi Pascal/iX, że nie powinno być żadnych ograniczeń w rodzaju przymusu. Prowadzi to do ciekawych błędów w programach. Niektóre MPE/iX awarii systemu można przypisać do korzystania z tego rodzaju typu przymus nieprawidłowo. Poniższe przykłady pokazuje, jak można ukryć błędy noncompatible.

 

przy założeniu, że:

 

var

big_ptr : globalanyptr;

my_address : integer;

small_ptr : localanyptr;

 

Złe:

 

$type_coercion 'noncompatible'$

my_address := integer (big_ptr); {will get half of data!}

my_address := integer (small_ptr); {will get 32 bit value}

 

A dobrze:

 

$type_coercion 'representation'$

my_address := integer (big_ptr); {will get syntax error}

my_address := integer (small_ptr); {will get 32 bit value}

 

W zły przykład, zmuszanie big_ptr powoduje ustawienie my_address do górnych 32 bitów big_ptr (tj: id miejsca), w milczeniu tracąc dolne 32 bitów adresu. W dobry przykład, Pascal/iX wygeneruje błąd składni na próbie zmuszenia wyrażenie 64-bitowej (big_ptr) do wartości 32-bitowej (integer - liczba całkowita).

 

#2-9. "Anyvar" jest rozszerzenie Pascal/iX "var". Gdy parametr formalny jest zadeklarowana jako "anyvar", kompilator pozwala jakakolwiek zmienna być przekazywane jako rzeczywistego parametru. Bez takiej funkcji, a bez obiektowego Pascala, nie można napisać jedną procedurę, że zero (usuń) dowolną zmienną (patrz poniżej na przykład).

 

Domyślnie, gdy parametr jest zadeklarowana jako anyvar Pascal/iX przejdzie adres rzeczywistego parametru *and* ukrytą liczbę całkowitą przez wartość, która rejestruje wielkość rzeczywistego paramter. Poniższy przykład pokazuje, co jest przekazywane do formalnego paramter jak: "anyvar foo : integer" i wpływa na "sizeof (foo)" w ramach procedury:

 

Rzeczywisty typ parametru

Rozmiar pola ukryty

sizeof (foo)

char

1

1

shortint

2

2

integer

4

4

longint

8

8

real

4

4

longreal

8

8

hpe_status (see #1-24)

4

4

packed array [1..80] of char

80

80

 

 

#2-10. Używam "anyvar" dość często. Jednym z przykładów jest:

 

procedure zero_var (anyvar foo : char);

{Purpose: zero every byte in the parameter}

var

bytes_left : integer;

byte_ptr : ^char;

 

begin

 

$push, range off$

byte_ptr := addr (foo);

bytes_left := sizeof (foo); {Note: gets actual size!}

 

while bytes_left > 0 do

begin {zero one byte}

byte_ptr^ := chr (0);

bytes_left := bytes_left - 1;

byte_ptr := addtopointer (byte_ptr, 1);

end;

$pop$ {range}

 

end {zero_var proc};

 

 

Należy zwrócić uwagę na komentarz do $pop$... pozwala mi przypomnieć, co opcje $pop$ rzekomo przywracania.

W Pascal/iX, $push$ zapisuje stan większości opcji kompilatora oraz $pop$ przywraca je. Zatem $push, wahają off$ ... $pop$ czasowo wyłącza opcję "range", a następnie przywraca go do starego stanu ... co jest znacznie inna, niż po prostu się włączał, gdy "zrobione"!

 

Oczywiście, Pascal/iX pozwala na jeszcze szybszy sposób zerowania zmienną, która dzieje się dobrze z Rejestrowalne parametrów anyvar.Cały kod powyższej procedury (od "begin" i "end") może być zastąpiony przez:

 

fast_fill (addr (foo), 0, sizeof (foo));

 

#2-12.Poniższy przykład, procedura, że większość użytkowników będzie zadzwonić z "false" w drugim parametrze, pokazuje użyteczność "default_parms":

 

const

print_with_cr = 0;

print_without_cr = 1;

 

procedure print_msg (

msg : str80;

cr_or_no_cr : integer)

option default_parms (

cr_or_no_cr := print_with_cr);

 

var

cctl_val : shortint;

 

begin

 

if cr_or_no_cr = print_without_cr then

cctl_val := octal ('320')

else

cctl_val := 0;

 

print (msg, -strlen (msg), cctl_val);

{Note: ignoring errors from print intrinsic}

 

end {print_msg};

...

print_msg ('Starting...', print_without_cr);

print_msg ('Ending'); {does a CR/LF at end}

 

Należy zauważyć, że nie użyłby "default_parm" dla parametru, który jest pominięty mniej niż około 75% czasu.

 

3. Problemy z wydajnością

 

Dwa największe problemy z wydajnością w programach Pascal/iX pomocą wbudowanego I/O, a za pomocą strun.

 

Wytyczne:

 

#3-1. Unikać Pascal I/O. Zamiast używać intrinsics.

 

#3-2. Unikać Pascal I/O. Zamiast używać intrinsics. Jest to warto powiedzieć dwa razy!

 

#3-3. Unikać sznurki w najważniejszych obszarach działania.

 

#3-4. Wyłącz sprawdzanie zasięgu ($range off$) tylko wtedy, gdy masz pewność, że program działa poprawnie.

 

#3-5. Użyj optymalizator Pascal/iX ($optimize on$).

 

Komentarz:

 

#3-1. Jeśli hermetyzacji połączeń I/O, to ich podstawowa realizacja można łatwo zmienić, aby korzystać z MPE intrinsics. Pomaga to również przenoszenia różnych systemach operacyjnych oraz w różnych językach. "Print_msg" procedura w komentarzu #2-12 jest przykładem.

 

Drugim powodem, dla uniknięcia Pascal I/O konstruuje jest efektywność. Pascal/iX I/O są bardzo nieefektywne procedury. Wytyczna ta jest ważna dla większości języków.

 

#3-3. Wyrażenia typu String spowodować kompilator emitować dużo połączeń do "pomocniczych" rutyny. Zamiast przydzielania jeden obszar roboczy w stos, te procedury alokacji (i zwalniania) w wielu dziedzinach pracy na stercie. To może być kosztowna działalność, i może prowadzić do utraty miejsca sterty i ostatecznego zakończenia procesu.

 

#3-5. Jeśli program działa poprawnie unoptimized i ma problem zoptymalizowany, to nie są prawdopodobnie jedną (lub więcej) zmiennych niezainicjowane. Drugim najczęstszym problemem jest za pomocą wskaźników w taki sposób, że optymalizator nie spodziewa (zwłaszcza gdy dostęp zmienne lokalne za pośrednictwem wskaźników).

 

4. Przenośność

 

Przenoszenia programów napisanych w Pascal/iX może być wzbogacony o kilka technik. Należy pamiętać jednak, że większość innych Pascal implementacje nie są tak bogate jak Pascal/iX. Delphi i Turbo Pascal (na kompatybilnych IBM PC) zapewniają niektóre z tych samych funkcji, jak Pascal/iX.

 

#4-1. Unikaj tych rozszerzeń Pascal/iX: rozszerzalny, tylko do odczytu, anyvar, opcję uncheckable_anyvar, default_parms, globalanyptr.

 

#4-2. Uniknąć większości $ dyrektyw (np .: $extnaddr$).

 

#4-3. Użyj typu przymus tylko dla typów identycznych rozmiarach. (dobra wskazówka, nawet jeśli nigdy nie zamierzają portu kodu!) Najwięcej Pa komputerów PC mają formę typu przymusu. Mogą się do niego jako "type casting".

 

#4-4. Unikaj "nawał" rekordów. Nawet większość języków C nie mają odpowiednik funkcjonalny. Obejmuje to unikanie "$ HP3000_16$".

 

#4-5. Hermetyzacji "strange" konstrukcje, gdzie to możliwe.

 

#4-6. Hermetyzują I/O. To nie jest kwestia języka przenoszenia tak bardzo, jak system operacyjny and/or kwestii wydajności.

 

#4-7. Miej linie kodu źródłowego krótki (72 znaków lub mniej w linii).

 

#4-8. Użyj typów zdefiniowanych przez użytkownika, takich jak "int16" i "int32" zamiast "shortint" lub "integer". Uwaga: to jest bardzo ważne dla programistów C!

 

#4-9. Należy pamiętać, że pola w dokumentacji mogą być pakowane inaczej na różnych komputerach.

 

#4-10. Standardowy Pascal nie pozwala wskaźniki zwrócić się do zmiennych. (Mogą wskazywać tylko na stercie.)

 

5. Podsumowanie

 

Najkrótsze podsumowanie tej pracy jest zapewne: można oceniać książki po okładce. Jeśli program wygląda ładnie, to prawdopodobnie nie jest miłe.

 

Original: http://www.allegro.com/papers/htpp.html