原文?:http://dn.codegear.com/article/10280
翻訳時に参照した原文が見当たりません。上のリンクは検索して見つかった原文らしきものですが、翻訳以降に更新されているかもしれず、この翻訳とはずれがあるかもしれません。

訳注:例外クラスや引数の命名規則が無い等、これだけでは規約として不十分だと思います。適当に補完しましょう。ちなみに、前置きに書かれている内容とは裏腹に、VCL のソース中にもこの規約に従っていないソースは多々あります。


サイト内関連リンク:Econos - Delphi 4 開発者ガイド コーディング標準 , The Delphi Bug List 日本語訳




Object Pascal スタイルガイド - by Charles Calvert

要約:この記事は Delphi コードの書式に関する標準スタイルに付いて述べています.この標準スタイルは,Delphiチームが発展させてきた習慣に基いています.
Object Pascal スタイルガイド

この規約は Delphi のコードの書式に関する標準スタイルに付いて述べています.この標準スタイルは,Delphi チームが発展させてきた習慣に基いています.

多くの適切に確立した仕事場では,ここで規定するものとは異なる習慣を持っていて当然だと思います.従って,私たちはあなたが自分のコードを Borland やプロジェクトJEDI,あるいはその他の公のリポジトリに送る前に,あなたのコードを Borland スタイルに変換するツールを使用することを強く推奨します.あなたの習慣を変えることを強制したくはありませんが,私たちは Borland 製品とともに出荷される全てのコードに対し,この習慣に従うことを強く要求しています.どのような形式であれ,公のリポジトリにコードを提出する際にはこの習慣に従うことを強く奨励します.

Object Pascal は美しく設計された言語です.その最大の長所のひとつは可読性です.この標準は,その Object Pascal コードの可読性をより高めるように設計されています.開発者がこの指針に書かれているシンプルな習慣に従えば,読みやすい統一されたスタイルを使用することにより,全ての Delphi 開発者に利益をもたらす標準を推進することになるでしょう.この標準を使用する努力は,特に保守とデバッグのサイクルにおいて,開発者のソースコードの価値を増すことになるでしょう.

これらが主として好みに基く習慣であることは言うまでもありません.私たちはこのページで推奨されているスタイルを信頼し,賞賛もしていますが,私たちがこれを支持する理由は,これが正しくこれ以外が間違っていると信じているからではなく,大多数の開発者が従う標準が存在することの効用を信じているからです.人間は標準に適合し,よく見かける - ゆえに素早くかつ容易に意味を汲み取れる - パターンをすぐに認識する方法を発見します.この努力の背景には,大多数の人が容易にコードを理解することを可能にする標準を作りたい,という思いがあります.もしも私たちのガイドラインが奇妙に思えたとしても,しばらくは努力してみてください.そうすれば,あなたが常にこのガイドラインを使用するようになると確信しています.あるいはあなたが望むなら,コードはあなた独自の形式に保っておき,Borland や公のリポジトリに送る前に,私たちのガイドラインに従わせるためのプログラムを実行してください.

例えば Visual SlickEdit のような一部のテキストエディタは,特定のスタイルに従うようにコードを整形する手助けをしてくれます.これと同じ機能を提供するその他のツールを知っている読者は,このセクションの最後にある私のアドレスに知らせてください.

Egbert van Nes の開発した無料のフォーマッターは以下の URL から入手可能です.
http://www.dow.wau.nl/aew/delforexp.html
(訳注:原文のリンクは切れていたので修正しました)

市販品の選択肢としては CrackerJax for Delphi があります.
http://www.kineticsoftware.com/products.html
(訳注:原文のリンクは切れていたので修正しました)

導入を終わる前に繰り返します.Borland のウェブサイト上と私たちの製品と共に出荷される CD において,この標準は法律です.私たちは統一された読みやすいスタイルでコードを提供したいと思っています.このガイドラインに書かれたルールを強制することは,その目標を達成する最もシンプルな手段です.

この規約を他のウェブサイトに載せないで下さい.代わりにこの文書にリンクしてください.

