オブジェクト指向から学ぶ、思春期の子供とのコミュニケーション「Tell, Don't Ask」原則

# はじめに
:christmas_tree::christmas_tree::christmas_tree::santa_tone1:メリークリスマス:santa_tone1::christmas_tree::christmas_tree::christmas_tree:
皆さんは、この特別な日をどのように過ごす予定でしょうか？
私は家族と共にこの聖夜を楽しみながら:cake:、
日々のコミュニケーションについて考え:thought_balloon:を巡らせています。

<br>
思春期:boy_tone1::girl_tone1:の子供を持つ親御さんにとって、子供とのコミュニケーションは一筋縄ではいかないことが多いですよね。
子供の成長に伴い、親としての接し方も変化させなければならない瞬間があると思います。

そんな私たちにオブジェクト指向プログラミング（以下、OOP）の基本原則の一つである「```Tell, Don't Ask```」で解決することが可能かもしれません。

世の中のお母さん、お父さん、特にお父さん方（私自身がお父さんなので）、この記事は必読です。
煙たがられる存在から、尊敬される父親になれるチャンス！です。
※これから展開されるコードは<ins>実体験を表したものではなく、フィクションであり、事実に基づかない場合が多々あります</ins>

## こんなことありませんか？
- 子供にアドバイスをしようとして、逆に反発:rage:を買ってしまう。
- 子供の話を聞く前に、すぐに自分の意見:speech_balloon:を述べてしまう。
- 子供が「ウザっ！:weary::thumbsdown:」と感じるほど、口うるさくなってしまう。

こういった問題は、多くの家庭で共通していると思います。

## これをコードに書くとこんな感じでしょうか？
子供が部屋を綺麗にしていることと、勉強を確認するシーンを考えてみましょう。
これは多くの家庭で見られる光景ですよね。

```java:Parent.class
class Parent {
    public void forceRoomCleaningAndStudy(Teenager teenager) {
        if (teenager.isRoomMessy()) {
            System.out.println("部屋が散らかってるね。いつ片付けるつもり？今すぐ片付けなさい！");
            teenager.cleanRoom();
        }
        System.out.println("掃除が終わったら、勉強もしなさい。");
        teenager.study();
    }
}
```
```java:Teenager.class
class Teenager {
    private boolean roomMessy;

    public Teenager(boolean roomMessy) {
        this.roomMessy = roomMessy;
    }

    public boolean isRoomMessy() {
        return roomMessy;
    }

    public void cleanRoom() {
        System.out.println("部屋を片付けるよ...（はぁ、めんどくさっ）");
        roomMessy = false;
    }

    public void study() {
        System.out.println("勉強もやるね...（ダルぅ...）");
    }
}
```
ParentクラスがTeenagerクラスの部屋が散らかっているかを確認（ask）しています。
また、Teenagerクラスの内部状態（部屋が散らかっているかどうか）に依存しており、
子供に部屋の片付けと勉強を一方的に命じています。

## 「Tell, Don't Ask」原則とは？
:::note info
オブジェクトが他のオブジェクトの内部状態を問い合わせる（ask）のではなく、
何をすべきかを指示（tell）するべきだという考え方です。
※Martin Fowler氏のサイトを読むと理解がより深まると思います。
https://martinfowler.com/bliki/TellDontAsk.html
:::

これを家庭でのコミュニケーションに応用すると親が子供に対して指示や命令をするのではなく、
子供に自分自身の考えや感情を表現する機会を与え、それに基づいてサポートすることを意味します。


## 改善案
```java:Parent.class
class Parent {
    public void proposeOrganizedRoomAndStudyPlan() {
        System.out.println("部屋をきれいにすると気分も新鮮になるよ。それと、今後の勉強の計画はどうする？");
    }
}
```
```java:Teenager.class
class Teenager {
    private boolean roomMessy;
    private boolean wantsToEnjoySNS;

    public Teenager(boolean roomMessy, boolean wantsToEnjoySNS) {
        this.roomMessy = roomMessy;
        this.wantsToEnjoySNS = wantsToEnjoySNS;
    }

    public void decideCleaningAndStudyPlan(Parent parent) {
        parent.proposeOrganizedRoomAndStudyPlan();
        if (roomMessy) {
            System.out.println("部屋はちょっと散らかってるけど、後で片付けることにするよ。");
        } else if (wantsToEnjoySNS) {
            System.out.println("まずは少しSNSをチェックしてから、勉強を始めるよ。");
        } else {
            System.out.println("部屋も綺麗だし、勉強を始める時間だね。");
        }
    }
}
```
この改善されたコードでは、ParentクラスがTeenagerクラスに部屋を整理することのメリットと、
それを行った後の勉強計画についての提案をしていますが、
最終的な決定はTeenagerクラスに任せています。
一方でTeenagerクラスは自身の現在の状態に基づいて次の行動を選択することができます。

これにより、子供の自主性が尊重され、親子間の健全なコミュニケーションが促進されます。
これは「```Tell, Don't Ask```」原則に沿っており、子供の自立性と親の適切なサポートを示しています。

## さらにBADコードを書くと
常にParentクラスはTeenagerクラスの状態に合わせて指示を出さないといけません。
これは手続型のプログラミングっぽいですね。

また、Teenagerクラスは値を保持するだけでビジネスロジックがないため、
ドメインモデル貧血症の傾向が強いです。

:::note info
ドメインモデル貧血症とは、オブジェクトが単にデータを保存し、取得する機能（例：getter,setter）しか持たず、ビジネスロジックがない状態です。
:::

```java:Parent.class
class Parent {
    public void checkAndAct(Teenager teenager) {
        if (teenager.isRoomMessy()) {
            System.out.println("部屋が散らかってるね。いつ片付けるつもり？今すぐ片付けなさい！");
            teenager.cleanRoom();
        } else if (teenager.needsToStudy()) {
            System.out.println("勉強の時間だよ。勉強しなさい！");
            teenager.study();
        } else if (teenager.usingSNS()) {
            System.out.println("SNSはやめなさい。");
            teenager.stopUsingSNS();
        }
        // 他にも様々な条件とアクションが追加される可能性がある
    }
}
```
```java:Teenager.class
class Teenager {
    private boolean roomMessy;
    private boolean needsToStudy;
    private boolean usingSNS;

    // コンストラクタ、getter、setterは省略

    public void cleanRoom() {
        System.out.println("部屋を片付けるよ...（はぁ、めんどくさっ）");
        roomMessy = false;
    }

    public void study() {
        System.out.println("勉強を始めるよ...（はぁ、めんどくさっ）");
        needsToStudy = false;
    }

    public void stopUsingSNS() {
        System.out.println("SNSをやめるよ...（ガチでウザい）");
        usingSNS = false;
    }
}
```
こんなことは絶対にしないでくださいね:construction:
嫌われるだけでなく、最悪の場合シカトされますよ:cry:


# おわりに
「```Tell, Don't Ask```」原則を家庭でのコミュニケーションに応用することで、親子関係はより良いものになります。

子供が自らの考えを表現し、親がそれを尊重することで、相互理解と信頼が築かれます。
※上司、部下の関係も同じですね:grin:

プログラミングの原則が私たちの日常生活にもたらす前向きな変化を、是非体験してみてください。

少し早いですが、皆さん、今年も一年お疲れさまでした！:sake: