こんにちわ。新米プロダクトマネージャのKMTです。
もともとエンジニアをしていて、最近プロダクトマネージャになった私ですが、
プロダクトマネージャのネタがまだないので、今回はエンジニア時代に心がけていたことをお話させてもらおうと思います。
わりと初歩的な内容ではありますが、読みやすいコードを書く方法の一つとして、聞いていただければと思います。
背景
読みやすいコードを書く技術を向上させたいと思っていた当時の僕が読んだ本が
「Clean Code アジャイルソフトウェア達人の技 Robert C.Martin (著)」でした。
その中で一番心に刺さり、ずっと心がけていたことが
「関数の中の処理は、同じ抽象度で統一すべきである」
でした。こちらについて解説させていただきます。
抽象度とは?
注文の処理を行うProcessCustomerOrder
メソッドを例に考えてみましょう。
public void ProcessCustomerOrder(Order order) { // 注文を処理状態にマーク(抽象度:高) order.MarkAsProcessed(); // ステータスを「発送済み」に更新(抽象度:高) order.UpdateStatus("Shipped"); // 通知送信(抽象度:中) SendShippingNotification(order.CustomerEmail); // ログ出力(抽象度:激低) // ↓ ここからOSレベルの処理が突然始まる var path = @"C:\logs\order_log.txt"; // ログディレクトリがなければ作成 if (!Directory.Exists(@"C:\logs")) { Directory.CreateDirectory(@"C:\logs"); } // ファイルにログを書き込み using (var writer = new StreamWriter(path, true)) { writer.WriteLine($"{DateTime.Now} - Order {order.Id} shipped to {order.CustomerEmail}"); } // ファイル属性を変更 File.SetAttributes(path, FileAttributes.ReadOnly); }
いかがでしたでしょうか?
抽象度で高、中、激低がでてきましたが、激低の処理は明らかにここにあることに違和感を感じませんか?
これが抽象度がそろっていないという状態です。
では抽象度を揃えるとどうなるでしょうか
public void ProcessCustomerOrder(Order order) { // 抽象度:高(ビジネスロジックの流れだけを表現) ProcessOrder(order); // 注文処理 NotifyCustomer(order); // 発送通知 LogOrderShipment(order); // 発送ログ記録 }
このようになります。
ビジネスロジックのメソッドに切り出して、ProcessCustomerOrder
内ではそれだけを書いております。
※当然ですが、実際には各メソッドの処理を別途書いている前提です
だいぶ読みやすくなりましたよね。
これが抽象度を揃えるという事です。
解説:なぜこの構成が良いのか?
1. 関数ごとの抽象度が一定
ProcessCustomerOrder
は「注文を処理する」という高レベルの業務視点に特化しています。
その中で、詳細な処理(ファイル操作や通知など)は別メソッドに委譲されています。
2. 見通しが良い
メソッドの目的が「処理の流れ」だけで構成されているため、パッと見て業務手続きが直感的に理解しやすいです。
3. テストや保守がしやすい
ログ処理や通知処理を個別にテスト・差し替えできるようになるため、保守性・拡張性が高まるのです。
まとめ
「Clean Code アジャイルソフトウェア達人の技」では、次のように語られています。
「コードは物語のように読めなければならない」
抽象度を揃えた関数は、まさに「上から下へ、すらすらと読める物語」になります。
今回サンプルで使用したC#のような表現力のある言語では、どうしても「業務ロジック」と「実装詳細」が混ざりがちです。
だからこそ、意識して抽象度を揃えることが、読みやすく・安全なコードを書くための鍵となります。
もしよければ今後意識してみてくださいね。
We are hiring!!
ROBOT PAYMENTでは一緒に働く仲間を募集しています!!!