はじめに
継続的な運用が必要な API を作成・運用したことがあるひとなら誰でもぶつかる問題の一つがリファクタリング。既存で走らせている API があるが、もともとの設計が良くなかった、作ったときとは状況が変わったために使いづらくなった、など様々な理由でリファクタリングをする必要が生じる場合があると思います。この記事ではなるべく問題の少ない方法でリファクタリングする方法を考えてみたので紹介します。
なお、前提条件として、サーバー側とクライアントが同時にアップデートできない状況(クライアント側がアプリである場合など)とし、API の例として書籍のデータを JSON データを通信に使用して読み書きするシステムを例とします。
ケース1: API のパラメータ名を変更したい
以下のように、書籍のリストを取得する API があったとします。パラメータとして sort をとり、指定されたフィールド名で昇順でソートされるとします。
GET /api/v1/book/book?sort=[filed_name]
sort (英語の意味:並び替えすること)はソートするフィールドを表す単語としては適切でないと判断し、orderBy と変更したいとします。この場合、すでに存在するsort
とorderBy
を両方サポートする期間を設け、その期間を経過した後にsort
パラメータを廃止します。
ケース2: API の URL path を変更したい
ID を指定して一つの書籍のデータを取る API があったとします。
GET /api/v1/book/getBook/:id
getBook
という名前は REST の考え方とあっていなかったのでbook
というリソースを意識した名前に変更したいとします。この場合もパラメータ名の変更と同様に以下の2つの path を生かした期間を設け、その期間を経過した後にgetBook
を使用している path を削除するとよいでしょう。
GET /api/v1/book/getBook/:id
GET /api/v1/book/book/:id
ケース3: API が返すモデルのなかのフィールドの型を変更したい
以下のような Book モデルがあったとします。
{
id: number
title: string
description: string
author: string
}
それを以下のようにauthor
をstring
から Author モデルに変更したいとします。
{
id: number
title: string
description: string
author: Author {
name: string
age: number
}
}
ここでは注意が必要です、author フィールドはもともとstring
であったため、単純にstring
からAuthor モデル
にしてしまうとクライアントでパースエラーが出てしまうことは目に見えています。そこで、一度 authorModel というフィールド名を経由して最終的に author とする方法をとります。上述のように、author と authorModel の両方のフィールドをそれぞれstring
、Author モデル
でサポートする期間を設ける。その後、author をAuthor モデル
に変更し、author と authorModel 両方をAuthor モデルで
サポートする期間を設けます。その後、authorModel フィールドを削除します。かなり回りくどいですがこれは仕方ないですね ....
ケース4: API の返すモデルのあるフィールドが必要なくなった
以下の Book モデルがあったとします。
{
id: number
title: string
description: string
}
システム開始当初、description フィールドを用意したはいいものの、実際にはほとんど使用されておらずデータ量を増やして DB 維持コストを増やしている原因であるので削除することにしたとします。期限を設けてクライアント側の開発者に対処してもらうのですが、もしかするとクライアント側が対応した後もユーザーが古いクライアントを使用していることも考えられますので、DB から description のデータを削除した後も description フィールドに空文字を入れた状態にすると、少なくともクラッシュを防げる状態になると思います。
最後に
クライアントが API のアップデートと同時にアップデートできないケースではこのような回り道をどうしてもしなければなりません。これは保守するエンジニアにとって負担のかかることです。スタートアップでリソースかつかつだよ〜(僕もそう)という場合には、API アクセス数を計測しておけば、使用者が限りなく少ない API に関してはえいやで API を落としてしまうという判断も場合によってはあるかもとは思います。(クライアント側でその機能だけ動かないがとりあえずクラッシュしない状態には最低限しておく必要がある)