もぎーです。最近一気に寒くなりましたが皆さんお元気でしょうか。
自宅ではついにエアコンを稼働させて(一緒にサーキュレーターとかつけると足元も暖かくていいです)ぬくぬくと過ごしています。

今回は仕事してて少し思うところがあったので簡単に「もしクラス設計について知らない、考えたことがなかった人」に考えてもらうきっかけになってもらえればなと思ったのでこの内容で書きます。

この記事は経験3年以下とかで、かつ一部の人向けです。

まずはじめに

最近なにがあったのかというとディレクトリ、ファイル構成やクラス設計があまりされておらず同じ処理がいたるところにあったり責務がわけられていなかったりしていてなかなか手強いプロジェクトがありました。

(といっても残念ながら仕事なので、様々な要因により理想とはかけ離れた作りとなる(なっている)ことは多々あるかと思います。。)

とはいえそんな中でもできることはあったり、特にそれを「知っていること」、「自分の中である程度考えがついていること」は重要なことなので考えるきっかけにしてください。

以下では「ディレクトリ、ファイル構成やクラス設計があまりされておらず同じ処理がいたるところにあったり責務がわけられていなかったり」した場合の問題点を記載しておきます。

問題1:同じ処理が複数箇所に点在しているためコードが見にくい

この問題があるとファイル内に必ずある無駄な行が増え、ファイルの見通しが悪くなります。

そうなると可読性の低下によりソースコードのメンテナンスが大変になったり、本当に全く同じ処理なのか?と疑心暗鬼になったり弊害が出ますね。

これに対してはクラス等に処理を持たせて、呼び出しでも継承でもインターフェースでも利用して必要に応じて利用できるようにしてあげればいいですね。

問題2:共通処理が仕込めない

エラーハンドリングや、DBConnectionなど、それぞれのファイルで処理すべき内容ではないものが点在しているので、機能によって同じ動作をさせたい時にそれぞれのファイルに処理を書いていくのは冗長(もちろん、コピペしたソースコードのテストもしなければいけなくなります)でメンテナンスが難しいです。

これも問題1と同じ対処法でいいですね。

問題3:責務の所在が不明瞭でどこに処理を追加すればいいかわからない

例えば、モデルの概念がないプロジェクトではどこにそのモデル特有の処理を書けばいいのでしょうか。

消去法で呼び出し側のファイルになりますね。

この時点で呼び出し側がモデルの責務を負うことになりますので、呼び出し側のクラスやファイルでは、そのモデルの振る舞いを保証する必要が出てきます。

例:処理Aが、Bというモデルを更新する際、Bのモデルが持つCとDを同時に変更する
これを処理Aで記載すると、そのモデルに同じような、でもほんの少し違う処理を書きたい場合コピペしてちょっと変更するしかなくなります。こうしたことを繰り返すと難解なソースコードになり、規模が膨れ上がった際の各処理の修正、改修コストが必要以上に上がっていきます。
理想としては、「モデルBは更新する際CとDを同時に変更する機能を提供する。処理Aが、Bのモデルの処理を呼び出す。」ですかね。

この場合特に単体テストでカバーすることになると思いますが、これまた同じようなテストを呼び出し側でやる必要が出てくるのでそもそも冗長でメンテナンスに手間がかかったりします。

対処法としてはこれも問題1と同じ対処方でいいですね(どのように設計するかは、より重要ですが)

まとめ

誰が作ったにしろ出来上がってしまっているものは仕方ないです。
ですがそこから問題を拾い上げられれば今後の改修で直していくことができたり、注意点を知っておくことでやることもスムーズに決まるかと思います。

ぜひ知っておいていただければと思います。