オブジェクト指向

オブジェクト指向は 人 である ~オブジェクト指向を簡単に理解しよう~

意味がわからないようなタイトルで始まりましたが、

オブジェクト指向って一体何?

って言われた時に自分が説明しているものをまとめてみます。
正直オブジェクト指向という言葉の定義なんて人それぞれなところがあるので、
こういう風に考えている人もいるんだなーぐらいに捉えてもらえると助かります。

オブジェクト = 人である

オブジェクトっていうから例えがわかりにくいものになるのかなって思っています。

よくある例え



ハンドル, タイヤ, ボディ, エンジン

よくありますよね、こういう例え。
変数は?メソッドは?どういうことになるの?
これだとなかなか伝わりにくい気がしています。

オブジェクト = 人 として扱う

車にはもはや例えません。

自分に頼れる知り合いがいたとして、その人に対して、「○○しといてねーお願いします。」
って言うと後はいい塩梅にやってくれます。
そういうことってありますよね。

そのイメージでクラスを設計します。
じゃあ例えば、去年送った相手にお歳暮を出す行為として例えます。

(悪い例)去年送った相手にお歳暮をひとりで出せる人

(ダメなパターン)

ひとつのクラスで書いてしまうパターンのことです。

お歳暮をひとりで送るくらいは当たり前な話です。
ですが、それをプログラムとして書くとなると複雑になります。

お歳暮を送る行為を一つのクラスで書いてしまいます。
名前はそうですね、OseiboManager とでもしましょうか。

OseiboManager
public class OseiboManager {
  public void buyOseibo() {
  }
  public void postOseibo() {
  }
}

上記のような感じです。でも待って。
お歳暮を出すにも色々考えないといけません。

  • お歳暮は誰に出す?
    • 去年の宛先のリストが欲しい
      • 相手の住所が欲しい
    • 相手は何が好きなんだっけ?
  • お歳暮はどこの店で買う?
    • ネットで買う?
      • どんなお店がネットにある?
  • いつに届くように出す?
    • カレンダー見ないとね。

実は考えることいっぱいです。
これだけの内容をひとつのクラスに書くと、、
行数が何行あっても足りませんよね。
あと、わけがわからなくなって、十中八九、品質が悪いコードになってしまいます。

ダメ、ゼッタイ!

(良い例)役割を複数の人に分散してしまおう

それぞれ上記でやりたかったことに 人 を設定していきます。
まず、宛先を決めてくれる人。

この人は去年送った人が誰か知っています。
住所も知っています。
名前と住所と好きな嗜好品や食べ物までリストアップしてくれて出してくれます。

そして名前と住所の履歴、管理方法をどうしているかや住所の暗号化してたり、なども
勝手にやってくれています。

外の人からは「今年は誰に送ればいい?リスト頂戴。あと、何が好きだったか教えて!」

それをプログラムにすると以下の感じです。

宛先を管理する人のクラス
// 宛先を管理するクラス
public class DestinationManager {
  // 住所と名前、好きなもののリストをもらうメソッド
  public List getdestinationList(){
  }

  // 送った履歴や、住所と名前の管理方法は private で隠蔽されています。
  // その人は知る必要がないからです。うまい具合にやってくれています。
 private ~~~
}

さて、ここで暗号化やデータの管理方法もそれなりに手間がかかるよ。
DestinationManager もいっぱいになっちゃうよ。っていう展開がどこかで来ます。

そうすると、また 暗号化だけをする人、住所と名前の管理だけをする人 を作るのです。
その上で宛先を管理する人がいる状態になります。

宛先を管理する人たちのクラス
// 宛先を管理するクラス
public class DestinationManager {
  // 住所と名前、好きなもののリストをもらうメソッド
  public List getdestinationList(){
  }

  // 送った履歴や、住所と名前の管理方法は private で変数として持ちます。
 private EncryptManager encryptManager;
 private DestinationInformationManager destinationInformationManager;
}

// 暗号化をするクラス
public class EncryptManager {
  private const String ENCRYPT_TYPE = "AES";
  public String encrypt(source){
  }

}

// 住所と名前を管理するクラス
public DestinationInformationManager {
  private String dataStoreName;
  private String dbConnectionInformation;
}

宛先を管理する人を頼る人は、実は中に 暗号化だけをする人、住所と名前の管理だけをする人 が
いることを知りません。でも使えます。
そうすることで、クラスの責任範囲を分割し、疎結合にすることができます。

ほかのクラスも同様

  • お歳暮はどこの店で買う?
  • いつに届くように出す?

こちらに関しても

  • お歳暮を上手に買う人 OseiboBuyer
  • ベストタイミングお届け人 BestTimingDeliver

のようにクラスを作って、外から扱うだけです。

お歳暮を上手に買う人とベストタイミングお届け人のクラス
public class OseiboBuyer {
  public void buy(){
  }
}

public class BestTimingDeliver {
  public void deliver(){
  }
}

人を利用する

では最初にいた人を持ってきます。
でも名前が変わっています。

去年送った相手にお歳暮をひとりで出せる人
去年送った相手にお歳暮を出せる人

この人に対して、メイン処理から
「送っといてよ!」って伝えるだけで終了です。
あとは内部の人と協力して色々やります。

去年送った相手にお歳暮を出せる人のクラス
public class LastYearOseiboDeliver {
  // それぞれの頼る人をクラスに持ちます
  private DestinationManager destinationManager;
  private OseiboBuyer oseiboBuyer;
  private BestTimingDeliver bestTimingDeliver;

  // 更に外から送る処理を呼ぶだけです。
  private void post(){
    // 他のクラスと連携していい塩梅に送ってくれます。
  }
}

 

まとめ

クラスが行う仕事を 人 に例えて分割することで、
「やっといてねー」「できたよー」っていう感じでなんとなくイメージがつきやすくなります。

これがオブジェクト指向でいう、 メッセージ

頼む人の中に、また実は頼む人がいた。でも意識する必要はない。
これが隠蔽されることでシンプルに扱うことができます。

これがオブジェクト指向でいう、カプセル化

だったりします。

こんな感じで理解すると、簡単に思えるんじゃないかなー・・?
画像作るのがめんどくさいし文章だらけなので、簡単じゃなかったらごめんなさい。笑


他にも、抽象化やポリモフィズムみたいなことはあるけど、
それは上記の考えが理解できた上の話なので、
次の段階、Step2 で理解することがおすすめです。


あと XXXXManager って命名するクラスも本当はあまり良くないです。
実際はもっと具体的な名前をつけることをおすすめします。
今回は例として書いた感じです。