LoginSignup
1

More than 3 years have passed since last update.

オブジェクト指向ベストプラクティス(個人学習用)

Posted at

初めに

ズブズブの素人の私ががクラスをを設計できる様に学習を進めていきます。
オブジェクト思考を理解しながら、独立性の高いクラスを構築を目指す。
個人学習目的なのであまり参考にはならない可能性があります。

目指すクラス設計とは

  • 直感的に理解しやすいもの
  • メンテナンスが少ない設計また、変更点があっても他のクラスに影響がない設計
  • 凝集度は高く
  • 結合度は低く

このことから依存関係が少ないクラス設計が望ましいと考えられます。1つのクラスをメンテナンスをすると他のクラスに影響が及ぼしていてはメンテナンスの困ってしまう訳です。
スパゲッティコードを防げ!!→キーワードは「カプセル化」と「多様性」

classの中身を隠蔽化する

例えばお寿司屋さんとお客様がいるとします。
ここではお寿司屋さんの対象がclassとし、お客さんがメインルーティンとします。
お客さんは寿司ネタのオーダーをすると、寿司屋の大将がお寿司を握ってくれる(method)お寿司を提供してくれます。
お客さんはオーダーさえすれば、後は握り終えてお寿司の提供を待つだけです。
この時、お客さんはこの「ネタは握り方をこうしてくれ」、「酢飯の酢の割合はこの程度にしてくれ」とオーダーされても大将は受け付けてくれません。それは大将の独自の経験や技術があるからです。その為、お客さんのオーダーは聞きますが、作成方法などは要求は聞きません。

ここまでで振り返ると
お寿司をオーダーする→publicメソッド
 握り方      →privateメソッド
 酢の割合     →privateメソッド
という風に情報や振る舞いを隠蔽かしているのです。

Untitled Diagram-ページ2 (3).png

ここではアクセスして欲しくないものを隠蔽していますが、これらを一つのclassのまとめたものがカプセル化です。

カプセル化がうまいとコードの見通しがよくなる
実際の例をみてみると

見通しが良い例
$sushiya = new Sushiya();

$sushiya = make_sushi('Tuna');
見通しが悪い例
$sushiya = new Sushiya();

$sushiya = createSumeshi();
$sushiya = cutFish();
$sushiya = holdSushi();

この様に目的に着目しておらず、手段に重点が置かれている。これではコードの肥大化をうむ。また今回は単純な内容ですが、これでは何を目的にしているのかがわかりにくいです。その点良い例では一目で目的がわかります。これが後者が隠蔽化ができていないことが原因となります。これをアクセス修飾子を調整することで理想的なカプセル化ができるはずです。

classの凝縮度

classがclassに与えられた役割にどれだけ集中しているかを示す尺度を凝集度という。
凝集度が高ければclass間の依存関係は低くなります。
class名と関連するmethodのmissmachをなくそうということです。
例えば、MailSendクラスがあり、そこにsemd(),checkMailAddress(),resaizeImage()があったとします。
この場合send()はメール送信、checkMailAddress()はバリデーション機能,resaizeImage()は画像をリサイズする機能となっておりMailSenderクラスに本質的にはcheckMailAddress(),resaizeImage()は関連しているとはいえません。
それならばそれに関連するImageCoverクラスやValidaterクラスを作成し、そこに上記のメソッドを格納して上げる方が、役割分担が明確でクラスでのメソッドやプロパティの関連性も明確になります。

Untitled Diagram-ページ2 (4).png

凝集度が高いとメリットがたくさんる
例えばNetRadioクラスがありそこにプロパティとして現在時刻、再生中のチャンネル、文字色、背景色 メソッドとして再生する、時刻表示するがあったとするとここでクラスに関連し本質は「ラジオ放送を聞くということ」なので上記と一緒でクラスの切り分けがを行うことが良いでしょう。
Untitled Diagram-ページ2 (5).png

切り分けを行い凝縮度を高めたいきます。そうすると今度はMyNetRaidoAppと行ったクラスを作成しカスタマイズができます。

Untitled Diagram-ページ2 (6).png
こうすることで以下のメリットがあります

  • MyNetRaidoAppクラスの機能更新がしやすくなる。また時計機能がを削除しても他の機能やクラスに影響がない
  • MyNetRaidoApp以外のクラスにも機能を移植できる。
  • NetRaido ,Clock, DesignRTmplateクラスは独立しているので1つのクラスに対する変更があっても影響がない。

この様にクラスの凝縮度を高めると保守性が高まりますが、過度にクラスを細分化しすぎるとプログラムファイルを探すにの時間がかかってしまったりするので、ある程度の匙加減は必要です。

classの結合度

クラス間の結合度は低い方が良いです。結合度が高ければ、1つのクラスに何か修正を行った場合関連するクラスに影響を及ぼすからです。

結合度が高くクラス間の依存関係が強い場合
クラスの関連性が循環しているパターン
Untitled Diagram-ページ2.png

結合度が低いクラスの関係
関係性が一方方向である。
Untitled Diagram-ページ2 (1).png

終わりに

上記のことを意識してクラス設計を行っていきます。
また今後もアップデートしていきます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1