アーキテクチャの原則と方法論 — は、開発者が保守可能でスケーラブルで理解しやすいコードを作成するのに役立つルールと推奨事項のセットです。TIOBE Index (2025)によると、アーキテクチャの原則に従うプロジェクトは、重大な欠陥が40%少なくなります。この記事では、SOLID、GRASP、DRY、KISS、YAGNIなどの原則について解説し、技術的負債とCode Smellについても説明します。
重要ポイント
アーキテクチャの原則 — は高品質なコードの基盤です。SOLIDはロバート・マーティン(「アンクル・ボブ」)によって導入された頭字語で、オブジェクト指向設計の5つの原則を表しています。SOLIDに従うことで、コードはより柔軟でテスト可能で変更に強くなります。アーキテクチャの原則の違反は、技術的負債の主な原因の一つです。
各原則を見ていきましょう。Single Responsibility Principle (SRP) — 各クラスは変更理由を一つだけ持つべきです。Open/Closed Principle (OCP) — クラスは拡張に対して開かれ、修正に対して閉じられているべきです。Liskov Substitution Principle (LSP) — サブタイプのオブジェクトは、ロジックを壊すことなく基本型のオブジェクトを置き換えられるべきです。Interface Segregation Principle (ISP) — 一つの汎用インターフェースより、多くの専門化されたインターフェースの方が良い。Dependency Inversion Principle (DIP) — 具体的な実装ではなく、抽象に依存すべきです。
SonarQubeの分析(2025年)によると、SOLID原則の違反は商業プロジェクトの68%で発生しています。最も一般的な問題はSRP違反(35%)とISP違反(22%)です。IT Sectrでは、アーキテクチャレビューの段階でSOLIDを実装しています。これにより、問題が技術的負債に発展する前に特定することができます。
SRP(単一責任の原則)— 最も重要であり、同時に最も頻繁に違反されるSOLIDの原則です。これは次のように述べています:クラスは変更理由を一つだけ持つべきです。クラスがやりすぎると、テスト、変更、理解が困難になります。
典型的な違反は、データを処理し、データベースに保存し、メール通知を送信するという3つのことを同時に行うクラスです。以下の例は、KotlinでのSRP違反とその修正方法を示しています。
// SRP違反 — クラスが3つの異なることを行う
class UserService {
fun registerUser(email: String, name: String) {
// 1. データ検証
if (!email.contains("@")) throw IllegalArgumentException("Invalid email")
// 2. データベースに保存
val user = User(email, name)
database.save(user)
// 3. 通知を送信
emailService.sendWelcomeEmail(email, name)
}
}
// 修正 — 3つのクラスに分割
class UserRegistrationService {
fun register(email: String, name: String) {
UserValidator().validate(email)
val user = User(email, name)
UserRepository().save(user)
NotificationService().sendWelcome(user)
}
}
修正版では、各クラスが自身のタスクに責任を持ちます:UserValidator — 検証、UserRepository — 保存、NotificationService — 通知。これによりコードがテスト可能で再利用可能になり、検証ロジックを変更せずにデータベースの実装を置き換えることができます。
GRASP (General Responsibility Assignment Software Patterns) — クレイグ・ラーマンによって記述された、オブジェクト間の責任割り当ての9つのアーキテクチャ原則です。SOLIDとは異なり、GRASPは「どのクラスがこのメソッドを持つべきか」という質問に答えます。主要なパターン:Information Expert、Creator、Controller、Low Coupling、High Cohesion、Polymorphism、Pure Fabrication、Indirection、Protected Variations。
Law of Demeter (LoD、最小結合の原則) — シンプルなルール:オブジェクトは直接の隣接オブジェクトとのみ通信すべきです。a.getB().getC().doSomething() と書くべきではありません — これはクラス間の強い結合を生み出します。LoDは再利用性を向上させ、テストを簡素化します。
IT Sectrでは、コードレビュー時にLoDの準拠をチェックしています。メソッドが3つ以上のオブジェクトを「通過する」場合、それはアーキテクチャの簡素化が必要なシグナルです。LoD違反は大規模プロジェクトで最も一般的なCode Smellの一つです。
DRY (Don't Repeat Yourself)、KISS (Keep It Simple, Stupid)、YAGNI (You Ain't Gonna Need It) — すべての開発者に知られている3つの基本的なアーキテクチャ原則です。そのシンプルさにもかかわらず、違反は頻繁に発生します。
DRY — コードを重複させないでください。同じロジックが2箇所に現れる場合は、共通のメソッドまたはクラスに抽出してください。重複はバグの主な原因です:ある場所での修正が別の場所に適用されるのを忘れられます。DRYは似たコードを持つことができないという意味ではありません — 重要なのはビジネスロジックが繰り返されないことです。
KISS — シンプルであるほど良い。多くの抽象化や継承を伴う複雑なソリューションは、しばしば過剰です。シンプルな解決策から始め、必要な場合にのみ複雑にしてください。YAGNI — 「いつか後で」必要になるかもしれない機能のためにコードを書かないでください。これはコードベースの肥大化とメンテナンスの複雑化につながります。
DRY — これは単にコピーペーストの欠如ではありません。これは、知識やロジックの各部分がシステム内で単一の明確な表現を持つべきであるという原則です。重複には明示的なもの(コピーされたコード)と暗黙的なもの(異なるレイヤーでの同じロジック)があります。
IT Sectrでは、重複を検出するためにコード分析メトリクスを使用しています。SonarQubeやDetektなどのツールは、重複コードの割合を表示します。5%を超える値はリファクタリングの理由になります。ただし、間違った抽象化を犠牲にしてDRYを達成すべきではないことを覚えておくことが重要です — 2つの類似したコード片を結合することで理解が複雑になる場合は、そのままにしておく方が良いこともあります。
関心の分離 (SoC) — システムを独立した部分(関心)に分割し、各部分が自身のタスクを解決するアーキテクチャ原則です。古典的な例は層への分割です:プレゼンテーション、ビジネスロジック、データアクセス。各層はその下の層にのみ依存します。
モジュール性 — システムをモジュールに分割できる程度。モジュールは、明確に定義されたインターフェースを持つ論理的に関連するクラスのグループです。モジュールは疎結合(low coupling)で強凝集(high cohesion)であるべきです。
凝集度 (Cohesion) — 同じモジュール内の要素が互いにどの程度関連しているかの尺度。高い凝集度は良いことです:クラスは一つのことを行い、それをうまく行います。低い結合度 (Low coupling) — モジュールが互いにどの程度独立しているかの尺度。低い結合度は良いことです:一つのモジュールの変更が他を壊しません。
理想的なアーキテクチャは高凝集度かつ低結合度です。実際には、これはクラスが同じデータに対して動作するメソッドを含み(凝集度)、具体的な実装ではなく抽象にのみ依存する(結合度)ことを意味します。バランスが崩れると「神オブジェクト (God Object)」や「スパゲッティコード」につながります。
技術的負債 (Technical Debt) — ワード・カニンガムによって導入された比喩で、チームが最適でないアーキテクチャ決定やアーキテクチャ原則の違反に対して支払う「利子」を表します。金融負債と同様に、技術的負債は意図的なもの(迅速に行うことを決定し、後でやり直す)と意図的でないもの(経験不足による悪いアーキテクチャ)があります。
Code Smell — コード内の深い問題の表面的な兆候。この用語はマーティン・ファウラーが著書「Refactoring」で広めました。典型的なCode Smell:長いメソッド、大きなクラス、長い呼び出しチェーン、コードの重複、コメントの過剰使用(明確なコードの代わりに)。
IT Sectrでは、技術的負債はJiraで個別のタスクとして追跡されています。各スプリントで、リファクタリングと負債返済に20%の時間を割り当てています。技術的負債に体系的に取り組むことが、新しい機能の追加にゼロから開発するよりも時間がかかるという状況を避ける唯一の方法です。
よくある質問
Single Responsibility Principle (SRP) — 最も重要です。その違反は自動的に他の原則の違反につながるからです。複数の責任を持つクラスは、テスト、拡張、保守が困難です。SRPから始めてください — 残りは自然と整います。
凝集度 (Cohesion) — モジュール内の結合(高いほど良い)。結合度 (Coupling) — モジュール間の結合(低いほど良い)。良いアーキテクチャは高凝集度かつ低結合度を目指します。
いいえ、原則はガイドラインであり絶対的な法則ではありません。小規模プロジェクトやプロトタイプでは、SOLIDへの過度の遵守が過剰設計につながる可能性があります。「十分に良い」アーキテクチャと開発速度のバランスを見つけることが重要です。
静的解析ツール(SonarQube、Detekt、ESLint)、コードレビュー、コードメトリクスを使用してください。負債の兆候:コードのテストが困難、ある場所の変更が別の場所を壊す、新しい機能の追加にかかる時間がスプリントごとに増加する。定期的なリファクタリングが負債を制御する唯一の方法です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。