はじめに
今回は「読みやすいコードのガイドライン」という書籍の中で紹介されていた
定義指向プログラミング
について記事にしてみたいと思います。
その中でも今回は
ネストをローカル変数への抽出で解消する
このことについて記事にしてみようと思います。
なお上記の書籍はKotlinのコードで紹介されているのですが、
この記事ではそれをDartに変換しています。
定義指向プログラミングとは
導入として先ず最初に「定義指向プログラミング」について概略を示します。
先述の書籍の中では以下のように紹介されていました。
コードに高い抽象度を与えて再利用性を高める
斜め読みで概要が把握できるようなコードを書く
関数内での読み返しが少ないコードを書く
コードに高い抽象度を与えるとは...
- 使い回しが効かない長いコードやリテラルを切り出し、
- それに名前を与えることで意味を明示的に示し、
- かつ再利用可能なものにしていくこと
こういったことを指しています。
斜め読みで概要が把握できるコードとは...
- コードの一部を眺めるだけで関数内の処理の流れが掴めるコードのこと
- 式やステートメントの最初の方、ネストの浅いところ(コードの左側)に重要なコードを書く
- 式やステートメントの最後の方、ネストの深いところ(コードの右側)に詳細な部分を書く
こういったことを指しています。
関数内での読み返しが少ないコードとは...
- 上から下に向かって読んでいけば概要がすんなりと掴めるコードのこと
- そのためにも深いネストや巨大なローカル関数をリファクタリングしていく
こういったことを指しています。
上記のことを踏まえて以降のコードを見てみましょう。
ネストの解消前
最初に以下のコードをご覧ください。
showDialogOnError(
presenter.updateSelfProfileView(
repository.queryUserModel(userId)
)
);
上記はエラーダイアログ表示を実行するコードですが、
その実引数に二重のインラインメソッドをあてています。
このコードの問題点...
一重であればインライン化によるメリットもありますが、
これが二重以上になってしまいますとそのメリットも無くなり、
かえって可読性が下がってしまいます。。。
そもそも上記のコードは
repository.queryUserModel(userId)
この処理で取得したユーザーモデルをもとに
presenter.updateSelfProfileView
この処理を実行し、
その戻り値によりエラー時はエラーダイアログを表示させるようにしているのですが、
その意味が捉えづらくなっていますし、
インライン化したメソッドの定義元に飛ばない限りは
それらの実引数の型も明確にならないコードになっており、
全体的に見通しが悪いものになっています。。。
意図が不明瞭であり斜め読みが出来ず、
慎重にコードを追っていかねばならないケースが散見すると認知上の負荷も増しますし、
欠陥の元にもなりかねません😱
ネストの解消後
そこでこんな風にリファクタリングしてみましょう💪
final userModel = repository.queryUserModel(userId);
final viewUpdateResult = presenter.updateSelfProfileView(userModel);
showDialogOnError(viewUpdateResult);
このコードであれば意図も明示的であり斜め読みもできますし、
上から下に向かってコードを追っていけばいいだけなので認知上の負荷も低そうですし、
可読性やメンテナンス性が高そうですよね♪
上記のように実引数がネストしている場合はこんな手法も使えそうですよね☺️
まとめ
今回は定義指向プログラミングのうち、
ローカル変数への抽出によるネストの解消について記事にしてみました。
次回はプライベート関数への抽出によるネストの解消について
記事にしてみようと思います💪
参照