訂正や提案を受け付けています.Charlie Calvert まで連絡ください.
(訳注:少なくとも 2004年4月時点でメールアドレスは宛先不明となっており,連絡を取れませんでした.そのためリンクは削除しました)


目次

(訳注:原文は章立てが混乱しています(特に8章辺り).この翻訳では適宜調整しています)

1 導入

この文書は Object Pascal の文法を定義しようとするものではありません.例えば else の前にセミコロンを置くのは文法違反ですが,その場合は単にコンパイラがそうさせないように仕向けるだけです.したがって,このスタイルガイドにはそのようなルールは書かれていません.この文書は Object Pascal があなたに選択権を与えている部分において取るべき適切な方針を定義することを目的としています.

1.1 背景

ここで提供されるガイドラインは Delphi ソースの公の部分を基にしています.Delphi ソースはこのガイドラインに正確に従うべきです.あなたがこのガイドラインに従っていないソースを見つけた場合でも,その正道から外れたソースではなく,このガイドラインをあなたの標準とみなすべきです.しかしながら,少なくとも自分のコードがどのように見えるべきかという一般的な感覚を得るのに役立つ限り,あなたはそのソースをこのガイドラインの補足として使用するべきです.

1.2 謝辞

この文書のフォーマットと一部の用語は,Java 言語のスタイル標準を定義するために行われた成果に基いています.Java は Object Pascal ソースの書式のルールには影響を与えていませんが,Sun のウェブサイトにある文書はこの文書の基礎となっています.特にこの文書のスタイルとフォーマットは,Achut Reddy による "A Coding Style Guide for Java WorkShop and Java Studio Programming" の影響を強く受けています.その文書は次のURLで見ることができます.
URL:http://wwws.sun.com/software/sundev/whitepapers/java-style.pdf (PDF)
(訳注:原文のリンクは切れていたので修正しました)

Delphi チームもこの文書の作成に大きく貢献しました.実際のところ,彼らの助けが無ければこの文書を作ることは出来なかったでしょう.

2 ソースファイル

Object Pascal のソースはユニットと Delphi Project ファイルに分けられ,共に同じ規約に従います.Delphi Project ファイルの拡張子は DPR で,プロジェクトのメインソースになります.プロジェクトで使用される全てのユニットは拡張子 PAS を持ちます.プロジェクト内ではその他に,バッチファイルや html ファイル,DLL 等の追加ファイルが役割を持ちますが,この文書では DPR ファイルと PAS ファイルの書式だけを扱います.

2.1 ソースファイルの命名

Object Pascal は長いファイル名をサポートしています.ひとつの名前を付けるのに複数の単語を使用する場合,単語毎に大文字を使用するのが最良です(例:MyFile.pas).これは InfixCaps,または Camel Caps として知られています.拡張子は小文字であるべきです.歴史的な理由により,Delphi 自身に含まれているソースでも 8.3 形式に制限されているものがありますが,もはや例えそれが Delphi チームによって使用されるであろうソースであっても,開発者はこの制限に縛られる必要はありません.

C/C++ のヘッダファイルを翻訳する場合,拡張子が PAS であることを除き,対応する Pascal のヘッダファイルは翻訳元のファイルと同じ名前を持つでしょう.例えば,Windows.hはWindows.pasになります.Pascalの文法の制限のために複数のヘッダファイルを一つのユニットに結合しなければならない場合,ファイルをまとめる元になるユニットの名前を使用します.例えば,WinBase.h を Windows.h に含める場合,Windows.pas と命名します.

2.2 ソースファイルの構成

全ての Object Pascal のユニットは以下の要素をこの順序で含むべきです.

  1. Copyright/ID ブロックコメント
  2. ユニット名
  3. インターフェース部
  4. 実装部
  5. 終わりの end とピリオド

各要素は少なくとも一行以上の空行で区切るべきです.

あなたが適切だと思う場所に追加の要素を組み入れることが出来ます.ただし,ファイルの先頭は常にコピーライトで始まり,次にユニット名,そして条件コンパイル定義やコンパイラ指令やインクルード文,その次に uses 節という順序を変えてはいけません.

