2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

enumを利用して複数の識別子を受け付けるAPIを呼び出す

Last updated at Posted at 2019-12-03

userIDやUUIDを同じパラメータとして扱い、サーバー側でよしなに判別するAPIを呼び出す時にどのように書けば良いかを考えていきます。

GET /v1/users/{user_identity}

このAPIのuser_identityは次のようにuserのidでもUUIDでも呼び出すことができます。

GET /v1/users/123456
GET /v1/users/AAAAA-BBBB-CCCCC-DDDD

このAPIを呼び出すために2つのメソッドを定義しました。

func fetchUser(byID id: Int) {
  request(url: "/v1/users/\(id)")
}

func fetchUser(byUUID uuid: String) {
  request(url: "/v1/users/\(uuid)")
}

内部の処理は同じなので、次のように一つのメソッドにまとめてみます。

func fetchUser(by id: Int? = nil, uuid: String? = nil) {
    if id == nil && uuid == nil {
        fatalError()
    }
    if id != nil && uuid != nil {
        fatalError()
    }
    if let id = id {
        request(url: "/v1/users/\(id)")
    } else if let uuid = uuid {
        request(url: "/v1/users/\(uuid)")
    }
}

fetchUserは、idかuuidを埋めれば適切にapiを呼ぶようになりました。
ただし、idとuuidはどちらか一つを与えるようにしなくてはfatalErrorが発生します。


fetchUser(uuid: userUUID) //OK
fetchUser() // Crash
fetchUser(by: userID, uuid: userUUID) // Crash

あなたは実装者なのでこのパラメータの与え方のルールを知っていますが、他の開発者は中のコードを読むか、あなたが書いたコメントを読むか、はたまた間違えて呼んでクラッシュするのを確認しないと、気がつくことは出来ません。
不正な呼び出しをコンパイルの時点で気が付けない事も良くないですね。

そこで、Swiftの強力なenumを利用します。


enum UserIdentity {
    case id(Int)
    case uuid(String)
}

func fetchUser(by identity: UserIdentity) {
    switch identity {
        case .id(let id):
            request(url: "/v1/users/\(id)")
        case .uuid(let uuid):
            request(url: "/v1/users/\(uuid)")
    }
}

fetchUser(by .uuid(userUUID))

このようにenumで識別子を管理する事で、fetchUserを呼ぶには必ず任意の識別子を一つ指定する制約が生まれました。
間違えた呼び方をしてビルドすることはもう出来ません。


おまけ

今回のケースでは、APIのパスをenumが生成することで次のように書く事もできます。

enum UserIdentity {
    case id(Int)
    case uuid(String)
}

extension UserIdentity {
    var path: String {
      switch identity {
        case .id(let id):
          return "/v1/users/\(id)"
        case .uuid(let uuid):
          return "/v1/users/\(uuid)"
      }
    }
}

func fetchUser(by identity: UserIdentity) {
    request(url: identity.path)
}

fetchUser(by .uuid(userUUID))

メソッドの内部実装をシンプルにする事で、可読性が上がり処理が追いやすくなります。
これが正解かはプロジェクトの状況に寄りますが、可読性の高いコードを追求してみましょう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?