高品質なソフトウェア開発のための原則 Part2 ~ SLAP・OCP・命名の重要性 ~
前回の記事では、ソフトウェア開発におけるKISS、DRY、YAGNI、PIEの原則について解説しました。今回は、引き続きSLAP、OCP、 名前の重要性の原則について詳しく説明します。
この記事の目次
SLAP (Single Level of Abstraction Principle)
What?
SLAPは「抽象化レベルの統一」という意味で、コードの抽象化レベルを揃えることを推奨します。高いレベルの抽象化概念(高水準)と低いレベルの抽象化概念(低水準)を分離し、同じ関数に属するコードの抽象レベルをすべて統一します。
Why?
抽象化レベルを統一すると、コードに要約性と閲覧性が生まれます。分割された関数は小さなコードの塊になり、閲覧性が向上します。コードの抽象度が揃っていないと読みづらくなり、理解が難しくなります。
How?
関数を構造化し、意図の伝わりやすい、抽象化レベルが揃った小さなステップ群の関数にします。他の関数を呼び出すコードで構成された関数を「複合関数」と呼び、複合関数内で呼び出す関数の抽象レベルを揃えます。
TypeScript例
// 抽象レベルを揃えた関数例
function processOrder(order: Order): void {
validateOrder(order);
const total = calculateTotal(order.items);
finalizeOrder(order, total);
}
function validateOrder(order: Order): void {
// 注文の検証処理
}
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
function finalizeOrder(order: Order, total: number): void {
// 注文の確定処理
}
この例では、注文処理を複数の関数に分割し、それぞれの関数が一貫した抽象化レベルを持っています。これにより、コードの可読性と保守性が向上します。
OCP (Open-Closed Principle)
What?
OCPは「オープン・クローズドの原則」という意味で、コードは「拡張に対して開いている」「修正に対して閉じている」という属性を同時に満たすように設計することを推奨します。
Why?
ソフトウェアは常に変化にさらされるため、長期にわたり安定した設計を維持するためには柔軟な設計が必要です。拡張に対して開いているコードは、新しい機能を追加する際に既存のコードに影響を与えません。一方、修正に対して閉じているコードは、既存のコードを変更せずに動作を変更できます。
How?
コードにインターフェースを用いることで、クライアントとサーバーの間に抽象化レイヤーを設け、既存のコードに影響を与えずに機能を追加できるようにします。
TypeScript例
// インターフェースを用いた柔軟な設計例
interface PaymentProcessor {
processPayment(amount: number): void;
}
class CreditCardProcessor implements PaymentProcessor {
processPayment(amount: number): void {
// クレジットカード決済処理
}
}
class PaypalProcessor implements PaymentProcessor {
processPayment(amount: number): void {
// PayPal決済処理
}
}
function checkout(processor: PaymentProcessor, amount: number): void {
processor.processPayment(amount);
}
この例では、PaymentProcessorインターフェースを用いることで、異なる決済方法を簡単に追加できます。新しい決済方法を追加する際にも、既存のコードを変更する必要がありません。
名前の重要性 (Naming is Important)
What?
適切な命名は、コードを通じてプログラマ同士がコミュニケーションするための最重要手段です。名前を付ける行為そのものに重要な価値があります。
Why?
わかりやすい名前の関数や変数は、その責務や意図を明確に伝え、コードの可読性と理解を向上させます。逆に、不適切な命名はコードの可読性を著しく低下させます。
How?
名前には情報を詰め込み、誤解のないように注意を払い、目的と効果を説明するようにします。発音可能で検索しやすい名前を心がけます。
TypeScript例
// 意図を明確にするための適切な命名例
interface User {
id: string;
name: string;
orders: Order[];
}
interface Order {
id: string;
items: Item[];
}
interface Item {
id: string;
price: number;
}
// ユーザーの合計支出を計算する関数
function calculateUserTotalSpent(user: User): number {
return user.orders.reduce((total, order) => total + calculateOrderTotal(order), 0);
}
// 注文の合計を計算する関数
function calculateOrderTotal(order: Order): number {
return order.items.reduce((sum, item) => sum + item.price, 0);
}
この例では、関数名や変数名を用いて意図を明確にしています。これにより、コードを読む人がその目的をすぐに理解できるようになります。
まとめ
この記事では、ソフトウェア開発におけるSLAP、OCP、命名の重要性について詳しく説明しました。これらの原則を実践することで、コードの品質が向上し、保守性や拡張性が高まります。前回の記事と合わせて、これらの原則を日々のコーディングに取り入れることで、プロジェクトの成功に貢献できるでしょう。
これで二つのパートに亘る、高品質なソフトウェア開発における主要な原則についての解説は終了です。これらの原則を理解し、実践することで、開発チーム全体の効率とコードの品質が向上します。是非、日々の開発に取り入れてみてください。
参考書籍:上田勲(2016). プリンシプルオブプログラミング 3年目までに身に着けたい一生役立つ101の原理原則 秀和システム
カテゴリー: