Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Enumを使ってフラグ値を良い感じに扱う

More than 3 years have passed since last update.

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

元ネタ

https://speakerdeck.com/twada/php-conference-2016-revised

防御的プログラミング

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

コード例

元ネタ: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というメッセージが出されることで,「あ、値の渡し方が間違えているんだな」と利用者に対して理解してもらうことができます。

akihiro-iwata
エムスリーデジカルというクラウド電子カルテのPdMやってます。 ex-Accenture
m3dev
インターネット、最新IT技術を活用し日本・世界の医療を改善することを目指します
https://m3.recruitment.jp/engineer/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away