原文:http://www.econos.de/delphi/cs.html
訳注: 独特なルールが目に付きます。翻訳してみたものの、お勧め出来るかどうかは……微妙です。

2004/09/13 0.1.0 初版
2006/04/18 0.2.0 全体的に見直し


サイト内関連リンク:Object Pascal スタイルガイド , The Delphi Bug List 日本語訳



Delphi 4 開発者ガイド コーディング標準

Copyright © 1998 Xavier Pacheco and Steve Teixeira

Modifications © 1998 Econos - Stefan Hoffmeister
Version 1.1.0
29 September 1998
Republished with permission

変更されていないオリジナルバージョンは以下にあります:

Delphi 4 Developer's Guide Homepage

この文書のほとんど全ての内容は、Xavier Pacheco と Steve Teixeira とによって作成されたオリジナルの文書を元にしています。この文書を作るために、ほんの少しの変更だけが加えられています。

Delphi Information Resources に戻る

導入

一般的なソースコードのフォーマット規則 Object Pascal ファイル フォームとデータモジュール パッケージ コンポーネント
 

導入

この文書は Delphi 4 Developer's Guide で使用されている Delphi プログラミングのコーディング標準について述べています。少数の例外を除き、全般的にこの文書は、Borland International によって使用されているしばしば "語られない" フォーマットガイドラインに従っています。Delphi 4 Developer's Guide にこの文書を含めている目的は、開発チームがそのコーディングに対して一貫したスタイルを強制できる方法を提供することです。その目的は、チームのプログラマ全員が他のプログラマによって書かれたコードを理解できるようにすることです。これは、一貫性を持たせることによるより可読性の高いコードを作成することで達成されます。

コーディング標準に存在するであろう全てをこの文書が含んでいる訳では決してありません。しかしながら、あなたの標準を得られる程には十分な詳細を含んでいます。あなたのニーズに合わせるために、これらの標準を自由に利用・修正してください。しかしながら、Borland の開発スタッフによって使用されているこの標準からあまりかけ離れすぎないことを推奨します。私達がこれを推奨する理由は、あなたがあなたのチームに新しいプログラマを連れて来たとき、彼らがもっとも慣れていそうな標準は Borland の標準だからです。大抵のコーディング標準の文書と同じように、この文書は必要に応じて進化して行きます。そのため、最新のバージョンはオンラインで http://www.xapware.com/ddg/ にて見つけることが出来ます。[注意: これはこの文書の オリジナルで 修正されていないバージョンに適用されます。]この文書は ユーザーインターフェイス標準 を扱いません。それは別のものですが、等しく重要なトピックです。サードパーティの書籍や Microsoft の文書がその種のガイドラインを十分にカバーしているので、私達はわざわざその情報を複製するのではなく、その情報を利用可能な Microsoft Developers Network やその他の情報源を示すことにしました。

Econos の Stefan Hoffmeister によってこの文書に適用された変更は、赤く 色付けされています。この変更はオリジナル文書の文章の変更または追加であり、レイアウトや書式の変更ではありません。

 

一般的なソースコードのフォーマット規則

インデント

インデントは 1 レベル当たり 2 個の空白文字にします。ソースファイル内にタブ文字を保存してはいけません。タブ文字は、ユーザー設定やソース管理ユーティリティ(印刷・アーカイブ・バージョンコントロール等)によって異なる幅に展開されるためです。

ツールメニューのエディタオプションの "タブ文字の使用" をオフにし、"オプティマルフィル" をオンにすることでタブ文字が保存されるのを禁止できます。

マージン

マージンは 80 文字にセットします。一般に、単語を終了させるときの例外を除いてソースはこのマージンを超えるべきではありませんが、このガイドラインは多少柔軟です。可能であれば必ず、1 行を超えるステートメントはコンマまたは演算子の後で折り返すべきです。ステートメントを折り返す場合、論理的にまとまった部分が同じインデントレベルになるようにインデントするべきです。

コメント

コメントには通常 { } のペアを使用するべきです。

もうひとつのコメント表記 (* *) は、開発時に一時的にコードを削除("コメントアウト")するときのために予約されるべきです。

// はコメントが一行の場合に限って使用するべきです。

条件定義

条件定義は中括弧 - "{", "}" - と大文字の条件コマンドとで書くべきです。

コードの可読性を高めるために、各条件定義のブロックの終わりにも条件名を記述します。

これらは通常のブロックと同じ方法でインデントするべきです。

  if ... then
  begin
    {$IFDEF VER90}
      raise Exception.CreateRes(SError);
    {$ELSE}
      raise Exception.Create(SError);
    {$ENDIF VER90}
  end;

Begin..End

begin ステートメントはそれだけで単独の行にします。例えば以下の 1 行目は誤りで、2 行目が正解です。

  for I := 0 to 10 do begin // 誤り。begin が for と同じ行にある。

  for I := 0 to 10 do       // 正しい。begin が別の行に書かれている。
  begin

