LoginSignup
4
1

More than 5 years have passed since last update.

「間違った使い方ができない」ようなコードを書くためにはEnumが有用です。

元ネタ

防御的プログラミング

コードを書く人間であれば誰しも,『良いコードとは何か』という問いに直面した経験があるかと思います。
これを一概に言い切ることは難しいですが,個人的にわかりやすい指標として「間違った使い方をする方が難しい」というのが挙げられると考えています。

コード例

元ネタ:https://twitter.com/yoookd/status/933711986071953409

具体的に、以下のコードを例にします。

<?php

class Something {
    public function praise($country) 
    {
        if($status === '1'){
            return 'Awesome';
        }else if ($status === '2'){
            return 'Excellent';
        }
        }else if ($status === '3'){
            return "...actually it's not bad";
        }
        throw new Exception('not defined country');
    }
}

引数にcountryを受取り,これが1の時はアメリカ人なのでAwesome,これが2の時はオーストラリア人なのでExcellent,これが3の時は英国人なので...actually it's not badと返します。
国籍設定に他意はありません。

この関数の「正しい」使い方を知るためには,関数の処理内容を見て「あ、1か2か3のどれかを渡すんだな」と理解する必要があります。あるいはコメントでそれを説明する方式もあります。いずれにせよ,関数の処理を文書かソースから理解し,関数を呼び出す側で1〜3以外の値が渡されないように工夫する必要があります。

Enumを使ったコード例

引用:https://qiita.com/Hiraku/items/71e385b56dcaa37629fe

<?php
abstract class Enum
{
    private $scalar;

    public function __construct($value)
    {
        $ref = new ReflectionObject($this);
        $consts = $ref->getConstants();
        if (! in_array($value, $consts, true)) {
            throw new InvalidArgumentException;
        }

        $this->scalar = $value;
    }

    final public static function __callStatic($label, $args)
    {
        $class = get_called_class();
        $const = constant("$class::$label");
        return new $class($const);
    }

    //元の値を取り出すメソッド。
    //メソッド名は好みのものに変更どうぞ
    final public function valueOf()
    {
        return $this->scalar;
    }

    final public function __toString()
    {
        return (string)$this->scalar;
    }
}

final class Country extends Enum
{
    const USA = '1';
    const AUSTRALIA = '2';
    const BRITISH = '3';
}

class Something {
    public function praise(Country $country) 
    {
        switch($country->value()){
            case Country::USA:
                return 'Awesome';
            case Country::AUSTRALIA:
                return 'Excellent';
            case Country::BRITISH:
                return "...actually it's not bad";
        }
    }
}

この書き方だと,例えばpraise関数に対して4という値を与えるとInvalidArgumentExceptionが発生します。先のコード例でも4という値を渡すと正しく動かないという点では共通していますが,InvalidArgumentExceptionというメッセージが出されることで,「あ、値の渡し方が間違えているんだな」と利用者に対して理解してもらうことができます。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1