int21h
Jak psát pěkný kód v pascalu
O dokumentu
Tento dokument popisuje vhodný styl pro formátování zdrojových kódů v Pascalu. Vychází z dokumentu
Object Pascal Style Guide, který popisuje standardní styl pro formátování zdrojových kódů v Delphi.
Obsah
1. Nejdůležitější zásady
1.1 Obecné zásady
Žádný řádek ve zdrojovém kódu by neměl být delší než 80 znaků. Na každý řádek píšeme nejvýše
jeden příkaz.
DoSomething;
DoThis;
DoThat;
Špatný způsob
DoSomething; DoThis;
DoThat;
Psaní dlouhých příkazů
V případě dlouhých příkazů a výrazů, kdy délka přesahuje 80 znaků, je vhodné řádek zalomit
za příslušným binárním operátorem.
Result := LongExpression1 or ... or LongExpressionX or
LongExpressionY or ... LongExpressionZ;
Sum :=
VeryLongStatement1 + ... + VeryLongStatementN;
Sum := VeryLongStatement1 + ... + VeryLongStatementX +
VeryLongStatementY;
Nevhodný způsob zalomení:
Result := LongExpression1 or ... LongExpressionX
or LongExpressionY or ... LongExpressionZ;
1.2 Identifikátory
U všech identifikátorů píšeme velké první písmeno. Pokud je název identifikátoru složen z více slov, první písmeno každého takového slova píšeme obvykle velké. Například
VeryLongIdentifier : String;
Takovému způsobu pojmenování se říká
pascalovský styl (Pascal casing, InfixCaps). Je to klasický způsob pojmenovávání identifikátorů v Pascalu, používá se však i v jazyce C#. Ve výjimečných případech (výčtové typy) můžeme použít i jiný způsob zápisu,
velbloudí styl (Camel casing, CamelCaps). Oba styly zápisu se liší pouze prvním písmenem v identifikátoru, identifikátor podle velbloudího stylu má malé první písmeno. Klíčová slova píšeme malými písmeny. Spojování slov podtržítky se
nedoporučuje. Rovněž je nevhodné používat kapitálky (velká písmena), ani pro názvy konstant.
Správný zápis
type
TButtonKind = (bkOk, bkCancel, bkRetry);
var
ConfigPath: String;
AverageSpeed: Integer;
btnClose: TButton;
Špatný zápis
VAR
Config_Path: string;
averagespeed: integer;
UGLY_VALUE: longint;
1.3 Názvy identifikátorů
Jak přehledně zapisovat názvy identifikátorů již víme, nyní si řekneme, jak jejich názvy vhodně zvolit, aby bylo jasné, k čemu identifikátor slouží, zda popisuje proměnnou nebo metodu.
První zásadní věc je nepoužívání češtiny při vytváření názvů jakýchkoliv identifikátorů. Zdrojový kód pak vypadá značně amatérsky. Češtinu lze tolerovat pouze ve výukových materiálech. Zda jsou komentáře česky nebo anglicky záleží na autorovi, v případě smysluplného kódu vystaveného na internetu je rozumnější zvolit angličtinu.
Při pojmenovávání proměnných je obecně doporučováno nepoužívat typ této proměnné v jejich názvu. Příklad nevhodného pojmenování:
SpeedInt: Integer;
Procedury, funkce a metody by měly obsahovat sloveso v rozkazovacím způsobu nebo jiný výraz se slovesem.
procedure DoSomething(ParamX: Longint);
function IsDeviceConnected: Boolean;
1.4 Odsazení
Vždy odsazujeme o 2 znaky. V žádném případě nepoužíváme znak tabelátor. Samozřejmě klávesu "tabelátor" použít můžeme, pokud víme, že do zdrojového kódu vkládá mezery a nikoliv znak #8.
Klíčové slovo begin
se neodsazuje a je vždy samostatně na řádku. Klíčová slova unit, uses, type, interface, implementation, initialization, finalization
musí být zarovnány s levým okrajem, píší se tedy vždy s nulovým odsazením.
Správné odsazení:
if Condition = false then
begin
DoThis;
DoThat;
end else
begin
DoSomethingElse;
...
end;
Špatné odsazení:
if Condition = false then
begin
DoThis;
DoThat;
end else begin
DoSomethingElse;
...
end;
if Condition then
begin DoThis;
DoThat;
end;
1.5 Bílé znaky
Kdy se mezera
nepíše:
- Mezi jméno metody (procedury a funkce) a levou kulatou závorku.
- Před a za operátor . (tečka).
- Mezi unární operátor a operand.
- Před a za kulaté závorky.
- Před a za hranaté závorky.
- Před středník a před čárku.
- Před dvojtečku.
Kdy se mezera
píše:
- Za klíčové slovo
array
- Za čárku.
- Před a za znak
=
- Před a za operátor přiřazení
:=
type
TLines = array [0..9] of String;
var
Lines: TLines;
begin
Result := ComputeSomething(ParamX, ParamY);
Window.Show;
DoSomethingElse(@Result);
DoSomethingElse(@Lines[5, 20]);
end;
Ukázka nepěkného formátování
type
TLines = array[0..9] of String;
var
Lines : TLines;
begin
Result:=ComputeSomething(ParamX, ParamY);
Window. Show;
DoSomethingElse( @ Result);
DoSomethingElse(@ Lines [ 5 , 20 ] );
end;
2. Zdrojové soubory
2.1 Pojmenování souborů na disku
Zdrojové soubory Turbo Pascalu, Borland Pascalu a jednotek Delphi (jakékoliv verze) mají příponu pas
. U zdrojových souborů FreePascalu je vhodné použít příponu pp
. Přípony se píší malým písmenem.
Názvy zdrojových souborů se pojmenovávají klasickým způsobem, tedy například
System.pas, SysUtils.pp, WinBase.pas, OpenGL.pp
Příklad špatného pojmenování:
opengl.pp, system.PAS, Win_Base.PAS, SYSUTILS.PAS
2.2 Deklarace uses
Příklad správného zápisu. Je třeba dodržet maximální délku řádku 80 znaků.
uses Crt, Printer;
uses Crt, Printer, SysUtils, Windows, WinBase,
WinConst, Drawing, Objects;
uses
Crt, Printer, SysUtils, Windows, WinBase,
WinConst, Drawing, Objects;
2.3 Konstanty a inicializované konstanty
Pro pojmenování konstant používáme klasický styl formátování:
const
Radius = 0.5;
StartLength: Integer = 6;
BUFSIZE = 1024;
Buf_Count = 16;
2.4 Datové typy
Řídíme se klasickou konvencí, k identifikátorům datových typů je však rozumné přidávat počáteční písmeno T. Pokud definujeme datový typ ukazatel, přidáváme počáteční písmeno P. Při definici výčtového typu je možné použít velbloudí styl. Používání mezer je probráno v kapitole o bílých znacích. Správný zápis:
type
TLine = array [0..255] of Char;
TMatrix = array [0..255, 0..100] of Real;
TWindowsStatus = (wsActive, wsInactive, wsInvisible);
PPerson = ^TPerson;
TPerson = record
Name: String;
Age: Integer;
Next: PPerson;
end;
Špatný zápis:
type
TLine = array[0..255] of Char;
Matrix = array [0..255,0..100] of Real;
TWindowsStatus=( WS_ACTIVE, WS_INACTIVE, WS_INVISIBLE );
Person = ^TPerson;
TPerson=
record
Name: String;
Age: Integer;
end;
Třída (datový typ class
a object
)
Pro definici třídy platí klasické pravidla, dále je vhodné dodržovat správné pořadí zápisu atributů, vlastností a metod a jejich rozdělení do rozsahů viditelnosti. Metody lze sestavit podle abecedního pořadí, přičemž konstruktory mohou být uvedeny jako první.
unit BaseClasses;
type
TMyOldPascalClass = object(TObject)
private
Position: Longint;
public
constructor Init(Position: Longint);
destructor Done; virtual;
end;
TMyDerivedClass = class(TMyClass)
private
FValue: Integer;
procedure SetValue(Value: Integer);
protected
procedure Sort;
public
constructor Create;
published
property Value read FValue write SetValue;
end;
implementation
constructor TMyOldPascalClass.Init(Position: Longint);
begin
self.Position := Position;
end;
...
end.
2.5 Proměnné
Proměnné deklarujeme klasickým způsobem. Je možné deklarovat více proměnných na jednom řádku, ale objekt je vhodné deklarovat na samostatném řádku. Nezapomeneme za dvojtečku (oddělovač proměnné a datového typu) vložit mezeru, před dvojtečku se mezera nevkládá.
var
SizeX, SizeY: Integer;
MainWindow: TWindow;
AboutWindow: TWindow;
Nevhodná deklarace:
var
SizeX, SizeY :Integer;
MainWindow, AboutWindow : TWindow;
2.6 Procedury a funkce
Pro pěknou definici procedur a funkcí použijeme známé pravidla. Je vhodné poznamenat, že funkci definujeme pro kód vracející
právě jednu hodnotu, procedury definujeme pro kód, který nevrací žádnou hodnotu nebo vrací alespoň dvě hodnoty. Nikdy bychom neměli vytvářet funkci, která vrací výsledky odkazovými parametry.
procedure DoSomething;
begin
Compute;
...
end;
procedure FindTwoSolutions(var ResultX, ResultY: Integer);
function SquareRoot(Value: Real): Real;
function CreateWindowEx(dwExStyle: DWORD;
lpClassName: PChar; lpWindowName: PChar;
dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
hWndParent: HWND; hMenu: HMENU; hInstance: HINST;
lpParam: Pointer): HWND; stdcall;
Příklad nevhodného zápisu
function FindTwoSolutions(var ResultX: Integer): Integer;
function CreateWindowEx(dwExStyle: DWORD;
lpClassName: PChar; lpWindowName:
PChar; dwStyle: DWORD; X, Y, nWidth, nHeight:
Integer; hWndParent: HWND; hMenu: HMENU; hInstance:
HINST; lpParam: Pointer): HWND; stdcall;
2.7 Příkaz if
Při použití tohoto příkazu si stačí uvědomit, že klíčové slovo
begin
bychom měli psát na zvláštní řádek. Je také doporučeno psát příkaz celou konstrukci příkazu
if
minimálně na dva řádky. V případě složitých podmínek se logické binární operátory (
and, or, xor
) píší na konec řádku.
if A < B then
DoSomething;
if A < B then
begin
DoSomething;
DoSomethingElse;
end else
DoThis;
if A < B then
begin
DoSomething;
DoSomethingElse;
end else
begin
DoThis;
DoThat;
end;
if A < B then
begin
DoSomething;
DoSomethingElse;
end
else
DoThis;
if A < B then
begin
DoSomething;
DoSomethingElse;
end
else
begin
DoThis;
DoThat;
end;
if (LongExpression1) or
(LongExpression2) or
(LongExpression3) then
begin
...
end;
Nevhodný zápis:
if A < B then DoSomething;
if A < B then
DoSomething
else DoThis;
if A < B then begin
DoSomething;
DoSomethingElse;
end else begin
DoThis;
DoThat;
end;
if (LongExpression1)
or (LongExpression2)
or (LongExpression3) then
begin
...
end;
2.8 Příkaz for
Příklad správně zapsaného cyklu:
for i := 0 to 10 do
begin
DoSomething;
DoSomethingElse;
end;
Příklad nesprávně zapsaného cyklu:
for i := 0 to 10 do begin
DoSomething;
DoSomethingElse;
end;
2.9 Příkaz while
Příklad správně zapsaného cyklu:
while x < j do
begin
DoSomething;
DoSomethingElse;
end;
Příklad nesprávně zapsaného cyklu:
while x < j do begin
DoSomething;
DoSomethingElse;
end;
2.10 Příkaz repeat
Příklad správně zapsaného cyklu:
repeat
x := j;
j := UpdateValue;
until j > 25;
2.11 Příkaz case
U příkazu větvení si můžeme všimnout výjimky ve způsobu odsazení bloků
begin end
kvůli zvýšení přehlednosti. Příklady doporučeného způsobu zápisu:
case Control.Align of
alLeft, alNone: NewRange := Max(NewRange, Position);
alRight: Inc(AlignMargin, Control.Width);
end;
case x of
csStart:
begin
j := UpdateValue;
end;
csBegin: x := j;
csTimeOut:
begin
j := x;
x := UpdateValue;
end;
end;
case ScrollCode of
SB_LINEUP, SB_LINEDOWN:
begin
Incr := FIncrement div FLineDiv;
FinalIncr := FIncrement mod FLineDiv;
Count := FLineDiv;
end;
SB_PAGEUP, SB_PAGEDOWN:
begin
Incr := FPageIncrement;
FinalIncr := Incr mod FPageDiv;
Incr := Incr div FPageDiv;
Count := FPageDiv;
end;
else
Count := 0;
Incr := 0;
FinalIncr := 0;
end;
2006-11-30 | kdoasi
Datum: 8.3.2008 14:55
Od: Mircosoft
Titulek: alternativně anarchistický názor
Souhlas:
Nemám rád tabulátory (#9) ve zdrojáku.
Nesouhlas:
Nemám rád zbytečné mezery (okolo :=, = apod.).
Nemám rád zbytečné odsazování za každou cenu.
Nemám rád, když příkazy mezi begin a end nejsou zarovnané stejně jako ten begin a end.
Nerad píšu velkými písmeny, pokud to není nezbytně nutné.
Rád píšu víc příkazů na jeden řádek, pokud jsou krátké, souvisí spolu a nezhorší se tím přehlednost (begin x:=3; y:=5; end).
Rád odlišuju klíčová slova velikostí písma podle důležitosti (BEGIN na začátku programu, Begin na začátku procedury a všude jinde jenom begin).
Žádný "jediný správný styl, všechny ostatní jsou špatné" neexistuje. Jsou jenom styly přehlednější a méně přehledné.