牛丼で分かるオブジェクト指向

# はじめに

今年もアドベントカレンダーはじまりました！
この記事はHamee Advent Calendar 2020の1日目の記事です。
Hameeのエンジニアが自分の興味あるテーマについて自由に書いていきます。
毎年一緒に参加して盛り上げてくれる皆さんに感謝です :clap:
今年で6年目の参加となりました！

# オブジェクト指向とは

僕の解釈ではデータを扱いやすいオブジェクト単位に設計し、それらを組み合わせることで効率よく開発をしていく指向のことだと思っています。
ただまぁ人によって解釈が違うし新卒や初心者にとっては「？？？」となることが多い考え方だと思います。
そこで、牛丼を例にオブジェクト指向を紐解いていこうと思います。

# なぜ牛丼？

Hameeは小田原にある会社です。
小田原には狭いエリアに牛丼チェーンが3つもあります。
この松屋・すき家・吉野家は日々Hamee社員の胃袋を支えています。
私も利用者の1人ですが、この3店舗のレシートの出方を見て今回の記事を書こうと思いつきました。

![スクリーンショット 2020-11-28 15.38.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/20778951-c717-14e1-74d9-0d05f212000d.png)

# これがその問題のレシート

![IMG_4494.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/8297e621-1b5c-beb0-0f9c-fcfccb9e3eda.jpeg)

左から松屋・すき家・吉野家
松屋「たっぷりネギたま牛めし」
すき家「牛丼弁当・ねぎ玉TP」
吉野家「牛丼・ねぎ玉子」

松屋は1品なのに対して、すき家と吉野家は2品でレシートが切られています。
ここにオブジェクト指向の違いがあります。
松屋は非オブジェクト指向、すき家と吉野家はオブジェクト指向です。

# どういうことかclassで説明

```php:Matsuya.php
class Matsuya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => new NegiTamaGyudon(),
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTamaGyudon{}

Matsuya::order('NegiTamaGyudon');
```

```php:Sukiya.php
<?php
class Sukiya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => [new Gyudon(), new NegiTama()],
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTama{}

Sukiya::order('NegiTamaGyudon');
```

以降吉野家はすき家と同様なので略
違いが分かりますか？
このままだと「え、こんなの作りの好みじゃないの？」って言われそうなので、ここから新メニュー開発した場合を想定しましょう。
エンジニア的に言うと「仕様変更」です。

# 新メニュー「キムチ牛丼」

```php:Matsuya.php
<?php
class Matsuya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => new NegiTamaGyudon(),
            'KimchiGyudon' => new KimchiGyudon(),
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTamaGyudon{}
class KimchiGyudon{}

Matsuya::order('KimchiGyudon');
```

```php:Sukiya.php
<?php
class Sukiya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => [new Gyudon(), new NegiTama()],
            'KimchiGyudon' => [new Gyudon(), new Kimchi()],
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTama{}
class Kimchi{}

Sukiya::order('KimchiGyudon');
```

まだ違いが分からない？
じゃあ次の新メニューはどうでしょう。

# 新メニュー「ネギ玉キムチ牛丼」

```php:Matsuya.php
<?php
class Matsuya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => new NegiTamaGyudon(),
            'KimchiGyudon' => new KimchiGyudon(),
            'NegitamaKimchiGyudon' => new NegitamaKimchiGyudon(),
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTamaGyudon{}
class KimchiGyudon{}
class NegitamaKimchiGyudon{}

Matsuya::order('NegitamaKimchiGyudon');
```

```php:Sukiya.php
<?php
class Sukiya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => [new Gyudon(), new NegiTama()],
            'KimchiGyudon' => [new Gyudon(), new Kimchi()],
            'NegitamaKimchiGyudon' => [new Gyudon(), new NegiTama(), new Kimchi()],
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTama{}
class Kimchi{}

Sukiya::order('NegitamaKimchiGyudon');
```

ここで大きく異なるのはすき家の方は新しくクラス定義を追加していません。
既存のクラス（オブジェクト）の組み合わせで簡単に新メニューが作成できます。
それに対して松屋はどんな新メニューができても必ずクラス（オブジェクト）を追加する必要があります。
新メニュー開発はどちらが楽でしょう？
とどめにこんな新メニューはどうでしょうか。

# 「豚丼」追加、もちろん全トッピング可

```php:Matsuya.php
<?php
class Matsuya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'NegiTamaGyudon' => new NegiTamaGyudon(),
            'KimchiGyudon' => new KimchiGyudon(),
            'NegitamaKimchiGyudon' => new NegitamaKimchiGyudon(),

            'Butadon'        => new Butadon(),
            'NegiTamaButadon' => new NegiTamaButadon(),
            'KimchiButadon' => new KimchiButadon(),
            'NegitamaKimchiButadon' => new NegitamaKimchiButadon(),
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class NegiTamaGyudon{}
class KimchiGyudon{}
class NegitamaKimchiGyudon{}

class Butadon{}
class NegiTamaButadon{}
class KimchiButadon{}
class NegitamaKimchiButadon{}

Matsuya::order('NegitamaKimchiButadon');
```

```php:Sukiya.php
<?php
class Sukiya {
    public static function order($order){
        $menu = [
            'Gyudon'         => new Gyudon(),
            'Butadon'        => new Butadon(),
            'NegiTamaGyudon' => [new Gyudon(), new NegiTama()],
            'KimchiGyudon' => [new Gyudon(), new Kimchi()],
            'NegitamaKimchiGyudon' => [new Gyudon(), new NegiTama(), new Kimchi()],
            'NegiTamaButadon' => [new Butadon(), new NegiTama()],
            'KimchiButadon' => [new Butadon(), new Kimchi()],
            'NegitamaKimchiButadon' => [new Butadon(), new NegiTama(), new Kimchi()],
        ];

        return $menu[$order];
    }
}

class Gyudon{}
class Butadon{}
class NegiTama{}
class Kimchi{}

Sukiya::order('NegitamaKimchiButadon');
```

松屋はメニュー分のクラスが増えましたがすき家は豚丼クラスを追加しただけです。
これがオブジェクト指向です。
オブジェクトを使い回せる点が非常に強いです。
このあと鶏丼や羊丼が来ても簡単に対応できます。

ちなみに小話ですが、すき家と吉野家には豚丼がありますが、松屋にはありません。

# まとめ

結構無理やり話をまとめたので異論はあると思いますがどうか温かい目で見ていただけるとｗ
少しでもオブジェクト指向の理解の助けになれば幸いです。


# おわりに

アドカレ6年目です。
毎年この時期になると「あぁもうそんな時期か、1年って早いなぁ」と実感します。
この後もHameeのアドカレをお楽しみに！

ちなみにどのお店の牛丼もそれぞれ違った美味しさがあって、全部大変美味しかったです！
（撮影後はスタッフが美味しくいただきました。）

![IMG_4492.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/f7110cc6-d901-610a-9ebc-88fa1c499258.jpeg)