ソフトウェア システムを構築する場合、コードベースの複雑さを管理することが重要です。
Clean Code の第 11 章では、長期にわたる保守と適応が容易なモジュール式システムの設計について説明します。
JavaScript の例を使用して、これらの概念を説明できます。
システムが成長するにつれて、当然、より複雑になります。この複雑さにより、次のことが困難になる可能性があります。
適切に設計されたシステムは、変更が容易で、テスト可能で、拡張可能である必要があります。これを達成する秘訣は、モジュール性と懸念事項の慎重な分離にあります。
クリーン システム設計の中心となるのはモジュール性の原則です。大規模なシステムを、それぞれが明確な責任を持つ小さな独立したモジュールに分割することで、システムを管理しやすくします。
各モジュールは特定の機能をカプセル化し、システム全体を理解し、変更しやすくする必要があります。
例: ショッピング カート システムの構成
JavaScript でショッピング カート システムを想像してみましょう。すべてのロジックを 1 つのファイルにまとめる代わりに、システムを複数のモジュールに分割できます:
// cart.js export class Cart { constructor() { this.items = []; } addItem(item) { this.items.push(item); } getTotal() { return this.items.reduce((total, item) => total + item.price, 0); } } // item.js export class Item { constructor(name, price) { this.name = name; this.price = price; } } // order.js import { Cart } from './cart.js'; import { Item } from './item.js'; const cart = new Cart(); cart.addItem(new Item('Laptop', 1000)); cart.addItem(new Item('Mouse', 25)); console.log(`Total: $${cart.getTotal()}`);
ここでは役割が分割されています。Cart はアイテムを管理し、Item は製品を表し、order.js は相互作用を調整します。
この分離により、各モジュールが自己完結型となり、個別にテストや変更が容易になります。
モジュール性の目標の 1 つはカプセル化、つまりモジュールの内部動作をシステムの残りの部分から隠すことです。
外部コードは、明確に定義されたインターフェイスを通じてのみモジュールと対話する必要があります。
これにより、システムの他の部分に影響を与えることなく、モジュールの内部実装を簡単に変更できます。
例: カート ロジックのカプセル化
カート内の合計の計算方法を変更したいとします。おそらく今は消費税を考慮する必要があるでしょう。このロジックは Cart クラス内にカプセル化できます:
// cart.js export class Cart { constructor(taxRate) { this.items = []; this.taxRate = taxRate; } addItem(item) { this.items.push(item); } getTotal() { const total = this.items.reduce((sum, item) => sum + item.price, 0); return total + total * this.taxRate; } } // Now, the rest of the system does not need to know about tax calculations.
システムの他の部分 (order.js など) は、合計の計算方法の変更による影響を受けません。これにより、システムの柔軟性が高まり、保守が容易になります。
大規模システムでよくある問題は、システムのさまざまな部分が絡み合うことです。
モジュールが多くの責任を負い始めると、異なるコンテキストでの変更や再利用が難しくなります。
関心の分離の原則により、各モジュールが 1 つの特定の責任を持つことが保証されます。
例: 支払いを個別に処理する
ショッピング カートの例では、支払い処理は別のモジュールで処理する必要があります:
// payment.js export class Payment { static process(cart) { const total = cart.getTotal(); console.log(`Processing payment of $${total}`); // Payment logic goes here } } // order.js import { Cart } from './cart.js'; import { Payment } from './payment.js'; const cart = new Cart(0.07); // 7% tax rate cart.addItem(new Item('Laptop', 1000)); cart.addItem(new Item('Mouse', 25)); Payment.process(cart);
これで、支払いロジックがカート管理から分離されました。これにより、システムの残りの部分に影響を与えることなく、後で支払いプロセスを簡単に変更できます (例: 別の支払いプロバイダーとの統合)。
モジュール化の最大の利点の 1 つは、各モジュールを個別にテストできることです。
上記の例では、支払いの処理方法を気にすることなく、Cart クラスの単体テストを作成できます。
例: カートの単体テスト
// cart.test.js import { Cart } from './cart.js'; import { Item } from './item.js'; test('calculates total with tax', () => { const cart = new Cart(0.05); // 5% tax cart.addItem(new Item('Book', 20)); expect(cart.getTotal()).toBe(21); });
懸念事項を明確に分離することで、各モジュールを個別にテストできるため、デバッグが容易になり、開発が迅速化されます。
モジュールが相互に依存しすぎると、システムの一部の変更が他の場所に予期せぬ影響を与える可能性があります。
これを最小限に抑えるには、モジュール間の疎結合を目指します。
これにより、各モジュールが独立して進化することができます。
例: 依存関係の挿入
モジュール内の依存関係をハードコーディングする代わりに、依存関係を引数として渡します:
// cart.js export class Cart { constructor(taxRateCalculator) { this.items = []; this.taxRateCalculator = taxRateCalculator; } addItem(item) { this.items.push(item); } getTotal() { const total = this.items.reduce((sum, item) => sum + item.price, 0); return total + this.taxRateCalculator(total); } }
このアプローチにより、Cart クラスがより柔軟になり、さまざまな税計算でのテストが容易になります。
コーディングを楽しんでください! ?
以上がクリーンなコードを理解する: システム ⚡️の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。