{*******************************************************}
{                                                       }
{       Borland Delphi Visual Component Library         }
{                                                       }
{       Copyright (c) 1995,98 Inprise Corporation       }
{                                                       }
{*******************************************************}

unit Buttons;

{$S-,W-,R-}
{$C PRELOAD}

interface

uses 
  Windows, Messages, Classes, 
  Controls, Forms, Graphics, 
  StdCtrls, ExtCtrls, CommCtrl;

type 節をconst 節の前に置いたり,type 節と const 節を好きな順序で混ぜて使ったとしても問題ありません.

実装部の順序は,最初に implementation,次にuses節,次にインクルード文やその他のコンパイラ指令となるべきです.

implementation

uses 
  Consts, SysUtils, ActnList, 
  ImgList;

{$R BUTTONS.RES}

2.2.1 Copyright/ID ブロックコメント

全てのソースファイルはバージョン情報と標準的なコピーライト通知を含むブロックコメントで始まるべきです.バージョン情報は以下のフォーマットであるべきです.

{*******************************************************}
{                                                       }
{       Widgets Galore                                  }
{                                                       }
{       Copyright (c) 1995,98 Your Company              }
{                                                       }
{*******************************************************}

コピーライト通知は少なくとも以下の行を含むべきです.

Copyright (c) yearlist CopyrightHolder.

もしあなたが,Borland によって使用されるファイルを作成しているサードパーティなら,コピーライト通知の最後にあなたの名前を追加しても構いません.

{*******************************************************}
{                                                       }
{       Borland Delphi Visual Component Library         }
{       Copyright (c) 1995,99 Borland International     }
{       Created by Project JEDI                         }
{                                                       }
{*******************************************************}

2.2.2 ユニット宣言

全てのソースファイルはユニット宣言を持たなければなりません.単語 unit は予約語であり,従って小文字であるべきです.ユニット名には大文字と小文字を混在させるべきであり,OS のファイルシステムが使用する名前と同じでなければなりません.

unit MyUnit;

このユニットがファイルシステム上に置かれる場合,MyUnit.pas と命名されます.

2.2.3 uses 宣言

ユニット内の uses 宣言は,小文字の uses で始まるべきです.各ユニット内で宣言されているキャピタライズ規則にしたがってユニット名を追加します.

uses MyUnit;

各ユニットはカンマで区切られなければならず,最後のユニットの後ろにセミコロンが置かれるべきです.

uses 
  Windows, SysUtils, Classes, Graphics, Controls, Forms, 
  TypInfo;

上の例のように uses 節をその次の行から始めるのるのも,次のようにユニットのリストを同じ行から始めるのも正しい書き方です.

uses Windows, SysUtils, Classes, Graphics, Controls, Forms, 
  TypInfo;

uses 節のユニットリストを 80 文字以内になるように折り返したり,行毎にひとつずつユニットを書いても構いません.

2.2.4 class/interface 宣言

class 宣言は空白2文字から始まり,その後に大文字 T から始まる識別子が続きます.識別子は大文字で始め,埋め込まれている単語毎に大文字を使用するべきです(InfixCaps).Object Pascal ソースではタブ文字を使用してはいけません.
例:

  TMyClass

識別子の後ろには空白1文字,イコール記号,小文字で class と続きます.

  TMyClass = class 

上位クラスを指定したい場合は,括弧,上位クラス名,閉じ括弧を追加します.

  TMyClass = class(TObject)

スコープ指定子は左端から空白2文字を空け,次の例で示す順序で宣言されるべきです.

  TMyClass = class(TObject)
  private
  protected
  public
  published
  end;

データは常に private 節のみに置かれ,その識別子はFで始まるべきです.全ての型宣言は左端から空白4文字を空けて書かれるべきです.

  TMyClass = class(TObject)
  private
    FMyData: Integer;
    function GetData: Integer;
    procedure SetData(Value: Integer);
  public
  published
    property MyData: Integer read GetData write SetData;
  end;

インターフェースは class 宣言と同じルールに従います.ただし,すべてのスコープ指定子と private のデータは削除しなければならず,class ではなく interface と記述しなければいけません.

3 命名規則