この規則の例外として、begin ステートメントが else の一部として現れる場合には以下のように書くことも出来ます

  if some statement = ... then
  begin
    ...
  end
  else begin
    SomeOtherStatement;
  end;

しかしながら、より好ましい書き方は以下の通りです。

  if some statement = ... then
  begin
    ...
  end
  else
  begin
    SomeOtherStatement;
  end;

なぜなら、begin ステートメントが対応する if ステートメントと常に同じレベルに現れるためです。

end ステートメントは常にそれだけで単独の行にします。

begin ステートメントが else の一部ではない場合、対応する end ステートメントは begin と同じレベルにインデントします。

 

Object Pascal

括弧

開き括弧とその次の文字との間に空白を入れてはいけません。同じように、閉じ括弧とその前の文字との間にも空白を入れてはいけません。以下の例は、括弧に関する誤った空白の空け方と正しい空白の空け方とを示しています。

  CallProc( AParameter ); // 誤り
  CallProc(AParameter);   // 正しい

ステートメント中に余分な括弧を含めてはいけません。ソースコード中で意図する意味を成すのに必要な場所でのみ括弧を使用するべきです。以下の例は、誤った用法と正しい用法とを示しています。

  if (I = 42) then              // 誤り - 余分な括弧
  if (I = 42) or (J = 42) then  // 正しい - 最低限の括弧

予約語とキーワード

Object Pascal 言語の予約語とキーワードは、常にすべて小文字であるべきです。デフォルトでは文法をハイライトする IDE の機能がこれらの単語を太字で表示します。これらの単語に大文字を使用するべきではありません。

手続きと関数 (ルーチン)

命名 / フォーマット

可読性を高めるために、ルーチンの名前は大文字で始まるキャメル形式にするべきです。以下は誤った手続き名の例です:

  procedure thisisapoorlyformattedroutinename;

次は適切にキャピタライズされたルーチン名の例です:

  procedure ThisIsMuchMoreReadableRoutineName;

ルーチンには処理内容を表す意味のある名前を付けるべきです。何らかのアクションを起こすルーチンには、そのアクションの動詞を前に付けます。例:

  procedure FormatHardDrive;

入力パラメータの値をセットするルーチンは先頭に Set を付けるべきです。例:

  procedure SetUserName;

値を取得するルーチンは先頭に Get を付けるべきです。例:

  function GetUserName: string;

引数

フォーマット

可能であれば、同じ型の引数はひとつのステートメントにまとめるべきです。

  procedure Foo(Param1, Param2, Param3: Integer; Param4: string);
命名

すべての引数の名前はその目的を表す意味のある名前にし、典型的にはそのルーチンに渡される識別子の名前に基づきます。適切であれば、引数の前に文字 A を置きます。例:

  procedure SomeProc(AUserName: string; AUserAge: integer);

このプレフィクス "A" は、その引数がクラス内のプロパティやフィールドの名前と同じ名前の場合のあいまいさを無くすための習慣です。

引数の順序

以下に示す引数の順序付けは、レジスタ呼び出しの活用に重視を置いています。

(呼び出し側によって)もっとも良く使用される引数を最初に置き、より使われない引数をその後に左から右の順に並べるべきです。

入力引数を出力引数の前に左から右の順に置くべきです。

もっとも一般的な引数から特殊な引数へと左から右の順に置くべきです。例:
SomeProc(APlanet, AContinent, ACountry, AState, ACity)

この規則の例外はイベントハンドラです。イベントハンドラの場合、TObject 型の Sender という名前の引数がしばしば最初の引数として渡されます。

定数引数

レコード・配列・ShortString・インターフェイスの引数がルーチン内で変更されない場合、その引数に const を付けるべきです。これにより、それらの変更されないパラメータをもっとも効率の良い方法で受け渡すコードをコンパイラが生成することが確実になります。

その他の型の引数でも、それがルーチン内で変更されない場合には任意で const パラメータとして定義して構いません。これは効率には影響ありませんが、そのルーチンを呼ぶ人にパラメータの用途に関するより多くの情報を提供します。

名前の衝突

使用している二つのユニットが同じ名前のルーチンを含むときにそのルーチンを呼び出すと、uses 節に最後に現れるユニットに属するルーチンが呼ばれます。uses 節に依存したこのあいまいさを避けるため、常に意図するユニット名を付けてそのメソッドを呼びます。例えば、

  SysUtils.FindClose(SR);

または

  Windows.FindClose(Handle);

変数

変数の命名とフォーマット

変数にはその目的を表す意味のある名前を付けます。

一般にループ制御変数には IJK のような 1 文字の名前が付けられますが、これは例えば UserIndex のような、より意味のある名前のほうが好ましいでしょう。

Boolean 型の変数の名前は、その TrueFalse の意味を明らかにするのに十分なほど説明的であるべきです。

変数宣言

変数を宣言するとき、ひとつの型に対して複数の宣言を置くべきではありません。各変数には常にそれぞれの型を指定します。例:

  var
    i: Integer;
    j: Integer;

各変数宣言の前にキーワード var を置いても構いません。例:

  var i: Integer;
  var j: Integer;

ローカル変数

手続き内で使用されるローカル変数は、他のすべての変数のための使用法と命名規則とに従います。一時変数も適切に命名します。

ローカル変数の初期化が必要な場合、ルーチンの入り口の直下で行います。ローカルの AnsiString 型変数は自動的に空文字列に初期化され、ローカルの interface 型と dispinterface 型の変数は自動的に nil に初期化され、ローカルの Variant 型および OleVariant 型の変数は自動的に Unassigned に初期化されます。

グローバル変数の使用

グローバル変数の使用は勧められませんが、必要であれば使用しても構いません。ただし使用する場合でも、それが使用されるコンテキスト内でのみグローバルであるように維持することが推奨されます。例えば単一のユニットの実装部のスコープでのみグローバルであることなどが許されます。

複数のユニットから使用されるグローバルデータは、すべてのユニットから使用される共通のユニットに移動するべきです。

グローバルデータは var セクション内で直接初期化することが許されています。グローバルデータは自動的にゼロで初期化されることを忘れないでください。したがってグローバル変数を 0や nil、''Unassigned といった "空の" 値で初期化しないでください。その理由のひとつは、ゼロで初期化されるグローバル変数は exe ファイル内に領域を取らないためです。ゼロで初期化されるデータはアプリケーションのスタートアップ時にメモリ内にのみ割り当てられる'仮想'データセグメント内に保存されます。ゼロ以外で初期化されるグローバルデータは exe ファイル内に領域を占めます。

グローバル変数がゼロで初期化されるという前提を明示するコメントを追加するべきです。例:

  var
    i: Integer { = 0 };

キャピタライズ

予約語の型名はすべて小文字で書くべきです。Win32 API の型名は一般にすべて大文字ですので、Windows.pas やその他の API ユニット内で示されるそれぞれの型の慣例にしたがうべきです。その他の変数名は最初の文字を大文字にし、残りはキャメル形式にするべきです。例:

  var
    MyString: string;  // reserved word
    WindowHandle: HWND; // Win32 API type
    I: Integer;         // type identifier introduced in System unit

浮動小数点型

Real 型は古い Pascal コードとの後方互換性のためにのみ存在しているため、使用は勧められません。一般的な浮動小数点の目的には Double を使用してください。Double はプロセッサ命令とバスとの最適化を促す型であり、IEEE が定義する標準フォーマットでもあります。ExtendedDouble よりも広い範囲が必要な場合にのみ使用してください。Extended は Intel 特有の型であり、Java ではサポートされません。Single は浮動小数点変数の物理的なバイト数が重要な場合(例えば他の言語の DLL を使用するような場合)にのみ使用してください。

列挙型

列挙型の名前はその列挙の目的を良く表す名前でなければいけません。それが型宣言だと分かるように、型名の 1 文字目は T にします。列挙型の各識別子は、元の列挙型の名前に関連する 2 文字または 3 文字の小文字を前に付けるようにします。例:

  TSongType = (stRock, stClassical, stCountry);

列挙型の変数のインスタンス名は、FavoriteSongType1FavoriteSongType2 のような具体的な名前を付ける理由がない限り、型名から 1 文字目の T を除いた名前(SongType)にします。

Variant と OleVariant

Variant 型および OleVariant 型の使用は一般に勧められませんが、COM や データベースなどの開発時にありがちな、実行時にしかデータ型を知ることが出来ない場合にはどうしても必要になります。オートメーションや ActiveX コントロールのような COM ベースのプログラミングには OleVariant を使用し、非 COM プログラミングには Variant を使用します。その理由は、Variant は Delphi ネイティブの文字列を(string 型と同等に)効率よく格納しますが、OleVariant はあらゆる文字列を Ole 文字列(WideChar 文字列)に変換し、参照カウンタも使用されず、常にコピーされてしまうためです。

構造化された型

配列型

配列型の型名はその配列の目的を良く表す名前でなければいけません。型名の 1 文字目は T にしなければいけません。配列型へのポインタを宣言する場合、1 文字目を P にし、配列型の宣言の直前で宣言しなければいけません。

  type
    PCycleArray = ^TCycleArray;
    TCycleArray = array[1..100] of Integer;

配列型のインスタンスには、型名から 1 文字目の T を除いた名前を付けます。

レコード型

レコード型にはその目的を良く表す名前を付けるべきです。型名の 1 文字目は T にしなければいけません。レコード型へのポインタを宣言する場合、1 文字目を P にし、レコード型の宣言の直前で宣言しなければいけません。各要素の型宣言は、ひとつ右のレベルにインデントしても構いません。例:

  type
    PEmployee = ^TEmployee;
    TEmployee = record
      Name: string;
      Rate: Double;
    end;

if 文

if/then/else 文の中でもっとも起こりやすいケースを then 節に置き、より稀なケースを else 節に置くべきです。

if 文を連続して書くことは避け、可能なら代わりに case 文を使用するようにします。

