『リーダブルコード』第4章 美しさ

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

コードの美しさの3つの原則

  1. 読み手が慣れているパターンと一貫性のあるレイアウトを使う。
  2. 似ているコードは似ているように見せる。
  3. 関連するコードをまとめてブロックにする。

なぜ美しさが大切なのか?

プログラミングの時間のほとんどはコードを読む時間なのだッ!

コードの整形について

本書では、以下のトピックがC++/Javaのコード例と共に議論されている。

  • 一貫性のある簡潔な改行位置
  • メソッドを使った整列
  • 縦の線をまっすぐにする

PHPer的には、PHP コードの整形はプログラマがやるべきことじゃないということで、IDEに任せてしまうのが一番。

幸い、PHPにはPSR-1/2というコーディング規約の「業界標準」があり、それに沿った整形を行うためのツール(PhpStorm等のIDE)も揃っている。

概念の整理について

  • 一貫性と意味のある並び
  • 宣言をブロックにまとめる
  • コードを「段落」に分割する

コードを意味のある並びにしたり、意味のある単位で区切ったりすると読みやすくなる。

個人的な好みと一貫性

一貫性のあるスタイルは「正しい」スタイルよりも大切だ。

『Web API デザインの鉄則』第4章 エラー表現とドキュメント

WEB+DB PRESS Vol.82

Web APIのドキュメントに明示する必要がある項目としては、次のような事柄が挙げられます。

  • 認可(Authorization)の方法、必要な権限(scope)
  • エンドポイントURLやHTTPメソッド
  • リクエスト形式
  • レスポンス形式
  • エラー表現
  • 説明やサンプル

エラー表現

主要なHTTPステータスコード

  • 2xx系(成功)
  • 3xx系(リダイレクト)
  • 4xx系(クライアント側のエラー)
  • 5xx系(サーバ側のエラー)

以下、本記事の著者が使っているステータスコードの使用例です。

2xx系

