概要
ターゲット
- 「コーディングでは、うまく関数分けた方がいい」と聞いたが、具体的にどうすればいいかわからない初心者
ゴール
- 関数を分けるとき、「初めはこういうのを考えるといいらしい」という情報を共有する
- ひとまず「関数を分ける」を始められる、試せるという状態を目指す
- なお、自分がつまずいたときに、ひとまず試せそうだと感じたものの紹介が中心です
- 有用かは自分も試している段階です…
備考
- 初心者の経験上の理解が中心なので、より高度な解決案や根本的な方法論については別記事を参照ください
分けないと何が問題なのか
- 関数を分けないと、以下のような問題がでる
- 関数が長いせいで、一部分修正しただけで全体の動きがダメになってないか不安になる
- 関数がしていることや責任範囲が、すぐ分からなくなる
- 関数が複数のことをしていて、テストケースが考えにくい
どんな方針で分けていけばいいのか
方針
- いきなり多くのことを考えられないので、2つの原則に絞って考える
関数化の基本は、
・コーディングしていて同じ処理が出てきたら関数化して使いまわす
・関数が肥大化してきたら分割してサブ関数化する
なぜこの2つなのか
- 先に挙げた「問題」の原因である以下の2つに対処できるから
- 原因1:1つの関数で、とにかく色々なこと(複数の処理)を行っている
- サブ関数化することで短く分割する
- 原因2:同じ1つの処理を、複数の関数に書いている
- 共通部分を関数化することで、まとめる
- 原因1:1つの関数で、とにかく色々なこと(複数の処理)を行っている
理想
- 理想的には、多くのひとが共有している以下の3原則を実践できるのが好ましい
コードを書く時の3原則
・KISS(Keep It Simple Stupid) : コードはstupidな位シンプルにしろ
・DRY(Don’t Repeat Yourself) : 繰り返しは極力避けろ(1つの使い回せるファンクションにまとめる)
・YAGNI(You Aren’t Gonna Need It) : 今実際に必要なコード以外は書くな
関数の分け方3パターン
- さらに、原則だけでは実践に落とし込めないので、実践パターンを探してみた
- 以下の項目に注目すると、うまく関数を分けられそう
ロジックとI/Oで分ける
- ソース
- これだけは覚えたい、ユニットテストを書くための4つのデザイン - Qiita
- 最近の単体テスト (p.49-)
- Clean Code
- 1つの関数に1つの抽象レベル
- なぜこの観点で見るか
- ロジックは「処理の流れ」で、I/Oは「実際の処理」なので、まとめると関数が複数のことをしている状態になってしまうから
a_and_b()みたいな関数をロジックとa()とb()にわける
- ソース
- Clean Code
- 副作用を避ける
- Clean Code
- なぜこの観点で見るか
- 関数に名前をつけるときに「複数の仕事をしている」と気がつけるから
- 例えば
- 関数の名前の付け方で悩んで、中身を見たら2つのことをしていたとき
- 関数に名前を付けてみたら、execute_and_return()となったとき
- 例えば
- 関数に名前をつけるときに「複数の仕事をしている」と気がつけるから
6行くらい書いたら変える
- ソース
- なぜこの観点で見るか
- 大体、新しい処理を書いているから
- コメントで長い補足を書き始めたときも、その補足を関数名にしてくくりだすことを考える機会にする
以上