Technology部の菊池です。
当記事では、開発プロジェクトの生産性を高めるうえで重要な「クリーンコード」を実現する方法を解説します。
クリーンコードを意識すれば、「数千コード書いてもバグがほとんど見つからなかった」なんて状況も夢ではありません。開発に携わるみなさん、ぜひご覧ください。
「クリーンコード」とは
前提として「クリーンコード」とは、「可読性」「メンテナンス性」「拡張性」の3つが揃ったものであると考えます。
クリーンなコードであれば、新しく参加したエンジニアであってもコードを書きやすくなります。その結果複数人で開発できて、プロジェクトの生産性が上がります。
逆にクリーンなコードでなければ、開発が属人化して知っている人しかコードが修正できない、新しく参加したエンジニアがコードを書くとデグレが発生する事態に陥ることになります。
よって開発に関わるメンバー全員が「クリーンコード」を意識しながら、プロジェクトに取り組む必要があるでしょう。
可読性
・非エンジニアでもソースコードを見れば内容を想像できる
・変数やファイル名、クラス名、メソッド名からロール&レスポンシビリティが想像できる
・制御構造文のネストが深くない(1メソッドあたり2〜3程度)
・1メソッドあたりのステップ数が多くない(多くても100行程度)
・ソースコード自体が単一責任である、複数責任のあるコードは実装しない
メンテナンス性
・クラスやコンポーネント、モジュール内に閉じた状態で修正できる
・修正を実施しても他のクラスやコンポーネント、モジュールに影響しない
・リファクタリングを実施しやすい
・デグレード対策として事前にテストコードが書いてある
拡張性
・コンポーネントやファイル、メソッド、クラスを追加しやすい
クリーンコードを実現する方法
クリーンコードを実現するためには、次の2つを心がけましょう。
- プログラムの凝集度を上げる
- プログラムの結合度を下げる
「凝集度」とは
「凝集度」とは、クラスやモジュール、メソッド内におけるロジックとデータの結びつきの強さを示す指標です。結びつきが強いほど「高凝集」であり、ソフトウェア開発において推奨されています。
▼ゴミの分別にたとえてみると……
低凝集な状態:
1つのゴミ箱のなかに資源ごみも生ごみも、燃えないゴミも混ざっていて、箱(クラスやモジュール)と入っているゴミ(データや処理)の結びつきが低い
高凝集な状態:
箱(クラスやモジュール)がゴミの種別ごとに分かれていて、箱のなかに入っているゴミ(データや処理)の結びつきが高い
また、凝集度には以下のような指標があり、凝集レベルは下にいくほど下がります。
・機能凝集:モジュール内のすべての機能が単一の明確なタスクを達成するために集中
・逐次凝集:モジュール内の各部分が特定の順序で実行され、一つの活動が次の活動の入力となる
・通信凝集:モジュールの部分が同じデータを操作する活動をおこなうが、異なる関数を持つ
・手続き凝集:モジュールが異なる操作を実行するが、それらが一つの手続きの中で実行される
・時間的凝集:関連する活動が特定の時間に実行される必要がある
・論理凝集:関連する性質はあるが、それ以外は関連性が低い活動がモジュール内に含まれている
・偶発的凝集:モジュール内のさまざまな活動が関連性を持たずにただ一箇所にまとめられている
理想は、すべてのコードが機能凝集であることです。
しかしながら、機能凝集を極端に進めるとソースコードファイル数が増加し、管理が困難になる可能性があります。
また、たとえばAWSのS3へアクセスする機能を用意する場合、必要な各機能(ファイルアップロードやダウンロード、一覧取得など)を個別のファイルで実装することになり、ファイル数やクラス数が増えて管理が複雑になってしまいます。実際私がこの状況を目の前にしたら、AWS S3クラスを用意してメソッドで分ける通信凝集を選ぶでしょう。
ゆえに、現実的には高凝集を目指すものの、プロジェクトの規模や他の制約も考慮して、適度なレベルの凝集度を選ぶことが重要です。
「結合度」とは
「結合度」とは、モジュール間の依存度を示す指標です。モジュール間の結合度が低いほど、修正における他のモジュールへの影響度が下がり、ソフトウェア開発において推奨されています。
▼カップルにたとえてみると……
高結合な状態:
付き合いたてのラブラブなカップル。四六時中連絡を取り合い、片方の連絡が滞ると、片方の機嫌が悪くなるなど、お互い依存し合っている状態
低結合な状態:
くっつき過ぎず依存し過ぎず、お互いに一人の人間として尊敬しあっているという状態
結合度には以下のような指標があり、結合レベルは下にいくほど下がります。
・内容結合:一つのモジュールが別のモジュールの内部動作に依存。避けるべき結合の形
・共通結合:複数のモジュールが同じグローバルデータを共有しており、変更が他に影響を及ぼす
・外部結合:複数のモジュールが同じ外部のデータやリソースに依存
・制御結合:一つのモジュールが別のモジュールに対して制御情報を渡す
・スタンプ結合:モジュール間でデータ構造を共有するが、利用するのはその一部分だけ
・データ結合:モジュール間で単純なデータパラメータを渡す
・メッセージ結合:モジュール間の通信がメッセージでのみおこなわれる
・無結合:モジュール間に依存関係がまったくない、望ましい結合の形
高凝集・低結合を実現するために
各自が高凝集・低結合なクリーンコードを理解したうえで、次のような取り組みが必要です。
1.コーディングルールをチーム内に周知徹底させる
コーディングルールはあらゆるオープンソースのリポジトリで定義されているため、ぜひ参考にしましょう。これらはオンラインでの開発を実現するために、オープンソースの管理人がコーディングルールを定義していると予想されます。
2.高凝集・低結合なデザインパターンを用いる
Atomic Designやクリーンアーキテクチャなど、世界中の開発者からすでに支持されているデザインパターンを採用することもオススメです。また、高凝集・低結合を実現するソフトウェア設計原則(「SOLID原則」など)もあるので、参考にするとよいでしょう。
なお、オフショアの場合、開発拠点への指示だしは上記を理解したテクニカルディレクターがクラスやモジュール単位でチケットを作成し、開発することが望ましいと考えます。テクニカルディレクターには、ソフトウェアの全体構成を理解したうえで、どんなモジュールが必要かを検討し、指示を出すことが求められます。
また指示を出す場合は入力と出力がどのような期待値になるかを定義したうえで各メンバーに伝えましょう。