if 文を 5 段階より深くネストしてはいけません。より明瞭なアプローチを考えてください。

if 文に余分な括弧を使用してはいけません。

ひとつの if 文で複数の条件をテストする場合、計算量の少ない条件から順に左から右へと並べるべきです。これによりコンパイラに組み込まれた短絡評価の恩恵を受けることができます。例えば、Condition1Condition2 より計算量が少なく、Condition2Condition3 より計算量が少ない場合、以下のようにif 文を記述するべきです。

  if Condition1 and Condition2 and Condition3 then

複数の条件をテストするとき、各条件を別々の行に書くほうが望ましい場合があります。これは特に、ひとつまたは複数の条件が長い場合にあてはまります。このスタイルを選ぶ場合、各条件が互いに揃うようにインデントします。

  if Condition1 and
     Condition2 and
     Condition3 then

通常、左から右へと読むよりも、上から下へと読むほうが簡単です。特に長く複雑な構造の場合はなおさらです。

if 文の一部が一行を超える場合、これらの行をまとめるために begin/end を使用するべきです。この規則は、1 行のコメントだけが現れる場合や、ひとつの文が折り返されて複数行にまたがる場合にも適用されます。

else 節は対応する if 節に常に揃えるべきです。

case 文

一般的なトピック

case 文中の個々の case は、数値順またはアルファベット順に並べるべきです。ユーザー定義型を使用している場合、各文をその型の定義順に従って並べます。

ある種の状況では、case 文を重要度やヒットする頻度の順に並べるほうが望ましいかもしれません。

各 case の実行文はシンプルになるようにし、一般に 4・5 行を超えるべきではありません。実行文がもっと複雑な場合、そのコードは別の手続きや関数に置くべきです。この目的にはローカル手続きやローカル関数がとても適しています。

case 文での else 節の使用はデフォルトの場合に限られるべきです。else 節では例えば例外を生成するなどして、エラー検出と前提の明文化とのために使用するべきです。

case 文の各部はインデントされなければいけません。すべての条件文を begin..end ブロック内に書くべきです。else 節は case 文に揃えます。例:

  case Condition of

    condition:
      begin
        ...
      end;

  else { case }
    ...
  end;

case 文の else 節には、それが case 文に属することを示すコメントを付けるべきです。

フォーマット

インデントと名前付けとの規則に関して、case 文はその他の構造と同じ規則に従います。

while 文

while ループを抜けるために Exit 手続きを使用することは勧められません。可能であれば、ループ条件だけを使用してループから抜けるべきです。

while ループのための初期化コードはその while ループの入り口の直前に書くべきです。その他の関係のない文によって切り離されるべきではありません。

すべての後処理はループの直後に行うべきです。

for 文

決められた回数だけコードを実行しなければならない場合、while 文の代わりにfor 文を使用するべきです。

ステップ処理(2 以上の加算・減算)が必要な場合、分かっている方のループ端から始まり終了条件まで繰り返す while 文を使用します。例:

  i := AList.Count-1;
  while i => 0 do
    i := i - 2;

repeat 文

repeat 文は while と似ており、同様の一般的ガイドラインに従うべきです。

with 文

一般的なトピック

with 文は十分に注意して慎重に使用するべきです。with 文の多用は避け、with 文の中で複数のオブジェクトやレコードを使用する場合は注意してください。例:

  with Record1, Record2 do

このようなコードはプログラマを混乱させるうえ、見つけ難いバグの原因となります。

フォーマット

インデントと名前付けとの規則に関して、with 文はこの文書で説明されている規則に従います。

構造化例外処理

一般的なトピック

例外処理はエラー訂正とリソース保護とのために頻繁に使用されるべきです。これはつまり、リソースを割り当てるのであれば、そのリソースを確実に開放するために try..finally を使用するべきだということです。この規則の例外は、リソースの割り当て/開放をユニットの initialization / finalization で行う場合と、オブジェクトの constructor / destructor で行う場合です。

try..finally の使用

可能であればリソースの割り当て毎に try..finally 構造を使用します。例えば以下のようなコードはバグの原因になる可能性があります。

  SomeClass1 := TSomeClass.Create
  SomeClass2 := TSomeClass.Create;
  try
    { do some code }
  finally
    SomeClass1.Free;
    SomeClass2.Free;
  end;

より安全な方法は次の通りです:

  SomeClass1 := TSomeClass.Create
  try
    SomeClass2 := TSomeClass.Create;
    try
      { do some code }
    finally
      SomeClass2.Free;
    end;
  finally
    SomeClass1.Free;
  end;

try..except の使用

例外発生時に何らかの処理を実行したい場合にのみ try..except を使用してください。一般に、エラーメッセージを画面に表示するためだけに try..except を使用するべきではありません。なぜならそれは Application によって自動的に行われるためです。 except 節で何らかの処理を実行した後にデフォルトの例外処理を呼び出したい場合、次の例外ハンドラへの例外を再生成するために raise を使用してください。

try..except..else の使用

try..except での else 節の使用は、処理してはならない例外も含めてすべての例外をブロックしてしまうため、勧められません。

クラス

命名 / フォーマット

クラスの型名はそのクラスの目的を良く表す名前にします。型名はそれが型宣言と分かるように文字 T を前に置かなければいけません。例:

  type
    TCustomer = class(TObject)

一般に、クラスのインスタンス名はクラス名から前置の T を除いた名前と一致します。例:

  var
    Customer: TCustomer;

フィールド

命名 / フォーマット

クラスのフィールド名は、それがフィールドだということを表す注釈として F を前に置くことを除き、変数の命名と同じ規則に従います。

可視性

すべてのフィールドは private であるべきです。クラスの外からアクセスされる可能性があるフィールドにはプロパティを通してアクセスできるようにします。

宣言

各フィールドはそれぞれの型と共に別々の行に宣言するべきです。例:

  TNewClass = class(TObject)
  private
    FField1: Integer;
    FField2: Integer;
  end;

メソッド

命名 / フォーマット

メソッド名は、この文書に書かれている手続き・関数のための命名と同じ規則に従います。

静的メソッドの使用

子クラスでオーバーライドされたくない場合に静的メソッドを使用します。

仮想メソッド / 動的メソッドの使用

仮想メソッドは子クラスでオーバーライドされる場合に使用します。(直接または間接に)多くの子クラスが存在するクラスでのみ動的メソッドを使用するべきです。例えば、まれにオーバーライドされる一つのメソッドと 100 の子クラスとを持つクラスでは、その 100 の子クラスで使用されるメモリを節約するために、そのメソッドを dynamic にするべきです。

しかしながら、仮想メソッドの代わりに動的メソッドを使用することでメモリ要求が削減される保証はありません。さらに、リソース消費量という観点から見た場合、動的メソッドによる利益はごくわずかなものです。したがって、次ように言うことが出来ます:

通常は仮想メソッドを使用し、例外的な 状況でのみ動的メソッドを使用します。

抽象メソッド

インスタンスが作られるクラスでは抽象メソッドを使用してはいけません。インスタンスが決して作られることのない基底クラスでのみ抽象メソッドを使用してください。

プロパティアクセスメソッド

すべてのアクセスメソッドは、クラス宣言の private 部または protected 部に置かなければいけません。

プロパティのアクセスメソッドの命名は、手続きや関数と同じ規則に従います。リードアクセサメソッド(読み取りメソッド)は Get を前置しなければいけません。ライトアクセサメソッド(書き込みメソッド)は Set を前置しなければいけません。書き込みメソッドの引数は Value という名前にし、その型はそれが表しているプロパティの型になります。

  TSomeClass = class(TObject)
  private
    FSomeField: Integer;
  protected
    function GetSomeField: Integer;
    procedure SetSomeField(Value: Integer);
  public
    property SomeField: Integer read GetSomeField write SetSomeField;
  end;

プロパティ

命名 / フォーマット

private のフィールドへのアクセスを提供するプロパティは、フィールド名から F を除いた名前にします。

プロパティ名は動詞ではなく名詞にするべきです。プロパティは情報を表し、メソッドは動作を表します。

配列型プロパティは複数形にし、通常のプロパティ名は単数形にするべきです。

アクセスメソッドの使用

必須ではありませんが、private のフィールドを表すプロパティへの書き込みメソッドの使用は最小限にすることが勧められます。

 

ファイル

プロジェクトファイル

プロジェクトファイルは説明的な名前にします。例えば The Delphi 4 Developer's Guide Bug Manager には DDGBugs.dpr といった名前を付け、システム情報を表示するプログラムには SysInfo.dpr のような名前を付けます。

フォームファイル

フォームファイルはそのフォームの目的を表す説明の後ろに Frm を付けた名前にます。例えば About フォームには AboutFrm.dfm という名前を付け、メインフォームには MainFrm.dfm という名前を付けます。

データモジュールファイル

データモジュールには、そのデータモジュールの目的を説明する名前を付けます。名前の後ろに DM を付けます。例えば顧客データモジュール(Customers data module)には、CustomersDM.dfm のようなフォームファイル名を付けます。

リモートデータモジュールファイル

リモートデータモジュールには、そのリモートデータモジュールの目的を説明する名前を付けます。名前の後ろに RDM を付けます。例えば顧客リモートデータモジュール(Customers remote data module)には CustomersRDM.dfm のようなフォームファイル名を付けます。

ユニットファイル

ユニット名

ユニットファイルには説明的な名前を付けます。例えばアプリケーションのメインフォームを含むユニットは、MainFrm.pas といった名前になるでしょう。

Uses 節

interface 部の uses 節にはその interface 部で必要とされるユニットだけが含まれるようにします。Delphi によって自動的に追加される余分なユニットはすべて削除してください。

implementation 部の uses 節にはその implementation 部で必要とされるユニットだけが含まれるようにします。余分なユニットは削除してください。

interface 部

interface 部には外部のユニットからアクセスされる型・変数・手続き/関数などの前方宣言だけが含まれるようにします。外部からアクセスされない宣言は implementation 部に置きます。

