Web制作、Web開発の歩き方

インターフェースを理解して、設計力を高めよう

第4話:インターフェース設計の落とし穴

(最終更新日:2024.1.27)

Linuxのイメージ
この記事は5分で読めます!
(絵が小さい場合はスマホを横に)

「良いインターフェースとは」

前回までで、インターフェースの概要や役割、具体的な使い方というものを学んだ。 今回は更に、より良くインターフェースを設計することを学んでいく。 良いインターフェース設計ができれば、ソフトウェア品質や開発の生産性向上に大きく貢献する。 今回の学びを経て、安全で分かりやすく、柔軟で拡張性の高いインターフェース設計ができればと思う。


1.良いインターフェース設計の例

良いインターフェースの設計例として、RESTful APIのコード例を見てみよう。 ここでは、一般的なユーザー管理機能を提供するAPIを考えてみる。 以下は、ユーザーの取得、作成、更新、削除を行うRESTful APIの簡単な実装だ。 ここでは、Node.jsとExpressフレームワークを用いている。

RESTful APIのコード例:ユーザー管理

各エンドポイントは、HTTPメソッド(GET、POST、PUT、DELETE)とユーザー操作を明確に関連付けている(一貫性と直観性)。 APIは、内部のデータ構造に関係なく機能します。これにより、バックエンドの変更がクライアントに影響を与えず、拡張が容易になる(疎結合と拡張性)。 リクエストとレスポンスの構造が明確で、APIの使用方法が理解しやすくなっている(明確さ)。

このコード例は、RESTful APIの基本原則を実装しており、良いインターフェース設計の一例として機能する。 このようなAPI設計は、クライアントとサーバー間の通信が効率的かつ一貫性を持って行われることを保証する。


2.インターフェース設計の落とし穴

インターフェース設計における一般的な落とし穴は、過剰設計、不明瞭な抽象化、過度の一般化、そして不十分なドキュメンテーションなどがある。 以下に、具体的なTypeScriptのコード例を挙げる。これらのコードを見ながら、何がまずいかを一緒に考えよう。 それぞれの落とし穴に対応する不適切なインターフェース設計と、それを改善する方法も示す。

下記のインターフェースは多くの責任を一つにまとめており、複雑すぎる。責務を分離する必要がある。

過剰設計(オーバーエンジニアリング)

下記のように修正すると、インターフェースごとに責務が分かりやすい。

過剰設計(オーバーエンジニアリング)の修正

次に不明瞭な抽象化の例をあげる。上部のコードでは、インターフェースは非常に抽象的で、具体的なデータ処理の方法が不明確である。 下部のコードでは、データの形式を明確にすることで、インターフェースの目的がより明確になっていることが分かる。

データ形式が不明瞭な抽象化(上)
明確な抽象化(下)

次に過度の一般化の例をあげる。 上部のインターフェースはあらゆるデータベース操作をカバーしようとしているが、それだと特定のデータベースの特有の機能を活用できない。 下部のインターフェースでは、データベースの種類に応じて活用できる。

過度に一般化した例(上)
データベースの種類で一般化した例(下)

最後にドキュメンテーションが不十分な例を挙げる。 上部では、このインターフェースは何をログに記録するか、ログの形式やレベルについての情報が不足している。 下部では、何をログに記録するか、ログの形式やレベルについて一目瞭然である。 メソッドの目的、パラメータ、動作を明確にするドキュメンテーションを提供している。

ドキュメントが不足している例(上)
ドキュメントが充分な例(下)

これらの例を通じて、インターフェース設計の一般的な落とし穴と、それらを避ける方法が理解できる。 適切なインターフェースを設計し、コードの可読性、保守性、拡張性を向上させよう。


3.まとめ

今回は、インターフェース設計の落とし穴と題して、悪い設計と良い設計を交互に見てみた。 インターフェースだからと言って、過度に抽象化したり、データの意味が分からなかったり、責務が不明確だったりすると、後の実装で困ることになる。 今後、インターフェースを設計する際、これら4つのアンチパターンになっていないか、見直してみよう。きっと改善点が見つかるはずだ。

▼参考図書、サイト

 「ちょうぜつソフトウェア設計入門―PHPで理解するオブジェクト指向の活用」 技術評論社 田中ひさてる
周りのプログラマーの一歩先を行く! プログラムの設計の本質と秘訣 Engineer Club


Understand Interfaces and Improve Your Design Skills Episode 4: Pitfalls in Interface Design (Last Updated: 2024.1.27) Linux Image You can read this article in 5 minutes! (If the images are small, rotate your smartphone.) "What Makes a Good Interface?" So far, we've learned about the overview, role, and usage of interfaces. This time, we'll go further and learn how to design better interfaces. A well-designed interface can significantly contribute to software quality and development productivity. Through today's lessons, let's aim to design safe, understandable, flexible, and highly extensible interfaces. [Table of Contents] Examples of Good Interface Design Pitfalls in Interface Design Summary 1. Examples of Good Interface Design Let's look at an example of good interface design using a RESTful API. Here, we'll consider an API that provides general user management functions. Below is a simple implementation of a RESTful API for retrieving, creating, updating, and deleting users. It uses Node.js and the Express framework. Example of RESTful API Code: User Management Each endpoint clearly associates HTTP methods (GET, POST, PUT, DELETE) with user actions (Consistency and Intuitiveness). The API functions independently of the internal data structure, ensuring changes in the backend do not affect clients, making it easier to expand (Loose Coupling and Extensibility). The request and response structures are clear, making the API usage straightforward (Clarity). This example implements the fundamental principles of RESTful API and serves as a good reference for interface design. Such an API design ensures efficient and consistent communication between clients and servers. 2. Pitfalls in Interface Design Common pitfalls in interface design include over-engineering, unclear abstractions, excessive generalization, and inadequate documentation. Below are TypeScript examples illustrating these issues. Let's examine them together and think about what went wrong. For each pitfall, we will also introduce solutions to improve the design. The following interface tries to handle too many responsibilities, making it overly complex. Responsibility separation is needed. Over-Engineering The revised version below makes responsibilities clearer by separating concerns across multiple interfaces. Fixed Over-Engineering Next, let's look at unclear abstractions. The top code example uses an overly abstract interface, making it difficult to understand how data processing works. The bottom example clarifies data structure, making the interface's purpose more transparent. Unclear Abstraction (Top) vs. Clear Abstraction (Bottom) Next is excessive generalization. The top interface aims to cover all database operations but fails to leverage specific database features. The bottom interface provides a more database-specific approach. Excessive Generalization (Top) vs. Database-Specific Design (Bottom) Lastly, let's discuss inadequate documentation. The top example lacks details about what gets logged, the log format, and log levels. The bottom example makes all these aspects clear, providing well-documented methods, parameters, and functionalities. Insufficient Documentation (Top) vs. Well-Documented Design (Bottom) By reviewing these examples, we can understand common pitfalls in interface design and how to avoid them. Designing proper interfaces improves readability, maintainability, and extensibility. 3. Summary In this lesson, we examined pitfalls in interface design, alternating between bad and good examples. If an interface is overly abstract, unclear, or has ambiguous responsibilities, it can lead to issues during implementation. When designing interfaces in the future, review them to ensure they avoid these four anti-patterns—you'll likely find areas for improvement. ▼ References  "Super Software Design Introduction—Understanding Object-Oriented Programming with PHP" by Hisateru Tanaka, published by Gijutsu-Hyoronsha  Engineer Club: Secrets to Advanced Software Design