(jp) =
これは、PHP で列挙型を使用するための私の個人的なスタイル ガイドです。 各セクションでは、ルールについて説明しますが、個人的なルールについても説明します。 独断 ルールの背後にある理由。
# 1. 大文字
列挙型の場合は大文字表記を使用する必要があります。
enum PostState
case PENDING;
case PUBLISHED;
case STARRED;
case DENIED;
# どうして?
列挙型は「定数値」に非常に近いものです。 RFC は PascalCase (他の言語に触発されたもの) を使用することを示していましたが、そうする正当な理由はありません。
一部の人々は、特に定数と列挙を視覚的に区別するために列挙に PascalCase を使用すると主張しています。 概念を区別するために命名規則に頼るのは良い考えだとは思いません。 命名規則に固執するのではなく、IDE や編集者の洞察に頼って何かを知る方が良いでしょう。
皮肉なことに、大文字の定数が存在する理由は同じです。通常の変数と区別するためです。 その事実を認めたいと思いますが、何十年にもわたるプログラミングの歴史を変えるためにできることはほとんどありません。 大部分の PHP プロジェクトでは大文字の定数が使用されていると言っても過言ではありません。そのため、慣習がどのように発生したかにかかわらず、密接に関連する概念についてはその慣習に従いたいと考えています。
それにもかかわらず、私は列挙型に PascalCase を使用してみましたが、常に不自然に感じました。 つまり、戻ってリファクタリングする必要がありました。 私は本能と戦うのではなく、定数値が何年にもわたって書かれてきた方法と、とにかく列挙型が定数にどれほど近いかという理由で、私にとって最も自然に感じる大文字表記を使用することにしました。
# 2. backed enum を使いすぎない
実際にそれらが必要な場合にのみ、裏付けられた列挙型を使用する必要があります。 一般的な使用例はシリアル化です。 列挙型がコード内でのみ使用される場合は、それを裏付けられた列挙型にしないでください。
enum PostState: string
case PENDING = 'pending';
case PUBLISHED = 'published';
case STARRED = 'starred';
case DENIED = 'denied';
# どうして?
手動で列挙型に値を割り当てると、保守のオーバーヘッドが発生します。列挙型のケース自体だけでなく、その値も保守する必要があります。 オーバーヘッドを追加する場合と追加しない場合を考慮することが重要です。
それに加えて、列挙型には組み込みの name
テキスト表現が必要な場合に常にアクセスできるプロパティ:
Status::PUBLISHED->name;
疑問がある場合は、次のルールを適用してください: スカラー値 (データベース、ユーザー入力など) からこの列挙型を作成する必要がありますか: 裏付けられた列挙型を使用します。 ただし、答えが「いいえ」の場合は、ユースケースで必要になるまで値の割り当てを保留してください。
# 3. 単純な一致メソッドが許可されます
列挙型に複雑なメソッドを含めないでください。 理想的には、それらは match
特定の列挙型の場合により豊富な機能を提供する式:
enum Status
case DRAFT;
case PUBLISHED;
case ARCHIVED;
public function label(): string
return match($this)
Status::DRAFT => 'work in progress',
Status::PUBLISHED => 'published',
Status::ARCHIVED => 'archived',
;
# どうして?
列挙型は複雑な機能を提供するべきではありません。列挙型にあまりにも多くのロジックを記述していることに気付いた場合は、代わりに状態パターンの使用を検討することをお勧めします。
良い経験則は、それが match
式 (クロージャーや呼び出し可能オブジェクトなどを返すことなく) を使用すれば、準備完了です。 それ以外の場合は、代替案を検討してください。
# 4. 値をラベルとして使用しないでください
裏付けられた列挙型の値は、ラベルの提供などの機能ではなく、(逆) シリアル化の値としてのみ使用する必要があります。
# どうして?
前のポイントの例を次のように書き直したくなるかもしれません。
enum Status
case DRAFT = 'work in progress';
case PUBLISHED = 'published';
case ARCHIVED = 'archived';
短くはなりましたが、2 つの懸念事項を 1 つにまとめています: ユーザーが読み取り可能な形式でラベルを表し、それらのシリアライゼーション値と組み合わせています。 前者は時間の経過とともに変更される可能性が非常に高く、後者は複雑なデータ移行を防ぐために可能な限り変更しないでください。
# 5. インデックス値なし
列挙型に「順序」または「インデックス」の概念を割り当てないでください。
enum VatPercentage: int
case SIX = 6;
case TWELVE = 12;
case TWENTY_ONE = 21;
enum Status: int
case DRAFT = 1;
case PUBLISHED = 2;
case ARCHIVED = 3;
# どうして?
たとえば、ステータス列挙型に整数値を割り当てたくなるかもしれません。 DRAFT
前に来る PUBLISHED
、 前に来る ARCHIVED
.
このようなシーケンシャル インデックス作成は限られたケースで機能しますが、維持するのは面倒です。 と呼ばれる別の状態を追加する必要がある場合はどうなりますか DENIED
? おそらく値を取得する必要があります 2
また 3
、つまり、公開およびアーカイブされたすべてのエントリのデータ移行が滞っていることを意味します。
不確かな場合は、状態パターンを使用して、代わりに状態とその順序間の複雑な遷移をモデル化できます。
同意しますか? 同意しませんか? 教えて ツイッター またはメールで!