小文字だけで書かれる予約語や指令を除き,Pascal の全ての識別子には InfixCaps を使用します.つまり,最初の文字が大文字で,識別子の中に埋め込まれている各単語も大文字で始まり,頭文字からなる単語も大文字を使用します.
例:

MyIdentifier
MyFTPClass

この規則に対する主な例外は,ヘッダファイルを翻訳する場合です.その場合には,常にそのヘッダファイルで使用されている規則に従うべきです.例えば,WM_LBUTTONDOWN を wm_LButtonDown とは書きません.

ヘッダファイルを翻訳する場合を除き,単語の区切りにアンダースコアを使用してはいけません.クラス名は名詞,または名詞句であるべきです.インターフェース名やクラス名は,その主要な目的を表すようにします.

良い型名:
  AddressForm, ArrayIndexOutOfBoundsException

悪い型名:
  ManageLayout         // 動詞句
  delphi_is_new_to_me  // アンダースコア

3.1 ユニットの命名

このセクションの最初で説明した InfixCaps を使用します.unit 宣言 のセクションも参照してください.

3.2 クラス/インターフェースの命名

このセクションの最初で説明した InfixCaps を使用します.各型宣言は大文字 T で始めます.

TMyType 

class/interface 宣言のセクションも参照してください.

3.3 フィールドの命名

このセクションの最初で説明した InfixCaps を使用します.各型宣言は大文字 F で始めます.全てのデータを private 節に置き,公開する場合にはプロパティやゲッター/セッターを使います.例えば,フィールド値を返す関数には GetSomething という名前を使用し,値をセットする手続きには SetSomething という名前を使用します.

ヘッダファイルの翻訳のために必要な場合を除き,全て大文字の定数を宣言してはいけません.

Delphi はカリフォルニアで作られています.そのため私たちは,ヘッダファイルの翻訳のために必要な場合を除き,表記法を使用しません.

正しい
  FMyString: string;

誤り
  lpstrMyString: string;

例外的に,列挙型にはハンガリアン記法を使用します.

  TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, 
    bkYes, bkNo, bkClose, bkAbort, bkRetry, 
    bkIgnore, bkAll);

この場合,列挙型の各要素の前に文字 bk を置いています.bk は ButtonKind を表しています.

名前付け規則について考える場合,一時変数やループカウンタを除き,1 文字のフィールド名は避けるべきです.

変数 l (小文字のエル)は,一部のプリンタやディスプレイ上では 1 (数字の一)と区別し難いため,避けるべきです.

3.4 メソッドの命名

メソッド名には InfixCaps スタイルを使用するべきです.大文字で始め,名前の中の各単語の最初の文字に大文字を使用し,頭文字からなる単語も大文字を使用します.これら以外の文字は全て小文字にします.単語の区切りにアンダースコアを使用してはいけません.この規則は非定数フィールドの命名規則と同じですが,このふたつは文脈によって簡単に区別できる点に注意してください.メソッド名は命令系動詞か動詞句であるべきです.

// 良いメソッド名:
ShowStatus, DrawCircle, AddLayoutComponent

// 悪いメソッド名:
MouseButton  // 名詞句であり,機能を表していない
drawCircle   // 小文字から始まっている
add_layout_component  // アンダースコア

// このメソッドの機能は分かり難い.
// これはサーバー機能を開始するのか?
// (それなら StartServer の方が良い)
// それともサーバーが開始されているかどうかをテストするのか?
// (それなら IsServerRunning の方が良い)
ServerRunning  // 動詞句だが,命令形ではない

クラスのプロパティを取得・設定するメソッドは,それぞれ GetProperty と SetProperty と命名するべきです.ここで Property はそのプロパティの名前です.

例:

GetHeight, SetHeight

クラスの boolean 型プロパティをテストするメソッドは,例えばそのプロパティ名が Visible であれば,IsVisible と命名するべきです.

例:

IsResizable, IsVisible

3.5 ローカル変数の命名

ローカル変数はフィールド名と同じ命名規則に従います.ただし,これはオブジェクトのフィールドではないので,最初の F は省きます.(セクション 3.3 参照)

3.6 予約語

