はむはむエンジニアぶろぐ

このブログのコンセプトは"ハッキングの為なら愛する家族を傷つけることをいとわない" 自分にとってエンジニアリングは "手段ではなく生きる目的" である

Tell, Don't Ask [ 求めるな、命じよ ]

f:id:secret_hamuhamu:20150816222337j:plain
Tell, Don't Ask は、オブジェクト指向プログラミングのよいとされる考え方の一つです。
Tell, Don't Ask は、日本訳で 求めるな、命じよ と訳されているのが、多いみたいですね。

オブジェクト指向というのは、役割を思ったオブジェクト同士が協力(コラボレーション)しながら機能(価値)を提供する。
オブジェクトが持つ役割が、あいまいだと良い設計と言われている 凝集度が高く結合度の低い ものは出来ません。

その為に、必要な考え方の一つなのが Tell, Don't Ask [求めるな、命じよ] である。
求めるな、命じよって言われてもピンきにくいですよね(´・ω・`)w
シーケンス図とか書いてみて、解説します。

Tell, Don't Ask

Tell, Don't Ask とは、 Ask ではなく Tell しなさいというものです。
オブジェクトAが、オブジェクトBを呼び出す際、求める(Ask)のではなく命じる(Tell)という考え方である。
では、どういう状態が Tell で、 Ask なのか?

服を購入しに来た客店員 のやりとりをシーケンス図にして例えてみる。

Ask

Askは、求めるというより尋ねると訳した方が自分的にはしっくり来ます。

シーケンス図

f:id:secret_hamuhamu:20150823215621p:plain

シーケンス図を見て分かる通り、 服を購入しに来た客 が、何度も在庫確認するために Ask(尋ねる) しなければならない。
つまり、やりとりが多い。
何故、やりとりが多くなるのか?それは、 在庫 に関する役割が、混同しているからである。
服を購入しに来た客在庫確認ロジック を持ち 店員 が、在庫データ を持っている。

Ask形式をPHPでコードにして書くとこうなる。

コード

<?php
// 店員
class AskSeller
{
    /**
     * 在庫数を返す
     * @param $clothesType string 服の種類
     * @param $color       string 服の色
     * @return 在庫数
     */
    public function getStock($clothesType, $color)
    {
        // ロジックは割愛
        return $stock;
    }

    /**
     * 服を販売し、販売価格を返す
     * @param $clothesType string 服の種類
     * @param $color       string 服の色
     * @return 在庫数
     */
    public function buy($clothesType, $color)
    {
        // ロジックは割愛
        return $price;
    }
}



// 服を購入しに来た客
$askSeller = new AskSeller();

// 緑のワンピースの在庫はある?
$greenStock = $askSeller->getStock('one-piece', 'green');
//在庫確認ロジック
if (count($greenStock) > 0) {
    // 在庫があれば、購入する
    $price = $askSeller->buy('one-piece', 'green');
} else {
    // 赤のワンピースの在庫はある?
    $redStock = $askSeller->getStock('one-piece', 'red');
    //在庫確認ロジック
    if (count($redStock) > 0) {
        // 在庫があれば、購入する
        $price = $askSeller->buy('one-piece', 'red');
    }
}


Tell

Tellは、 命じよ である。
命令するのみ。
服を購入するための在庫確認ロジックを 店員 に移す。

シーケンス図

f:id:secret_hamuhamu:20150823215615p:plain

シーケンス図を見て分かる通り、 服を購入しに来た客 は、購入したい服を購入すると Tell(命ずる) だけでよい。
服を購入しに来た客 は、何を購入したいのか?どういう優先度で?ということを 店員 に命ずるのである。
つまり、在庫確認をしなくて良い。それは 服を購入しに来た客 の役割ではない。
在庫確認ロジック を、 店員 に持たせることで、 在庫 に関する役割を完全に 店員 に移すことが出来る。

Tell形式をPHPでコードにして書くとこうなる。

コード

<?php
// 店員
class TellSeller
{
    /**
     * 在庫数を返す
     * @param $clothesType string 服の種類
     * @param $color       string 服の色
     * @return 在庫数
     */
    private function getStock($clothesType, $color)
    {
        // ロジックは割愛
        return $stock;
    }

    /**
     * 服を販売し、販売価格を返す
     * @param $clothesType string 服の種類
     * @param $color       string 服の色
     * @return 在庫数
     */
    public function buy($clothesType, array $colors)
    {
        // 在庫確認ロジック
        foreach($colors as $color) {
            $stock = $this->getStock($clothesType);
            if ($stock > 0) {
                // 在庫あり (英語弱すぎてこの変数名が妥当か分からん
                $inStockColor = $color;
                break;
            }
        }
        // ロジックは割愛
        return $price;
    }

}

// 服を購入しに来た客
$tellSeller = new TellSeller();
// ワンピースを購入するわ。色の優先度は、緑, 赤の順番ね。
$tellSeller->buy('one-piece', ['green', 'red']);


まとめ

クラス図だけを見てこれは、 Ask してるぞ!って気づきにくいと思います。
なので、不吉な臭いを感じたらシーケンス図にしてみると Ask していることに気づいたりします。

他に Tell, Don't Ask を思い出すケースというか適用できるパターンとして、GetterやSetterを使用しないという考え方が、あります。
ThoughtWorksアンソロジー という良書の中で、紹介されています。

ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション

ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション

  • 作者: ThoughtWorks Inc.,株式会社オージス総研オブジェクトの広場編集部
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2008/12/27
  • メディア: 単行本(ソフトカバー)
  • 購入: 14人 クリック: 323回
  • この商品を含むブログ (81件) を見る

自明かもしれない: Getter や Setter を使わない

Getter/Setterを使用するのは、悪いことではないのですが本当にこのアクセサは必要なのか?考えてみるといいと思います。

参考

TellDontAsk
求めるな、命じよ

おすすめの本

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

  • 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
  • 出版社/メーカー: 翔泳社
  • 発売日: 2009/07/14
  • メディア: 大型本
  • 購入: 45人 クリック: 673回
  • この商品を含むブログ (152件) を見る

アジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技

アジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技

  • 作者: ロバート・C・マーチン,瀬谷啓介
  • 出版社/メーカー: ソフトバンククリエイティブ
  • 発売日: 2008/07/01
  • メディア: 大型本
  • 購入: 18人 クリック: 586回
  • この商品を含むブログ (71件) を見る