読みやすいコード(僕にとって)

最近気づいたことがある。それは、僕はみんなみたいに複雑なことが理解できない、ってこと。

話をしてても「ごめんなさい。いまのわかんなかった。もう一回教えて欲しい。」とかよくあるし。ドキュメントも、ちょっと複雑なことが書いてあると、全然頭に入ってこない。

色んなルールがドキュメントに書いてあって、それをちゃんと守りながら開発してる人たちとか見てると、みんなすごいなぁって思うのであった。

なんだろうなぁ。こう・・・色んな想像が始まってしまって、考えが落ち着かないんよね。

そんな僕なのだけど、ここ数年はありがたいことに色んなコードを読む機会がある。読みやすいコードもあれば、パズルみたいに複雑なものもあって。そんな中で、たぶん、僕にとって読みやすいコード、というのは普通の人にとってはとても読みやすいコードなのかなぁって思って。書いてみる。

JavaでWebのアプリを開発してる。基盤とかフレームワーク側じゃなくて、それを使う方のコード。

適切な・統一的な名前がついていること(Ubiquitous Language)

変数とかクラス名とかメソッド名とかそういうのに適切な名前がついてると読みやすくて嬉しい。3,4行の処理に名前をつけてメソッド化したりしてるとすごく読みやすい。欲を言えば、それが仕様書でも同じ名前が使われてて、さらに喋るときもその名前で会話ができてると、隠された概念にもすぐ気づけていい。

ひとつのことだけをやってる(SRP)

僕が混乱し始めるしきい値がある。それは「3」。3つ以上のことを同時に考え始めると。ぷしゅーってなる。

ひとつ、というのは心が落ち着く。コントローラーは入力値のチェックだけを。ユースケースは機能を実現することだけを。プレゼンターは結果をビューに返すことだけを。やってくれていると幸せ。2つ以上のことをやると、片方の処理には関係ないものもまざってきて、それがこの処理に必要だからあるのか、もう一つの処理のためのものなのか。3つ以上になると、最初におぼえていたものが、溢れて消えていく。ので、ひとつのことだけをやってるクラスやメソッドが好きです。

イミュータブルである

イミュータブルだと心が落ち着く。だって、もう変更されることがないんだもの。最初に完璧な形になってるとか幸せ。setterがあると混乱する。い、いったい、いつこのsetterは呼び出されるんだ!?ってドキドキしながら読むことになってつらい。LocalDateやBigDecimalは好き。Value Objectの集まりは、いくつあっても安心していられる。

使いまわされない(final)

ひとつの変数が使いまわされて、色んな役割を担っていると、つらい。しっかりその都度ちゃんと適切な名前がついた変数が使われていると嬉しい。

必要かもしれないからってコードは必要ない(YAGNI)

使われていなさそうなコードがあると、誰がどんな風に使っているのかを探して回ってしまう。そのせいで、読みにくくなっていたり、余分な処理をしていたり、余分なテストをしていたりする。「将来的に必要になると思うから今入れておく」ってのは、使われないことが多いし、むしろ、そのときやりたいことの邪魔になったりするし、全然いいことない。「将来的に必要になる機能に備えて拡張ポイントを用意しておく」くらいまでで僕のキャパは限界である。

継承よりも実装や委譲

フレームワークとかで、継承を上手に使ってるなぁって思うときはあるんだけど。そのフレームワーク上で業務をコードに表すときに、継承ってつらい。抽象クラスも苦手。なんだろう?処理が飛び飛びになることとか。クラスの完全性みたいなものが壊れそうで怖いとか。そういうの。

継承じゃなくて、インターフェイスを実装する、って感じなら、全然気持ちが楽。インターフェイスで他のコンポーネントと話をするのがいいな。でも、複数のクラスで共通の処理を持ちたいときとかあって、そういうときは委譲を使うと読みやすくて好き。

処理の共通化じゃなくて意味の共通化

オブジェクト指向を勉強し始めると、似たようなコードは全て共通化し始めてしまうもんなのかな。意味とかコンテキストが全然違うのに「やってる処理が同じだから!」ってまとめてしまうと、ここを変更したいんだけど・・・影響範囲がが・・・。とかなって、結局他に影響しないようにって、ifを書いてしまうようになったりしてつらい。

共通化は、意味の塊での共通化がいいな。インターフェイスを経由して話ができる感じ。その向こうの実装を気にしなくていいような感じ。

関係のあるクラスを近くに

たまに、ひとつの処理をレイヤー分けしてるコードを見る。横に切ってる感じ。ビジネスロジックレイヤーが複数あったりするとだいぶつらい。一つの処理を理解するのにレイヤーを行き来しないといけない。それよりも、ひとつの機能を実現するためのクラス群が同じパッケージ内にあると嬉しい。

今日思いつくのはこんなところかな

適切な名前がついていて、ひとつの役割だけを担っていて、イミュータブルにできるものはイミュータブルになっていて、変数はfinalで、継承よりインターフェイスに対してコードを書いていて、処理じゃなくて意味が閉じ込められていて、関係のあるクラスが近くにまとまっていると、僕にとって読みやすいコードなので、みんなにとってはもっと読みやすいのかなー。

って思った。

あ、あと、型安全になっている。もだな。