200 OK
  • エントリリソースの取得(GET)
  • コレクションリソースの取得(GET
  • エントリリソースを更新し、現在のリソースを返す(PUT, PATCH)
  • オーバーロードPOST/GETを行い、レスポンスボディを返す(POST, GET)
201 Created
  • エントリリソースの作成(POST)
202 Accepted
  • 非同期処理全般(POST, PUT, DELETE, PATCH)
204 No Content
  • エントリリソースを更新するが、現在のリソースは返さない(PUT, PATCH)

4xx系

400 Bad Request

クライアント側の汎用エラー

401 Unauthorized

クライアントが適切なAuthorizationヘッダを送ってこなかった場合

403 Forbidden

リクエスト形式も認可情報も妥当であるが、そのほかの何らかの理由によりアクセスが拒否された場合

409 Conflict

リソースの変更が不可能又は矛盾している

429 Too Many Requests

リクエストの回数制限などにひっかかる場合に用いる

エラー表現と標準仕様

HTTPエラー表現のRFCとしてhttp-problemというものがあります。

ドキュメントに図を活用する

PlantUMLというUMLモデリングツールについて紹介されています。UMLについてはあまり詳しくないので省略で…。

感想

RESTの基本の整理のように、初心者にも役に立つ部分がありますが、基本的には、「Web APIの設計のベストプラクティスを知りたい」という読者に最もフィットする記事だと思います。クローズドなAPIであれば、多少いい加減な設計でも、クライアント側との合意ができていれば問題ありません。しかし、多くのユーザーに提供するAPIの場合、設計が非常に重要になります。

RFCのようなパブリックな仕様に基づいたAPI設計や、JSON Schemaを使用したマシンリーダブルな仕様書の作成等、意識すべきポイントの勘所がおさえられていて参考になる記事でした。

『Web API デザインの鉄則』第3章 インタフェース設計

WEB+DB PRESS Vol.82

Web APIのインタフェースを定義する際に決めなければならない点は以下になります。

  • エンドポイントURI
  • HTTPメソッド
  • クエリパラメータ

エンドポイントURIの定義

ROA(Resource Oriented Architecture)におけるリソースは、URIを持つ必要があります。

エンドポイントURIとは、個々のリソースの所在を表すURIです。

前回に引き続き、本記事ではブログポストのリソースの扱いを題材にしていきます。
(オリジナルの記事ではメールのドメインリソースを題材としています)

すでに存在するリソースを返すエンドポイント

  • GETメソッドでアクセスできる
  • リソースの表現はapplication/json形式
  • /api/posts:複数のpostsリソースを取得(コレクションリソース)
  • /api/posts{/posts_id}:単一のpostsリソースを取得
  • /api/posts{/posts_id}/comments{/id}:ポストに関連するコメントを取得する(エントリリソース)

新しいリソースを作成するエンドポイント

  • POSTメソッドでアクセスできる
  • リソースの表現はapplication/json形式
  • /api/posts:新しいpostsリソースを作成

すでに存在するリソースを削除するエンドポイント

  • DELETEメソッドでアクセスできる
  • 削除が成功した場合は204 No Contentで応答する
  • /api/posts{/posts_id}:単一のpostsリソースを削除

HTTPメソッドの選び方

RESTにおいてよく用いられるHTTPメソッドは次の4つです。

  • GET(リソースの取得)
  • POST(リソースの作成)
  • PUT(リソースの更新)
  • DELETE(リソースの削除)

POSTを利用するケース

a. コレクションリソースに対して新規のエントリリソースを追加
b. 既存のリソースに対して状態を追加
c. オーバーロードPOST

aとbが一般的な利用方法です。

cのオーバーロードは、「ROAの用途では表現しきれないインターフェースを持つもの全般を表現するために用いる手法」です。具体的には、リソースの差分更新などに使用されます。

PUTを利用するケース

a. 既存のエントリリソースを更新
b. 新規のエントリリソースを(明示的に)追加

aは既存のリソースに対する差分更新ではなく置き換えだという点が重要です。PUTメソッドによる更新の際は、置き換えるべきリソースの完全な表現をリソースに含める必要があり、一部分だけを更新することはできません。完全な表現が含まれるからこそ、PUTメソッドの冪等性があるといえます。

差分更新については、PATCHという新しいHTTPメソッドがRFC5789で提案されており、Rails4でも採用されています。

コレクションとクエリパラメータ

コレクションリソースを取得する場合、エントリを何らかのリストとして表現する必要があります。こういったコレクションに対しては、取得件数や並び順、検索条件などを取得時に指定したいことがあります。

クエリパラメータが必要なケース

コレクションリソース全体を取得すると膨大な量になってしまうような場合には、ページネーションが必要となります。

ページネーションのためには、以下のようなクエリパラメータが必要です。

  • コレクション取得の開始位置(OFFSET)
  • コレクションの最大取得件数(LIMIT)
  • コレクションのソートフィールド(ORDER BY)
  • コレクションの並び順(ASC/DESC)

『リーダブルコード』第3章 誤解されない名前 読書メモ

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

鍵となる考え:名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する

filter()だと、選択するのか除外するのか分からない。選択するならselect()、除外するならexclude()とした方が分かりやすい。

限界値を含めるときは min と max を使う

このコードには、商品数が10の場合にもエラーとして処理してしまうというバグがある。
限界値を明確にするには、名前の前に max_ や min_ をつけたほうがよい。

範囲を指定するときは first と last を使う

これでは、[2, 3]が表示されるのか、[2, 3, 4]が表示されるのか分からない。
終端を範囲に含めるのであれば、lastを使ったほうが良い。

※この辺、英語のニュアンスの問題なので、非ネイティブには伝わりづらいような…。

包含/排他的範囲には begin と end を使う

10月16日に開催されたイベントを表示するなら、以下のようなコードになる。

ここで、PrintEventsInRange()の仮引数の名前のような、包含範囲を示すには、begin/endを使うのがよい。

真偽値の名前

以下の変数名は、パスワードをこれから読み取る必要があるのか、既に読み取り済みなのか分からない。

真偽値の変数名の頭には、is・has・can・shouldなどをつけて分かりやすくする。また、否定形を使うと分かりづらくなることがあるので注意。

ユーザの期待に合わせる

多くのプログラマは、get で始まるメソッドはメンバの値を返すだけの「軽量アクセサ」であるという規約に慣れ親しんでいる。

らしい(自分はあまり実感が無いが…)。

その他、C++標準ライブラリのlist.size()等、データ量によっては処理に非常に時間がかかるメソッドに、一見すると軽そうな名前がつけられていると、軽い気持ちで使ってしまい、結果として処理がものすごく遅くなったりする。

まとめ

最善の名前とは、誤解されない名前である。

『Web API デザインの鉄則』第2章 読書メモ

WEB+DB PRESS Vol.82

第1章で、「Web APIをリリースするまでに決めなければならないこと」として、以下の5項目が挙げられています。

  1. 認可(Authorization)方式の決定
  2. リソース設計
  3. インタフェース設計
  4. エラー表現
  5. ドキュメント

このうち、第2章では「リソース設計」を扱っています。

リソースの定義

Web+DB Pressの記事の方ではEメールを送信するためのドメインを例に挙げてリソース設計を行っていますが、本記事ではブログの「記事(post)」をリソースとして設計してみます。

シンプルなブログ記事に必要な項目は以下のようなものになります。

  • タイトル
  • 本文
  • 状態
  • 作成日
  • 更新日

これを表にすると以下のようになります。人間には読みやすいですが、この表を機械に読み取らせてバリデーションさせるのは難しい。

フィールド名 名称 データ型 詳細
title タイトル string 記事タイトル。255文字まで。
content 本文 string 記事本文。65535文字まで。
is_public 状態 boolean 記事の状態。下書き(false)・公開(true)のいずれか。デフォルトはfalse。
created 作成日 string 記事作成日。ISO 8601形式の時刻を表す文字列。
updated 更新日 string 記事更新日。ISO 8601形式の時刻を表す文字列。

postリソースの例は以下のようになります。

記事では、ここで、データを定義するためのフォーマットとしてJSON Schemaを使用しています。

公式サイトによると、JSON Schemaの特徴は以下のように紹介されています。

JSON Schema
describes your existing data format
clear, human- and machine-readable documentation
complete structural validation, useful for
automated testing
validating client-submitted data

JSON Schemaは、データのフォーマットを定義するための仕様で、人間にも機械にも読みやすい。自動テストやクライアントの送信した値のバリデーションに便利、とのこと。

読みやすさ・書きやすさに関しては、XMLよりはマシかな程度ですね。読みやすさに関しては、JSON Schemaを表形式に変換するツール等があれば改善されそうです。書きやすさに関しても、ymlで書いてJSONに変換すればだいぶマシになるかもしれません。

JSON Schemaの最大のご利益は、このフォーマット(リソースの仕様)をそのままバリデーション等に使えることです。例えばPHPでもJSON Schemaに基づくバリデーターはいくつか実装されており、最も人気があるのはjustinrainbow/json-schemaです。

※PHPでのJSON Schemaの利用法に関しては、こちらの記事が参考になります。