予約語や指令は全て小文字で書くべきです.これは時にちょっとした混乱を招きます.例えば Integer のような型は単なる識別子なので大文字で始めますが,文字列は予約語 string として宣言されているので,全て小文字で書きます.
(訳注:少なくとも Delphi 5 のコード補完機能では "String" と補完されます.単なる Delphi 側のミスか,あるいは,string も Integer と同じように扱ってもほとんど問題ないためにわざとそうしているのか,真相は分かりません)

3.7 型宣言

全ての型宣言は文字 T で始まり,このセクションの始めクラス宣言のセクションで述べたものと同じキャピタライズの規約に従うべきです.

4 空白の使用

4.1 空行

論理的に関連を持つコードを空行を用いてグループ化することにより,可読性を向上させることが出来ます.空行は以下のような場所でも使用するべきです.

  1. コピーライトのブロックコメントの後,パッケージ宣言の後,インポート部の後
  2. 各クラス宣言の間
  3. 各メソッド宣言の間

4.2 空白文字

Object Pascalは非常にきれいで読みやすい言語です.一般に,行を分割するためにコード内に多くの空白を追加する必要はありません.以下のセクションでコードに空白を置く際に従うべきいくつかのガイドラインを示します.

4.2.2 空白を使うべきではない場所

  1. メソッド名とその次の括弧の間
  2. .(ドット)演算子の前後
  3. 単項演算子とそのオペランドの間
  4. キャストとキャスト対象の間
  5. 開き括弧の後や,閉じ括弧の前
  6. 開きブラケット [ の後や,閉じブラケット ] の前
  7. セミコロンの前

正しい使用例:

function TMyClass.MyFunc(var Value: Integer);
MyPointer := @MyRecord;
MyClass := TMyClass(MyPointer);
MyInteger := MyIntegerArray[5];

間違った使用例:

function TMyClass.MyFunc( var Value: Integer ) ;
MyPointer := @ MyRecord;
MyClass := TMyClass ( MyPointer ) ;
MyInteger := MyIntegerArray [ 5 ] ;

4.3 インデント

全てのインデントレベルにおいて,空白2文字を使用するべきです.言い換えると,最初のレベルのインデントは空白2文字,二番目のレベルには空白4文字,三番目には空白6文字と言うことです.タブ文字を使用してはいけません.

いくつかの例外があります.予約語 unit,uses,type,interface,implementation,initialization,finalization は,常に左端から始めるべきです.ユニットの最後の end も左端から始めるべきです.プロジェクトファイル内では,program とメインの begin と end は常に左端から始めるべきです.begin..end ブロックの内側のコードは少なくとも空白2文字でインデントされるべきです.

4.4 行の折り返し

各行は 80 桁に制限するべきです.80 桁を越える行は必要に応じて 2 行以上に折り返します.折り返した行は先頭の行に対して 2 文字分のインデントを付けて並べます.begin 文はそれだけで一行にします.

例:

// 正しい

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;

// 正しい

if ((X = Y) or (Y = X) or
  (Z = P) or (F = J) then
begin
  S := J;
end;

パラメータとその型の間では,それがカンマ区切りのリストである場合を除き,折り返してはいけません.カンマ区切りのリストの場合は,次の行に型名が続くように,少なくとも最後のパラメータの直前で折り返します.変数名とコロンの間には空白を入れません.コロンと型名の間にはひとつだけ空白を入れます.

// 正しい

procedure Foo(Param1: Integer; Param2: Integer);

// 誤り

procedure Foo( Param :Integer; Param2:Integer );

論理演算子の前で行を折り返すべきではありません.普通は空白を置かない場所,例えばメソッド名とその後ろの括弧の間や,配列名とその後ろのブラケットの間のような場所では,行を折り返すことは避けなくてはいけません.もしどうしてもこのような状況で折り返さなければならない場合,改行できる場所としてはメソッド名の直後の開き括弧の後があります.begin 文をその他のコードと同じ行に書いてはいけません.

例:

// 正しい
while (LongExpression1 or LongExpression2) do begin
  // DoSomething
  // DoSomethingElse;
end;

// 正しい
while (LongExpression1 or LongExpression2) do 
begin
  // DoSomething
  // DoSomethingElse;
end;

// 正しい
if (LongExpression1) or 
  (LongExpression2) or 
  (LongExpression3) then

5 コメント

Object Pascal 言語は,ブロックコメントと単一行コメントの二種類のコメントをサポートしています.コメントの使用に関するいくつかの一般的ガイドラインを以下に示します.

i := i + 1;  // iに1を加える

例:

// ???: Sort が修正されたら,Sort の呼び出しに変更する
List.MySort;

5.1 ブロックコメント

Object Pascal は二種類のブロックコメントをサポートしています.最も一般的に使用されるブロックコメントは,ブレースのペア { } です.Delphi チームはこのタイプのコメントを出来るだけ簡潔に保つのを好みます.例えば,コメント中に線や模様を作るためにアスタリスクを使うのは避けるべきです.その代わり,ワープロ文書と同じように空行を使用してコメントを分割します.以下の DsgnIntf.pas からの抜粋のように,コメント内の言葉は最初のブレースと同じ行から始めるべきです.

{ TPropertyEditor

  Edits a property of a component, or list of components, 
  selected into the Object Inspector.  The property 
  editor is created based on the type of the
  property being edited as determined by the types 
  registered by...
  
  etc...
  
    GetXxxValue
      Gets the value of the first property in the 
      Properties property.  Calls the appropriate 
      TProperty GetXxxValue method to retrieve the 
      value. 
      
    SetXxxValue Sets the value of all the properties 
      in the Properties property.  Calls the appropriate 
      TProperty SetXxxxValue methods to set the value. }

ソースファイルの最初の Copyright/ID コメントには,常にブロックコメントが使用されます.また,複数行のコードをコメントアウトする場合にも使われます.

メソッドを説明するブロックコメントは,メソッド定義の前に置くべきです.

例:

// 正しい

{ TMyObject.MyMethod
   
  This routine allows you to execute code. }

procedure TMyObject.MyMethod;
begin
end;

// 誤り

procedure TMyObject.MyMethod;
{******************************************************
  TMyObject.MyMethod
   
  This routine allows you to execute code. 
*******************************************************}
begin
end;

もうひとつのブロックコメントは,二つの文字,括弧とアスタリスクを含みます (* *).時としてこれらは星括弧コメント(starparen comments)と呼ばれます.一般的に,このコメントは開発時にのみ役に立ちます.なぜならこのコメントの主な利点が,2 段階までのコメントのネストを可能にすることだからです.Object Pascal は同じ種類のコメントのネストをサポートしていません.つまり,実際にはコメントのネストは1段階しか存在せず,星括弧の中のブレース,ブレースの中の星括弧,ということです.それぞれがネストしていない限り,このタイプのコメントの間にあるその他の標準的な Pascal のコメントは無視されます.したがってこの文法を使えば,コードやコメントの混ざった大きなコードの固まりをまとめてコメントアウトすることが出来ます.

(* procedure TForm1.Button1Click(Sender: TObject);
begin
  DoThis; // Start the process
  DoThat; // Continue iteration
  { We need a way to report errors here, perhaps using
    a try finally block ??? }
  CallMoreCode; // Finalize the process
end; *)

この例では,プロシージャの begin と end の間にある他のコメントを含め,メソッド Button1Click 全体をコメントアウトしています.

5.2 単一行コメント

単一行コメントは,文字列 // と,それに続くテキストで構成されます.// とコメントの間には空白を 1 文字入れるべきです.単一行コメントは,その後に続くコードと同じインデントレベルに置くべきです.単一行コメントを複数用いて,より大きなコメントを作っても構いません.

単一行コメントやコメントグループの前には,それがブロックの最初の行ではない限り,空行を 1 行置くべきです.複数の文に対して単一行コメントを置く場合,そのコメントやコメントグループの後にも空行を1行置くべきです.コメントが次の文(複合文でも良い)だけに適用される場合,その後に空行を置いてはいけません.

例:

// データベースを開く
Table1.Open;

単一行コメントは,コメント対象のコードの後ろに続けることも出来ます.時にトレイリングコメント(trailing comments)と呼ばれるこのコメントは,そのコメントが説明するコードと同じ行に置かれます.このコメントとそれが説明するコードとの間には少なくとも1文字の空白を置くべきです.ひとつのコードブロックに二つ以上のトレイリングコメントを書く場合,それらは全て同じ桁に揃えるべきです.

例:

if (not IsVisible) then
  Exit;          // nothing to do
Inc(StrLength);  // reserve space for null terminator

全てのコードにトレイリングコメントを付けることは避けなければいけません.通常,メソッドや関数の begin..end 内に書くコメントを最小限に制限することは最適です.より長いコメントは,メソッド宣言や関数宣言の前のブロックコメント内に置くことが出来ます.

6 クラス

6.1 クラス本体の構成

クラス本体の宣言は以下の順序で構成されるべきです.

クラス内のフィールド,プロパティ,メソッドは,名前のアルファベット順に並べるべきです.

6.2 アクセルレベル

IDE によって挿入されるコードを除き,クラスのスコープ指定子は以下の順序で宣言されるべきです.

Object Pascal にはクラスのメンバーのアクセスレベルとして,アクセスレベルの高い順に,published,public,protected,private の4種類があります.デフォルトのアクセスレベルは published です.一般に,メンバーにはそのメンバーにとって適切な最低限のアクセスレベルを与えるべきです.例えば,同じユニット内のクラスからだけアクセスされるメンバーには private アクセス権を設定するべきです.より低いアクセスレベルで宣言することは,しばしばより多くの最適化の機会をコンパイラに与えます.その一方で,private の使用はサブクラス化によるクラスの拡張を難しくします.もし将来そのクラスがサブクラス化されるかもしれないと考えるなら,サブクラスで必要とされるかもしれないメンバーを private の代わりに protected で宣言し,private なデータへのアクセスに使われるプロパティには protected の地位を与えるべきです.

データへの public なアクセスは決して許可するべきでありません.データは常に private 節で宣言し,public なアクセスはゲッター・セッターメソッド,またはプロパティを経由するべきです.

6.3 コンストラクタ宣言

メソッドはアルファベット順に並べるべきですが,コンストラクタとデストラクタを public 節のリストの先頭に置くのも,それらを public 節のアルファベット順の位置に置くのも,どちらも正しい書き方です.

二つ以上のコンストラクタが存在し,それらが全て同じ名前の場合,より多くのパラメータを持つコンストラクタがより少ないパラメータを持つコンストラクタの後に来るようにしながら,パラメータリストの辞書順に並べます.これは(もしあれば)引数無しのコンストラクタが常に先頭に来ることを意味します.C++Builder との互換性のためには,コンストラクタのパラメータリストがユニークになるようにします.C++ はコンストラクタを名前で呼ぶことが出来ず,したがって複数のコンストラクタを区別する唯一の方法がパラメータリストになります.

6.4 メソッド宣言

可能ならば,メソッド宣言は一行にするべきです.

例:

// 改行する時は左から空白2文字を空けて並べます.
procedure ImageUpdate(img: Image, infoflags: Integer,
  x: Integer, y: Integer, w: Integer, h: Integer);

7 インターフェース

インターフェースはクラスの宣言と同じような形で定義します.

InterfaceName = interface([Inherited Interface])
  InterfaceBody
end;

インターフェース宣言は空白 2 文字でインデントします.インターフェース本体は 4 文字でインデントします.終りの end 文も空白 2 文字でインデントします.終わりの end 文の直後にセミコロンを置くべきです.

インターフェース宣言にはフィールドはありません.ただし,プロパティは許されます.

インターフェースの全てのメソッドは,何もしなくても public かつ abstract です.インターフェースメソッドの宣言の中にこれらのキーワードを明示的に含めてはいけません.

上に書いたことを除き,インターフェース宣言はクラスの場合と同じガイドラインに従います.

7.1 インターフェース本体の構成

インターフェース宣言の本体は以下の順序で構成されるべきです.

  1. インターフェースメソッド宣言
  2. インターフェースプロパティ宣言

インターフェースのメソッドとプロパティの宣言スタイルは,クラスのメソッドとプロパティのスタイルと同じです.

8 文

文は 1 行以上のコードと,それに続くセミコロンから成ります.単一文はセミコロンをひとつだけ含みます.一方,複合文は二つ以上のセミコロンを含み,複数の単一文を含みます.

これは単一文です.

A := B; 

これは複合(あるいは構造化)文です.

begin
  B := C;
  A := B;
end;

8.1 単一文

単一文はひとつのセミコロンを含みます.文を折り返さなければならない場合,二行目は直前の行に対して空白 2 文字分インデントします.

  MyValue := 
    MyValue + (SomeVeryLongStatement / OtherLongStatement);

8.1.1 代入文と式

各行はただひとつの文を含むべきです.例えば,

a := b + c; Inc(Count);  // 誤り
a := b + c;              // 正しい
Inc(Count);              // 正しい

8.1.2 ローカル変数宣言

ローカル変数は Camel Caps (大文字で始まり,埋め込まれている各単語の先頭が大文字)に従うべきです.変数名の前に F を付け加えてはいけません.それはクラス宣言のフィールド用に予約されている習慣だからです.

var
  MyData: Integer;
  MyString: string;

同じ型の複数の識別子を一行で宣言しても構いません.

var
  ArraySize, ArrayCount: Integer;

ただし,クラス宣言ではこの規則を使わないで下さい.クラス宣言の場合は各フィールドをその型と共に別々の行に書くべきです.

8.1.3 配列宣言

開きブラケット "[" の前と閉じブラケット "]" の後に,常に空白を 1 文字置くべきです.

type
  TMyArray = array [0..100] of Char;

8.2 複合文

複合文は常にセミコロンで終わりますが,その直後が end 文の場合に限り,セミコロンを置くかどうかは自由です.

begin
  MyStatement;
  MyNextStatement;
  MyLastStatement   // ここにはセミコロンがあっても無くても良い
end;

8.2.1 if

if文は常に最低 2 行で書くべきです.

例:

  // 誤り
  if A < B then DoSomething; 
  
  // 正しい
  if A < B then 
    DoSomething;

構造化 if 文では,文を分ける各要素をそれぞれ新しい行に書きます.

例:

  // 誤り
  if A < B then begin
    DoSomething; 
    DoSomethingElse;
  end else begin
    DoThis;
    DoThat;
  end;
  
  // 正しい
  if A < B then 
  begin
    DoSomething; 
    DoSomethingElse;
  end 
  else 
  begin
    DoThis;
    DoThat;
  end;

以下は,有効だと考えられる幾つかのバリエーションです.

  // 正しい
  if Condition then
  begin
    DoThis;
  end else
  begin
    DoThat;
  end;

  // 正しい
  if Condition then
  begin
    DoThis;
  end
  else
    DoSomething;

  // 正しい
  if Condition then
  begin
    DoThis;
  end else
    DoSomething;

以下の書き方は好まれませんが正しい例です.

  if Condition then
    DoThis
  else DoThat;

8.2.2 for

例:

  // 誤り
  for i := 0 to 10 do begin
    DoSomething; 
    DoSomethingElse;
  end;
  

  // 正しい
  for i := 0 to 10 do
  begin
    DoSomething; 
    DoSomethingElse;
  end;

8.2.3 while

例:

  // 誤り
  while x < j  do begin
    DoSomething; 
    DoSomethingElse;
  end;
  

  // 正しい
  while x < j do 
  begin
    DoSomething; 
    DoSomethingElse;
  end;

8.2.4 repeat until

例:

  // 正しい
  repeat
    x := j;
    j := UpdateValue;
  until j > 25;

8.2.5 case

例:

  // 正しい
  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;

8.2.6 try

例:

  // 正しい
  try
    try
      EnumThreadWindows(CurrentThreadID, @Disable, 0);
      Result := TaskWindowList;
    except
      EnableTaskWindows(TaskWindowList);
      raise;
    end;
  finally
    TaskWindowList := SaveWindowList;
    TaskActiveWindow := SaveActiveWindow;
  end;