implementation 部

ユニット内でプライベートなすべての型・変数・手続き/関数などの宣言は implementation 部に含めるべきです。

initialization 部

ユニットの initialization 部に時間のかかるコードを置いてはいけません。アプリケーションの初期表示をもたつかせてしまいます。

finalization 部

initialization 部で割り当てたすべてのリソースを確実に開放するようにしてください。

フォームユニット

フォームに付随するユニットファイルには、対応するフォームファイルと同じ名前を付けます。例えば About フォームには AboutFrm.pas という名前を付け、メインフォームには MainFrm.pas というユニットファイル名を付けます。

データモジュールユニット

データモジュールに付随するユニットファイルには、対応するフォームファイルと同じ名前を付けます。例えば顧客データモジュール(Customers data module)には CustomersDM.pas のようなユニット名を付けます。

一般的なユニット

一般的なユニットは、そのユニットの目的を良く表す名前にします。例えばユーティリティユニットには BugUtilities.pas といった名前を付け、グローバル変数を含むユニットには CustomerGlobals.pas のような名前を付けます。

プロジェクトで使用されているすべてのパッケージ間でユニット名が一意でなければならないことを忘れないでください。一般的すぎるユニット名や普通すぎるユニット名は勧められません。

コンポーネントユニット

コンポーネントやコンポーネントのセットを定義しているユニットをそれぞれ区別するために、コンポーネントユニットはそれぞれ別々のディレクトリに置きます。プロジェクトと同じディレクトリに置いてはいけません。ユニット名はその内容を良く表す名前でなければいけません。

注意:コンポーネントの命名に関するさらなる情報は、ユーザー定義コンポーネント のセクションを参照してください。

ファイルヘッダ

すべてのソースファイル・プロジェクトファイル・ユニット等には、情報通知のためのファイルヘッダを含めることが勧められます。適切なファイルヘッダは次の情報を含まなければいけません。

  {
  Copyright © YEAR by AUTHORS
  }

通常はこのヘッダに、ユニットの目的を表す 1 行の説明と連絡方法とを追加し、例えば以下のようにします。

{***************************************************************}
{                                                               }
{  This line describes the purpose of the unit                  }
{                                                               }
{  Copyright (c) 1998 WidgetMakers, Ltd.                        }
{                        contact@WidgetMakers.corp              }
{                                                               }
{     All rights reserved.                                      }
{                                                               }
{***************************************************************}
 

フォームとデータモジュール

フォーム

フォームの型の命名規則

フォームの型にはそのフォームの目的を説明する名前を付けます。型定義の 1 文字目は T とし、名前をその後に続け、最後に Form を付けます。例えば About フォームの型名は以下のようにします。

  TAboutForm = class(TForm)

メインフォームの定義は以下のようにします。

  TMainForm = class(TForm)

顧客登録フォーム(customer entry form)には以下のような名前を付けます。

  TCustomerEntryForm = class(TForm)

フォームのインスタンスの命名規則

フォームのインスタンスは、対応する型名から 1 文字目の T を除いた名前にします。例えば上記のフォームの場合、以下のようなインスタンス名にします。

型名 インスタンス名
TAboutForm AboutForm
TMainForm MainForm
TCustomerEntryForm CustomerEntryForm

自動生成フォーム

特に理由がない限り、自動生成するのはメインフォームだけにします。その他のすべてのフォームは、プロジェクトオプションのダイアログボックスにある自動生成のリストから削除してください。さらなる情報は次のセクションを参照してください。

モーダルフォームをインスタンス化する関数

すべてのフォームに、そのフォームを生成し、セットアップし、そのフォームをモーダル表示し、最後に開放するというインスタンス化関数を含むようにします。この関数はそのフォームの Modal Result を返します。この関数への引数は、この文書で規定されている"引数の受け渡し"の規則に従います。これはコードの再利用と保守とを容易にするためにカプセル化するための関数です。

フォーム変数はユニットから削除し、インスタンス化関数の中でローカル変数として宣言します。これを行うには、プロジェクトオプションダイアログにある自動生成のリストからそのフォームを削除する必要があることに注意してください。自動生成フォーム を参照してください。

例えば次のユニットは、ユーザーデータを取得するフォームの GetUserData 関数です。

  unit UserDataFrm;
  interface
  uses
    Windows, Messages, SysUtils, Classes, Graphics,
    Controls, Forms, Dialogs, StdCtrls;
  type
    TUserDataForm = class(TForm)
      edtUserName: TEdit;
      edtUserID: TEdit;
    private
      { Private declarations }
    public
      { Public declarations }
    end;

  function GetUserData(var aUserName: string; var aUserID: Integer): Word;

  implementation

  {$R *.DFM}

  function GetUserData(var aUserName: string; var aUserID: Integer): Word;
  var
    UserDataForm: TUserDataForm;
  begin

    UserDataForm := TUserDataForm.Create(Application);
    try

      UserDataForm.Caption := 'Getting User Data';
      Result := UserDataForm.ShowModal;
      if Result = mrOK then
      begin
        aUserName := UserDataForm.edtUserName.Text;
        aUserID := StrToInt(UserDataForm.edtUserID.Text);
      end;

    finally
      UserDataForm.Free;
    end;

  end;

  end.

データモジュール

データモジュール命名規則

DataModule の型にはそのデータモジュールの目的を説明する名前を付けます。型定義の 1 文字目は T とし、名前をその後に続け、最後に "DataModule" を付けます。例えば顧客データモジュール(Customer data module)の型名は以下のようにします。

  TCustomerDataModule = class(TDataModule)

例えば注文データモジュール(Orders data module)には以下のような名前を付けます。

  TOrdersDataModule = class(TDataModule)

データモジュールのインスタンスの命名規則

データモジュールのインスタンスは、その型名から前置の T を除いた名前にします。例えば前述のデータモジュールの型の場合、以下のようなインスタンス名にします。

型名 インスタンス名
TCustomerDataModule CustomerDataModule
TOrdersDataModule OrdersDataModule
 

パッケージ

実行時パッケージ vs 設計時パッケージ

実行時パッケージには、そのパッケージ内の他のコンポーネントによって必要とされるユニット/コンポーネントのみが含まれるようにします。プロパティエディタ/コンポーネントエディタやその他の設計時のみに必要なコードを含むユニットは、設計時パッケージに置くべきです。コンポーネントを登録するためのユニットは設計時パッケージに置きます。

ファイルの命名規則

パッケージは以下のテンプレートにしたがって命名します。

"iiilibvv.pkg" - 設計時パッケージ

"iiistdvv.pkg" - 実行時パッケージ

ここで "iii" は識別子のプレフィクスを表す 3 文字です。このプレフィクスは会社や個人や、その他の任意の要素を特定するために使用できます。

"vv" はパッケージが意図している Delphi のバージョンに対応するそのパッケージのバージョンを表しています。

実行時パッケージか設計時パッケージかを表すために、パッケージ名に "lib" または "std" を含めることに注意してください。

設計時パッケージと実行時パッケージとが両方存在する場合、ファイルは同じような名前になります。例えば Delphi 4 Developer's Guide のためのパッケージは以下のようになります。

DdgLib40.pkg - 設計時パッケージ

DdgStd40.pkg - 実行時パッケージ

 

コンポーネント

ユーザー定義コンポーネント

プレフィクスを表す 3 文字を付けることを除き、コンポーネントは "クラス" のセクションで定義されているのと同じ規則にしたがうべきです。このプレフィクスは会社や個人や、その他の任意の要素を特定するために使用できます。 例えば Delphi 4 Developer's Guide のために書かれた時計(Clock)コンポーネントは次のように定義します。

 TddgClock = class(TComponent)

3 文字のプレフィクスを小文字で書くことに注意してください。

コンポーネントユニット

コンポーネントユニットは、主要なコンポーネントを一つだけ含むべきです。主要なコンポーネントとは、コンポーネントパレットに現れる任意のコンポーネントです。主要なコンポーネントと同じユニットに、任意の補助的なコンポーネント/オブジェクトを置くことが出来ます。

登録ユニットの使用

コンポーネントの登録手続きはコンポーネントユニットから切り離し、別のユニットに置くべきです。任意のコンポーネント・プロパティエディタ・コンポーネントエディタ・エキスパートなどを登録するために登録ユニットを使用するべきです。

コンポーネントの登録は設計時パッケージ内でのみ行われるべきです。したがって登録ユニットは実行時パッケージに含めず、設計時パッケージに含めるべきです。

登録ユニットは以下のように命名することが推奨されます。

 XxxReg.pas

ここで "Xxx" は 3 文字のプレフィクスで、会社や個人や、その他の任意の要素を特定するために使用されます。例えば Delphi 4 Developer's Guide 内のコンポーネントのための登録ユニットは DdgReg.pas のような名前にします。

コンポーネントのインスタンスの命名規則

すべてのコンポーネントには説明的な名前を付けなければいけません。Delphi によって付けられるデフォルトの名前は残しません。コンポーネントには型を表す小文字のプレフィクスを付けます。コンポーネントにポストフィクスではなくプレフィクスを付ける理由は、オブジェクトインスペクタやコードエクスプローラ上でコンポーネントの型による検索を容易にするためです。

コンポーネントのプレフィクス

以下のプレフィクスは Delphi 4 に付属している標準コンポーネントに割り当てられるものです。サードパーティ製コンポーネントによって追加されるコンポーネントをこのリストに追加してください。

Standard タブ

プレフィクス コンポーネント
mm TMainMenu
pm TPopupMenu
mmi TMainMenuItem
pmi TPopupMenuItem
lbl TLabel
edt TEdit
mem TMemo
btn TButton
chk TCheckBox
rb TRadioButton
lb TListBox
cb TComboBox
scb TScrollBar
gb TGroupBox
rg TRadioGroup
pnl TPanel
cl TCommandList

