ループ処理、switch文、break文、continue文の組み合わせには要注意（迷子になるから）

まずは以下のプログラムを見ていただきたい。
※このプログラム自体に意味はありません。参考用にサンプルで作ったものなので、ツッコミどころはいっぱいありますが、一応動きます。

```php:sample.php
<?php
$dbData = [
    ['id' => 1, 'type' => 1, 'col1' => '1-col1', 'col2' => '1-col2', 'col3' => '1-col3', 'col4' => '1-col4'],
    ['id' => 2, 'type' => 0, 'col1' => null,     'col2' => null,     'col3' => '2-col3', 'col4' => '2-col4'],
    ['id' => 3, 'type' => 2, 'col1' => '2-col1', 'col2' => '2-col2', 'col3' => '2-col3', 'col4' => '2-col4']
];

function fileterData(array $data)
{
    $result = [];
    foreach ($data as $datum) {
        $id = $datum['id'];
        $start = null;
        $end = null;
        for ($i = 1; $i <= 4; $i++) {
            switch ($i) {
                case 1:
                    $start = $datum['col' . $i];
                    continue 2;
                case 2:
                    $end = $datum['col' . $i];
                    continue 2;
                case 3:
                case 4:
                    continue 2;
                default:
                    continue 3;
            }
        }
        if (!empty($start) && !empty($end)) {
            $result[] = $datum['id'];
        }
    }
    return $result;
}

print_r(fileterData($dbData));
```

`php sample.php`を実行したときに得られる結果はなんでしょう？

```
php sample.php
Array
(
    [0] => 1
    [1] => 3
)
```

ですね！

# つらいプログラムのトレース

メンテナンスすることになったプログラムに上のような記述がありました。
どこがつらいか皆さんはわかりますか？

私はいくつかあります。

1. DBから取得したようなデータをループでフィルターしている。
2. カラムに対してループ処理して、`type`とカラム名によって変数代入、カラムの意味が変わってくる。
3. 2次元ループ内でswitch文、`continue 3`をしている。

一つ断っておくと、私自身は「つらいなぁ」とは思っていますが、100%否定もできないなと思っています。
というのも、DBデータをプログラム上でフィルターしたい場面は存在するし、カラムの意味を、例えばtypeカラムの値によって変更する設計はしばしば見受けられます。
できれば正規化していてほしいですが、「やむを得ない事情」というのは存在すると思うからです。
すべてが理想形どおりに進むわけはないと思っています。

# `continue 3`とか久しく見たことがなかった

いわゆるループ処理でよく使われるcontinue文には数字またはラベルというものを指定できます。
[PHP: continue - Manual](https://www.php.net/manual/ja/control-structures.continue.php)

このこと自体は私も10年以上前、専門学校でJavaを勉強していたときに習いました。
改めて当時の教本（当時はSun Microsystemsでした）を見返したところ、continue文の記載はあるものの、数値やラベルの指定を解説している箇所はありませんでした。おそらく同時の講師（めっちゃ板書がきれいな先生でした）が、基本だから抑えておくようにと思ったのだと思います。

当時のノート。
![qiita_20211124_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131218/2a677c9b-aa77-401b-8d7d-af10cdd2bbf8.png)

## `continue 3`はどういう意味か？

上記のプログラムでは`continue 3`は意味をなしていないので、`continue 2`を見ていきましょう。
と言っても、上の画像にほとんど答え書いてありますが。
ここに入ると処理は、`for`のところまでスコープが戻ります。`continue`以降の処理は実行されません。
ということは`continue 3`は`foreach`のところまでスコープが戻ります。

# そしてプログラマは、考えるのをやめた

最初は処理がどうなっているのかプログラムをトレースしていました。
ロガーを入れてみたりしたけど、いまいちどうなっているのかわからない。
そして`continue 2`みたいな構文を見つけたとき、どうするか迷いましたが、トレースしてみることにしました。
ですが、数時間しても何がどうなっているのかわからなくなって、そして考えるのをやめた。

結果だけをみて、「Don't think. Feel.」することにしました。

## 「Don't think. Feel.」できない事態になったら？

その時考えることにしました。
とにかく今、デバッグされて、正常に動いているものを無理に時間を割いて理解するのは時間の無駄、、、と思うことにしました（本当にそれでいいのかという気はしています）。

# 避けるべきとされるプログラム

こういったプログラムを見るとよく思うのですが、このプログラムを作った人はすごい人なのかどうかということです。
ひとつ言えるのは、メンテナンスしていた人はすごいと思います。

## 入れ子のしすぎ

if文とかでもそうですが、制御ブロック、端的に言うとインデント、もう少し詳しく言うと入れ子（ネスト）は3つを超えだすと、かなり見づらく、トレース、デバッグがしづらくなり、関数やメソッドへの切り出しを考えるべきと思っています。
結局そのプログラムがリリースされるとしばらくは自分がメンテナンスすることになりますし、プログラムはだいたい80桁で折り返せって言われますよね。
縦に長いのはマウスとかでスクロールできますが、横に長いのはスクロールしづらい。

上のプログラムも同じで、せめて何らかの形で、switchは別の関数に切り出されていると、まだ可読性が増すのかなと思います。
そして早期リターンするとか。

## `do-while`

書籍「[リーダブルコード](https://www.amazon.co.jp/dp/4873115655)」では、`do-while`も避けたほうがいいと言われています。
個人的には避けるべきだと思っていますが、Excelやスプレッドシートを処理するときにどうしても解決できない処理を`do-while`で解決したことがあります。
ここでは詳しく述べませんが、そのときひらめいたかのように「`do-while`なら解決できるのでは？」と思ったのを覚えています。

ちなみに専門学校では「これを使いたがる人がいる」といった感じで教えられました。

## `goto`

書籍「リーダブルコード」ではこれもアンチパターンとして紹介されていたような気がします。
私の先輩も避けるべきと言っていました。
goto文は、ラベルの付いたところまで処理を移動させる制御文。ループ処理に似ていますが、ちょっと違います。
[goto文 - Wikipedia](https://ja.wikipedia.org/wiki/Goto%E6%96%87)

ちなみにこれは専門学校でも習った気がするのですが、ノートに取ってなかったのか。。。

私はPHPerなのですが、PHP 5.3（2009年リリース）から導入されました。当時は今更なぜ？って感じでした。

その後、EC-CUBE案件をやったときにどれかは忘れましたが、プラグインの一つにgoto文が使われていました。
「嘘やろ・・・」と言ったことを覚えています。

# まとめ

どんなプログラムにも、多かれ少なかれジレンマが存在していると思います。
過去の自分のプログラムを見て、「今ならもっとシンプルに作れるな・・・」、と思いながらも、デバッグも終わって安定稼働しているものを大きく変更するのは、それだけでリスクになります。
他人が書いたプログラムならなおさらです。

だからせめて、これから各プログラムは、気をつけていきたい。
そう思いながらプログラムを書いています。