PHP
どう書く

PHPでelseを書きたくない時に使える回避手段


はじめに


  • 社内勉強会で発表する内容です

  • ロジックの中でelseを使わなくなったので、どうやって回避しているのかをまとめています

  • バリバリ主観が入っているので、そこは注意


自分で検証したやつ

https://github.com/niisan-tokyo/replaceelse



if ~ else の回避手段



オリジナル


OriginalElse.php

class OriginalElse

{
public function ifElse(bool $bool)
{
if ($bool === true) {
return 'YES';
} else {
return 'NO';
}
}
}



書き換え



早期リターン

よく見るポピュラーなelseの回避手段

オリジナルは、そもそもelseが不要だったりする

一応、どんなときでも使える


ReplaceElse.php

class ReplaceElse

{

/**
* 早期リターン
*/

public function ifElse(bool $bool)
{
if ($bool === true) {
return 'YES';
}

return 'NO';
}
}




初期値代入

elseの中を初期値もしくはデフォルト値とみなし、if条件が来たら中身を書き直す方法

if ~ elseが代入処理か、代入処理に変換する必要があるので、ちょっと面倒かも

巨大なデータを入れる場合でもない限り、初期値代入のコストはだいたい無視していい


ReplaceElse.php

    /**

* 初期値代入
*/

public function ifElse2(bool $bool)
{
$str = 'YES';
if ($bool === false) {
$str = 'NO';
}

return $str;
}




三項演算子

単純なif ~ elseは三項演算子で書くと目に優しい

分岐処理がそれぞれ一行で住む場合に使用できる

初期値代入の亜種で、プログラムの行数をかなり節約できる

条件式が長い場合は条件式部分を分離しないと横に長くなって目に厳しい


ReplaceElse.php

    /**

* 三項演算子
*/

public function ifElse3(bool $bool)
{
return ($bool === true) ? 'YES': 'NO';
}



if~elseまとめ


  • elseを使わなくて書けます

  • 個人的優先順位は 三項演算子 > 早期リターン > (メソッド化) > 初期値代入

  • 三項演算子は条件式と相談して、可読性が落ちそうなほど長くなければ使う

  • さっさとreturn できるならしちゃう

  • 条件分岐がメソッドで切り出すほどでもなければ、初期値代入でお茶を濁す



if ~ else if ~ else



オリジナル

分岐条件が複数ある場合

書きたくないelseがいくつもある...だと


OriginalElse.php

    public function ifElseIf(int $num)

{
if ($num === 0) {
$str = 'ZERO';
} else if ($num === 1) {
$str = 'ONE';
} else if ($num === 2) {
$str = 'TWO';
} else {
$str = 'OTHER';
}

return $str;
}




書き換え



switch文

個人的には強く非推奨

switch文のほうが早いよっていう言説をたまに聞くけど、今どきのCPUでは無視していいレベルだと思う

インデントが増えたりして可読性も悪くなる気がする

比較条件がゆるい比較なので、評価に使用する変数の型が可変な場合は注意


ReplaceElse.php

    /**

* switch文 (この場合は等価)
*/

public function ifElseIf(int $num)
{
switch ($num) {
case 0:
$str = 'ZERO';
break;
case 1:
$str = 'ONE';
break;
case 2;
$str = 'TWO';
break;
default:
$str = 'OTHER';
}

return $str;
}




早期リターンつなぎ

都度return してelseをことごとく消していく方法

単純なロジックの中であれば上から条件を眺めていける


ReplaceElse.php

    /**

* 早期リターンつなぎ
*/

public function ifElseif2(int $num)
{
if ($num === 0) {
return 'ZERO';
}

if ($num === 1) {
return 'ONE';
}

if ($num === 2) {
return 'TWO';
}

return 'OTHER';
}




配列とnull合体演算子

ちょっとアクロバティックなやり方で、php7以上が必須

分岐が多いけど単純な場合はこれを使う事が多い


ReplaceElse.php

    /**

* 配列 + null合体演算子
*/

public function ifElseIf3(int $num)
{
$arr = [
0 => 'ZERO',
1 => 'ONE',
2 => 'TWO'
];

return $arr[$num] ?? 'OTHER';
}




配列とnull合体演算子とメソッドコール

各if, elseif, elseの分岐で複雑な処理が入る場合は各々の処理をメソッドに分ける

メソッドのインターフェースが同じ場合に使える


ReplaceElse.php

    /**

* 配列 + null合体演算子 + メソッドコール
*/

public function ifElseIf4(int $num)
{
$arr = [
0 => 'getZero',
1 => 'getOne',
2 => 'getTwo'
];
$method = $arr[$num] ?? 'getOther';
return $this->{$method}();
}

private function getZero() { return 'ZERO'; }
private function getOne() { return 'ONE'; }
private function getTwo() { return 'TWO'; }
private function getOther() { return 'OTHER'; }




if ~ else ~ if まとめ


  • こちらは優先順位がつけにくいが, 短い場合は早期リターンつなぎで、分岐が多くなってくると、配列 + null合体演算の組み合わせになる感じ

  • 各分岐後の処理が大きくなると、メソッドに出しちゃう

  • switch文は基本読みにくくなるのでやらない



まとめ


  • elseを書かなくても分岐処理は書けるし、else使わないほうが見やすい場合が多い

  • 単純な分岐であれば三項演算子が見やすいが、条件が複雑であれば早期リターンを使うほうがスッキリする

  • 複数分岐するのであれば配列を駆使するのもあり

  • 他にも書き方があるとは思うが、とりあえずみやすさを優先するといいんじゃないかって思う