Additional タブ

プレフィクス コンポーネント
bbtn TBitBtn
sb TSpeedButton
me TMaskEdit
sg TStringGrid
dg TDrawGrid
img TImage
shp TShape
bvl TBevel
sbx TScrollBox
clb TCheckListbox
spl TSplitter
stx TStaticText
cht TChart

Win32 タブ

プレフィクス コンポーネント
tbc TTabControl
pgc TPageControl
il TImageList
re TRichEdit
tbr TTrackBar
prb TProgressBar
ud TUpDown
hk THotKey
ani TAnimate
dtp TDateTimePicker
tv TTreeView
lv TListView
hdr THeaderControl
stb TStatusBar
tlb TToolBar
clb TCoolBar

System タブ

プレフィクス コンポーネント
tm TTimer
pb TPaintBox
mp TMediaPlayer
olec TOleContainer
ddcc TDDEClientConv
ddci TDDEClientItem
ddsc TDDEServerConv
ddsi TDDEServerItem

Internet タブ

プレフィクス コンポーネント
csk TClientSocket
ssk TServerSocket
wbd TWebDispatcher
pp TPageProducer
tp TQueryTableProducer
dstp TDataSetTableProducer
nmdt TNMDayTime
nec TNMEcho
nf TNMFinger
nftp TNMFtp
nhttp TNMHttp
nMsg TNMMsg
nmsg TNMMSGServ
nntp TNMNNTP
npop TNMPop3
nuup TNMUUProcessor
smtp TNMSMTP
nst TNMStrm
nsts TNMStrmServ
ntm TNMTime
nudp TNMUdp
psk TPowerSock
ngs TNMGeneralServer
html THtml
url TNMUrl
sml TSimpleMail

Data Access タブ

プレフィクス コンポーネント
ds TDataSource
tbl TTable
qry TQuery
sp TStoredProc
db TDataBase
ssn TSession
bm TBatchMove
usql TUpdateSQL

Data Controls タブ

プレフィクス コンポーネント
dbg TDBGrid
dbn TDBNavigator
dbt TDBText
dbe TDBEdit
dbm TDBMemo
dbi TDBImage
dblb TDBListBox
dbcb TDBComboBox
dbch TDBCheckBox
dbrg TDBRadioGroup
dbll TDBLookupListBox
dblc TDBLookupComboBox
dbre TDBRichEdit
dbcg TDBCtrlGrid
dbch TDBChart

Decision Cube タブ

プレフィクス コンポーネント
dcb TDecisionCube
dcq TDecisionQuery
dcs TDecisionSource
dcp TDecisionPivot
dcg TDecisionGrid
dcgr TDecisionGraph

QReport タブ

プレフィクス コンポーネント
qr TQuickReport
qrsd TQRSubDetail
qrb TQRBand
qrcb TQRChildBand
qrg TQRGroup
qrl TQRLabel
qrt TQRText
qre TQRExpr
qrs TQRSysData
qrm TQRMemo
qrrt TQRRichText
qrdr TQRDBRichText
qrsh TQRShape
qri TQRImage
qrdi TQRDBMImage
qrcr TQRCompositeReport
qrp TQRPreview
qrch TQRChart

Dialogs タブ

ダイアログボックスは実際にはコンポーネントによってカプセル化されたフォームです。そのため、フォームの命名規則に似た規則に従います。型定義はコンポーネント名としてあらかじめ定義されています。インスタンス名は Delphi によって付けられる数字のポストフィクスを取り除き、その型と同じ名前にします。以下はその例です。

インスタンス名
TOpenDialog OpenDialog
TSaveDialog SaveDialog
TOpenPictureDialog OpenPictureDialog
TSavePictureDialog SavePictureDialog
TFontDialog FontDialog
TColorDialog ColorDialog
TPrintDialog PrintDialog
TPrintSetupDialog PrinterSetupDialog
TFindDialog FindDialog
TReplaceDialog ReplaceDialog

Win31 タブ

プレフィクス コンポーネント
dbll TDBLookupList
dblc TDBLookupCombo
ts TTabSet
ol TOutline
tnb TTabbedNoteBook
nb TNoteBook
hdr THeader
flb TFileListBox
dlb TDirectoryListBox
dcb TDriveComboBox
fcb TFilterComboBox

Samples タブ

プレフィクス コンポーネント
gg TGauge
cg TColorGrid
spb TSpinButton
spe TSpinEdit
dol TDirectoryOutline
cal TCalendar
ibea TIBEventAlerter

ActiveX タブ

プレフィクス コンポーネント
cfx TChartFX
vsp TVSSpell
f1b TF1Book
vtc TVTChart
grp TGraph

Midas タブ

プレフィクス コンポーネント
prv TProvider
cds TClientDataSet
qcds TQueryClientDataSet
dcom TDCOMConnection
olee TOleEnterpriseConnection
sck TSocketConnection
rms TRemoteServer
mid TmidasConnection

Delphi Information Resources に戻る。


Copyright © 1998 Econos - Stefan Hoffmeister