D言語のスタイル

Dスタイルは、Dプログラムを書くためのスタイル規約である。 である。D言語のスタイルはコンパイラによって強制されるものではない。それは 純粋に外観的なものであり、選択の問題である。D言語のスタイル "に従う、 しかし、Dスタイルに従うことで、他の人があなたのコードを扱いやすくなり、あなたが他の人のコードを扱いやすくなる。 他の人があなたのコードを扱いやすくなり、あなたが他の人のコードを扱いやすくなる。 D言語のスタイルは、プロジェクト・チームのためにカスタマイズされたプロジェクト・スタイル・ガイドの出発点となる。 スタイル・ガイドの出発点とすることができる。
フォボスやその他の公式Dソースコードへの提出は、以下のガイドラインに従う。 これらのガイドラインに従う。
ホワイトスペース
- 1行に1文。
- ハードウェア・タブの代わりにスペースを使う。
- 各インデント・レベルは4列とする。
命名規則
- 一般
- 以下に別段の定めがない限り、名前はキャメルケース(camelCased)でなければならない(これはすべての変数を含む)。
すべての変数を含む)。つまり、複数の単語を連結してできた
は、最初の単語以外の各単語が大文字になる。また、名前
はアンダースコア '_' で始まらない。
プライベートである場合を除く。
int myFunc(); string myLocalVar;
- モジュール
- モジュール名とパッケージ名はすべて小文字で、[a.z[0..9][_]文字のみを含むこと。
文字[a..z][0..9][_]のみを含む。これは
大文字小文字を区別しないファイルシステムを扱うときの問題を避けることができる。
import std.algorithm;
- クラス、インターフェイス、構造体、共用体、列挙型、非同名テンプレート
- ユーザ定義型の名前はPascalCasedでなければならない。
最初の文字が大文字であることを除けば、camelCasedと同じである。
class Foo; struct FooAndBar;
- 同名テンプレート
- テンプレート内のシンボルと同じ名前を持つテンプレート。
(そのため、そのテンプレートのインスタンスはその
そのため、そのテンプレートのインスタンスはそのシンボルに置き換えられる)、その内部のシンボルは、テンプレートの中にない場合と同じように大文字で表記されるべきである。
例えば、型はPascalCasedにし、値は
例えば、型は PascalCased で、値は camelCased であるべきである。
template GetSomeType(T) { alias GetSomeType = T; } template isSomeType(T) { enum isSomeType = is(T == SomeType); } template MyType(T) { struct MyType { ... } } template map(fun...) { auto map(Range r) { ... } }
- 関数
- 関数名はキャメルケース(camelCased)でなければならず、最初の文字は小文字になる。
これにはプロパティやメンバー関数も含まれる。
int done(); int doneProcessing();
- 定数
- 定数の名前は、通常の変数と同じようにキャメルケースにすべきである。
enum secondsPerMinute = 60; immutable hexDigits = "0123456789ABCDEF";
- 列挙型メンバ
- 列挙型のメンバーはキャメルケース(camelCased)でなければならない。
を小文字にする。
enum Direction { bwd, fwd, both } enum OpenRight { no, yes }
- キーワード
- 名前がキーワードと衝突する可能性があり、別の名前を選ぶよりもキーワードを使用する方が望ましい場合、そのキーワードを使用する。
キーワードを使用することが望ましい場合は、そのキーワードにアンダースコア
'_'を付ける。名前は
キーワードとの衝突を避けるために、大文字と小文字を区別してはならない。
enum Attribute { nothrow_, pure_, safe }
- 頭字語
- 頭字語がシンボル名に使用される場合、頭字語のすべての文字は大文字と小文字が同じでなければならない。
の大文字と小文字は同じでなければならない。つまり、頭字語の最初の文字が小文字の場合
が小文字の場合、頭字語の文字はすべて小文字になる。
頭字語の最初の文字が大文字であれば、頭字語のすべての文字は大文字である。
はすべて大文字である。
class UTFException; ubyte asciiChar;
- ユーザー定義属性
- ユーザー定義属性としてのみ使用されるシンボルの場合、その名前はキャメルケース(camelCase)でなければならない。
の最初の文字を小文字にする。この
この規約は、先に述べた規約よりも優先される。
これは、@safe 、
@nogc や、特別なコンパイラが認識するUDA@selector のような組み込み属性の規約と一致する。
struct Foo {} // この構造体は通常の命名規則に従う // この構造体はUDAとしてのみ使用されることを意図しているため、 // 構造体の通常の命名規則を上書きする struct name { string value; } @name("bar") Foo foo;
型の別名
Dプログラミング言語では、型エイリアスに2つの機能的に等価な構文が用意されている。
alias size_t = uint;
...よりも好まれる。
alias uint size_t;
なぜなら
- Cのtypedef構文を反転させたものではなく、すでになじみのある代入構文に従っている。
- 冗長な宣言では、何が宣言されているかがわかりやすい。
alias important = someTemplateDetail!(withParameters, andValues); alias Callback = ReturnType function(Arg1, Arg2) pure nothrow;
対
alias someTemplateDetail!(withParameters, andValues) important; alias ReturnType function(Arg1, Arg2) pure nothrow Callback;
...のような無意味な型エイリアス。
alias VOID = void; alias INT = int; alias pint = int*;
...は避けるべきである。
宣言スタイル
宣言は左結合なので、左揃えにする:
int[] x, y; // xとyが同じ型であることを明確にする int** p, q; // pとqが同じ型であることを明確にする
を使い、両者の関係を強調する。C言語のスタイルは使わないこと:
int []x, y; // yもint[]であるため、紛らわしい int **p, q; // qもint**であるため、紛らわしい
演算子オーバーロード
演算子オーバーロードは、言語がサポートする基本型を拡張する強力なツールである。 を拡張する強力なツールである。しかし、強力であるがゆえに 難読化されたコードを生み出す可能性が大きい。特にそうだ、 既存のD演算子には従来の意味がある。 は「加算」、「<<」は「左シフト」を意味する。 は「左シフト」を意味する。 演算子'+'を'add'と異なる意味でオーバーロードすることは、恣意的な混乱を招く。 は恣意的に混乱を招くので避けるべきである。
ハンガリー語表記
変数の型を表すのにハンガリー記法を使用する を使うのは悪い考えだ。 しかし、(型では表せない)変数の目的を表すために (型では表せない)変数の目的を表すために記法を使うことは、しばしば良いことである。 である。
プロパティ
適切な場合はいつでも、関数はプロパティ関数でなければならない。特に 特に、ゲッターとセッターは一般的に避けるべきである。 プロパティ関数を優先すべきである。そして一般的に、関数は動詞であるべきである、 プロパティは、メンバ変数と同じように名詞であるべきだ。 ゲッター・プロパティは状態を変更すべきではない。
プロパティの構文
UFCSまたは オプションの括弧を使用しない。 括弧の省略は、メンバがフィールドか関数かを気にしない汎用的なコードで有用である。 例えば、範囲プリミティブfront のように、メンバがフィールドか関数かを気にしない一般的なコードでは、括弧を省略することが有効である。 また、範囲関数の連鎖をよりコンパクトにすることもできる。 しかし、副作用のある関数を単純に呼び出す場合は、"通常の"関数呼び出し構文を使用する。
import std.range, std.stdio; void main() { // Good writeln(); writeln("hello"); iota(0, 10).dropOne.array.front.writeln; // Bad writeln; "hello".writeln; writeln = "hello"; }
ドキュメンテーション
すべての公開宣言は、以下の形式で文書化される。 Ddoc形式で、少なくともParams と Returns セクションを持つべきである。
単体テスト
実用的な限りにおいて、すべての関数は、unittestブロックの直後にあるunitestブロックを使ったユニットテストによってテストされる。 unittest "ブロックを使ったユニットテストによって実施される。 を使って単体テストを行う。 コードのすべてのパスは、少なくとも一度は実行されるべきである、 コード・カバレッジ・アナライザーによって検証される。
Phobosの追加要件
一般的に、本ガイドはコードを推奨したり要求したりするものではない。 を推奨したり要求したりするものではない。一番上の の小さなセクションに、唯一の書式ガイドラインがある。ただし Phobosや他の公式Dソースコードでは、さらに必要なものがある:
ブラケット
中括弧は1行で区切る。これにはいくつかの例外がある (ラムダ関数を宣言するときなど)はあるが、通常の関数ブロックや型定義では、中括弧は一行で書くべきである。 ブロックや型定義では、中括弧は自分の行に書くべきである。
void func(int param) { if (param < 0) { ... } else { ... } }
不必要な括弧は避ける:
(a == b) ? "foo" : "bar"; // NO a == b ? "foo" : "bar"; // OK
行の長さ
行の長さはソフトリミットで80文字、ハードリミットで120文字である。 文字である。つまり、ほとんどのコード行は80文字以下でなければならない。 80文字以内であるべきだが、適切な場合には80文字を超えることができる。 を超えることができる。ただし、120文字を超えることはない。
空白文字
- for 、foreach 、if 、while 、version の後には空白を入れる:
for (…) { … } foreach (…) { … } static foreach (…) { … } if (x) { … } static if (x) { … } while (…) { … } do { … } while (…); version (…) { … }
if (…) { … } else if (…) { … }
a + b a / b a == b a && b arr[1 .. 2] int a = 100; b += 1; short c = cast(short) a; filter!(a => a == 42);
a = !a && !(2 == -1); bool b = ~a; auto d = &c; e++; assert(*d == 42); callMyFancyFunction("hello world");
インポートする。
- グローバルなインポートよりも、ローカルで選択的なインポートを優先すべきである。
- 選択的インポートでは、コロン(: )の前後に、以下のようにスペースを入れる。 import std.range : zip
- インポートは辞書順に並べる。
リターン型
属性
- テンプレート化された関数でないものは、以下の属性を持つべきである。 マッチする属性 (@nogc,@safe,pure,nothrow) を付けるべきである。
- テンプレート化された関数のテンプレート引数が、属性が適切であるかどうかに影響する場合、その関数はテンプレート化されるべきではない。 ある属性が適切であるかどうかに影響する場合、その関数はその属性でアノテートされるべきではない。 そのため、コンパイラーはその属性を推測することができる。 しかし、その属性がテンプレート引数 (によって影響されない(したがって、常に推測される)のであれば、関数はその属性を明示的にアノテートすべきである。 を明示的にアノテーションしなければならない。 関数がそうであるように。
- 属性はアルファベット順に並べる。const @nogc nothrow pure @safe (順序は先頭の@ を無視する)。
- Every unittest"アノテーションを付ける。 (例えば ) を付け、テンプレート化された関数に属性が存在することを確認する。pure nothrow @nogc @safe unittest { ... }
テンプレート
- unittest ブロックはテンプレートでは避けるべきである。これらはインスタンスごとに インスタンスごとに新しい 。 テンプレートの外に置くべきである。unittest
宣言
- 宣言の制約は、その宣言と同じインデント・レベルを持つべきである。 宣言の制約は、その宣言と同じインデントレベルを持つべきである:
void foo(R)(R r) if (R == 1)
// Prefer: T transmogrify(T)(T value) if (isIntegral!T) in (value % 7 == 0) out (result; result % 11 == 0) { // ... } // over this: T transmogrify(T)(T value) if (isIntegral!T) in { assert(value % 7 == 0); } out (result) { assert(result % 11 == 0); } do { // ... }
struct S { int x; invariant (x > 0); }
クラス/構造体フィールド宣言
- 構造体やクラスでは、フィールドの型とフィールド名の間には空白を1つだけ入れなければならない。 フィールドの型とその名前の間には空白を1つだけ入れなければならない。これは、将来の変更によって 必要以上に大きな git diff が生成される問題を避けることができる。
class MyClass { // Bad int a; double b; // Good int x; double y; }
ドキュメント
- すべてのパブリックシンボルはドキュメントで公開されるべきである:
/// パブリックシンボル enum myFancyConstant;
/** 数値が正数かどうかをチェックする。 `0`は正の数とはみなされない。 Params: number = チェックする番号 Returns: その数値が正であれば`true`、そうでなければ`0`を返す。 See_Also: $(LREF isNegative) */ bool isPositive(int number) { return number > 0; }
すべてのコードがこれらのルールに従うことを必ずしも推奨しているわけではない。 コーディング・スタンダードに関する議論では、賛否両論になるだろう。 しかし、Phobosやその他の公式D のソースコードに提出する際には必須である。
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.108.0
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku