$30 off During Our Annual Pro Sale. View Details »

仕事でWeb API開発するときに考えていること / 技育CAMPアカデミア2023

仕事でWeb API開発するときに考えていること / 技育CAMPアカデミア2023

2023年5月10日(水) サポーターズ主催「技育CAMPアカデミア」で開催されたCARTA HOLDINGSセッションの発表資料です。

・登壇者
株式会社CARTA HOLDINGS
所属: 株式会社fluct アドプラットホーム事業本部 データエンジニアリングチーム
名前: 鈴木 進也 (すずき しんや)
twitterアカウント: @YangYang_pareto
自己紹介: fluctというアドテクの会社でWeb API開発をしたりデータエンジニアリングをしています。三度の飯よりキーボードが好きです。

CARTA Engineering

May 10, 2023
Tweet

More Decks by CARTA Engineering

Other Decks in Technology

Transcript

  1. 仕事でWeb API開発するときに考えているこ

    技育CAMP 2023
    CARTA HOLDINGS Inc.

    View Slide

  2. ● yanyan
    ● 新卒3年目
    ● 株式会社fluct アドプラットフォーム事業本部
    ○ データエンジニアリングや API開発してます
    自己紹介
    CARTA HOLDINGS Inc.

    View Slide

  3. 今日のサンプルコードは Githubにおいてあります
    https://github.com/shinya-ml/geeksai-backend-study
    サンプルプログラム
    CARTA HOLDINGS Inc.

    View Slide

  4. ざっくりしたWebアプリケーションの構成
    CARTA HOLDINGS Inc.

    View Slide

  5. ざっくりしたWebアプリケーションの構成
    CARTA HOLDINGS Inc.
    この部分を作るときに考えていることを話します

    View Slide

  6. 認知負荷の話
    01
    アプリケーションのアーキテクチャの

    02
    APIの設計について
    03
    テストの話
    04
    CARTA HOLDINGS Inc.
    思想を言語化する
    04

    View Slide

  7. 認知負荷の話

    View Slide

  8. 人が学習する際にかかる記憶領域に対する負荷
    ● 開発には様々な認知負荷がかかる
    ○ コードの意図を読み取る、アーキテクチャの理解 etc…
    ● A Philosophy of Software Design では、ソフトウェアの複雑性が増大している兆候の一つとしてあ
    げられている
    ● 自分は普段の開発で認知負荷が高くなりすぎていないか?を気にしている
    認知負荷とは
    CARTA HOLDINGS Inc.

    View Slide

  9. ● 認知負荷が高いものは理解するのが難しい
    ● 理解が不十分なままコードの修正や書き足しをすると、 より複雑度が高まってしまう
    ○ 認知負荷の高いコードは、さらなる認知負荷の上昇をもたらす
    ● 規模が大きくなるにつれて複雑性の増加は避けられない
    ○ 工夫して複雑になりすぎないようにすることはできる
    なぜ認知負荷を気にしているのか
    CARTA HOLDINGS Inc.

    View Slide

  10. アーキテクチャの話

    View Slide

  11. 実際はインフラの構成とかもスコープだが今回はアプリケーションコードの構造の話
    ● アプリケーションの実装をレイヤーごとに分けて整理する
    ● レイヤーに分けると何が嬉しい?
    ○ 関心事の分離
    ○ 依存関係の整理
    1からコードを書いていくときに、どうやってレイヤー構造を考えていくか
    ここでいうアーキテクチャとは
    CARTA HOLDINGS Inc.

    View Slide

  12. ● レイヤードアーキテクチャ
    ● ヘキサゴナルアーキテクチャ
    ● オニオンアーキテクチャ
    ● クリーンアーキテクチャ
    ● etc…
    よく目にするアーキテクチャたち
    CARTA HOLDINGS Inc.
    [画像の出典] Ready for changes with Hexagonal Architecture, Clean
    Architecture

    View Slide

  13. いかなるアプリケーションに対しても最適なアーキテクチャなどない
    彼らは銀の弾丸ではない
    CARTA HOLDINGS Inc.

    View Slide

  14. ● そのアプリケーションにとって妥当なアーキテクチャは 開発が進むにつれて変化していく
    ● 小規模な段階から壮大なアーキテクチャにすると大体辛い
    ○ ほとんど何もしてないレイヤーが生まれる
    ○ 意味のない抽象化 (具体的な実装が一つしか無い )
    ○ なぜそのレイヤーが存在しているのかわからない = 認知負荷が高い
    必要なときに必要な変更をする
    CARTA HOLDINGS Inc.

    View Slide

  15. ● handler: HTTP リクエストを受けてレスポンス返す
    ● repository: DBとやりとりする
    ● entity: アプリケーションで扱うオブジェクトを定義する
    例えば
    CARTA HOLDINGS Inc.
    handler
    repository
    entity DB
    依存の流れ
    単にCRUDするだけならこれくらい素朴な構成でもよい

    View Slide

  16. ● ビジネスロジックを書く層がほしい!
    ○ 必要になったら足せば良い
    扱う関心事が増えた
    CARTA HOLDINGS Inc.
    handler
    repository
    entity DB
    usecase

    View Slide

  17. ● repositoryに依存する層のユニットテストをしたい
    ○ repositoryの部分はフェイクに差し替えたい
    ● インターフェースに依存する形にする
    抽象化したい
    CARTA HOLDINGS Inc.
    handler
    repository
    interface
    repository
    implementation
    repository
    mock
    entity DB

    View Slide

  18. 1. 関心事の分離
    2. 依存の流れを1方向にする
    これらを守りながら、 その時々でベストな設計を模索する
    何が大事かは関わる人とかサービスの特性によって変わってくる
    依存関係を整理するときに大事なこと
    CARTA HOLDINGS Inc.

    View Slide

  19. ● 関心事とは
    ○ 自分が主に取り扱おうとしているトピック、対象
    ○ e.g.) DBとのやりとり、HTTP req/resについて etc…
    関心事の分離
    CARTA HOLDINGS Inc.

    View Slide

  20. ● まずはどんな関心事が存在するのか言語化することが大事
    ● 1レイヤーが複数の関心事を扱わないようにする
    ○ e.g.) ファットコントローラー
    関心事の分離
    CARTA HOLDINGS Inc.

    View Slide

  21. ● 認知負荷が低い
    ○ 触りたい実装がどこにあるか把握しやすい
    ○ e.g.) DB周りはrepository層をみればいい
    ● 変更しやすい
    ○ どこを修正すればいいか明確
    ● 壊れたときに直しやすい
    ○ どこで壊れたか特定しやすい
    各層が1つの関心事だけを扱っていると何が嬉しい?
    CARTA HOLDINGS Inc.

    View Slide

  22. ● レイヤー構造を成すので、レイヤー間に 依存関係が生まれる
    ● 依存とは
    ○ 依存される側の知識が依存する側に漏れ出ている状態
    ○ メソッドの呼び出しに必要な引数とか
    ● 依存される側に変更が入ると、する側も影響を受ける
    ○ あるモジュールが依存したりされまくったりしている(密結合)と辛い
    依存関係
    CARTA HOLDINGS Inc.

    View Slide

  23. ● 依存の向きを交通整理する
    ● 具体的な関心事を扱うレイヤー → 抽象的な関心事を扱うレイヤーという依存の流れを作る
    ○ 具体的な関心事: 特定の技術に関すること (DBとかGraphQLとか...)
    ○ 抽象的な関心事: アプリケーションが扱うドメインコアなこと (ビジネスロジックとか ...)
    依存の流れを1方向にする
    CARTA HOLDINGS Inc.

    View Slide

  24. ● サービスのコアとなる部分が特定の技術に依存しない
    ○ 変更しやすい
    ● ある技術を差し替えてもサービスのコアには影響しない
    具象 → 抽象の向きで依存させる
    CARTA HOLDINGS Inc.

    View Slide

  25. つまり、具体的な知識がビジネスロジックに漏れ出る
    ● e.g.) MySQLの知識がusecase層で必要になる
    具体的な関心事が漏洩すると ...
    ● 円の外側に対する変更で内側も影響を受ける
    ● 技術の差し替えが難しくなる
    抽象 → 具象という依存があるとどうなる?
    CARTA HOLDINGS Inc.

    View Slide

  26. ● アプリケーションにレイヤー構造を設けることで依存関係が整理される
    ● 関心事を適切に分けよう
    ● 何を守りたいか?を考えながら、必要に応じてアーキテクチャは変化させよう
    まとめ
    CARTA HOLDINGS Inc.

    View Slide

  27. API設計の話

    View Slide

  28. APIをどういう形式で提供するかは、いくつか選択肢がある
    ● REST
    ○ リソースベースのURI
    ○ JSON形式でデータをやり取りする
    ○ 長いこと使われてる
    ● gRPC
    ○ Protobuf形式でやり取りする
    ○ マイクロサービス間の通信とかで使われてる
    ● GraphQL
    ○ クエリ言語 + クエリに対するサーバーサイド実装
    ○ クエリする側が柔軟に欲しいデータを持ってこれる
    APIのスタイル
    CARTA HOLDINGS Inc.

    View Slide

  29. ● ユースケースに応じて使い分けよう
    ○ 銀の弾丸などない
    ● GraphQLはRESTの上位互換とか、そんなことはない
    ○ RESTのほうがいい場合もある
    大前提
    CARTA HOLDINGS Inc.

    View Slide

  30. ● APIの利用者
    ○ 誰が使うんだっけ
    ○ どのくらい使われるんだっけ
    ● ユースケースの数
    ○ 利用者が多様でユースケースも様々なんだよねーとか
    ● サービス的になにを重要視するか
    ○ APIとしての柔軟性?
    ○ パフォーマンス? etc…
    どういう軸で考えるのか
    CARTA HOLDINGS Inc.

    View Slide

  31. ● REST
    ○ リソースベースでエンドポイントを生やすので、 1つのAPIで色々なユースケースに対応しよう
    とすると辛くなりがち
    ○ 1APIのユースケースが単純ならわかりやすい
    ● GraphQL
    ○ クエリによって利用者側が柔軟に欲しいデータを記述できるのでユースケースが多様な場合
    に対応しやすい
    ○ エラーハンドリングが難しい
    ● gRPC
    ○ パフォーマンス重視ならこれかな
    ○ 内部向けのAPIかくなら、型もかっちり書けるしよさげ
    ざっくりとした私の所感
    CARTA HOLDINGS Inc.

    View Slide

  32. 正しい使い方をするのが簡単で、間違った使い方をするのが難しい
    ● APIを使う側のことを考えて設計する
    ● 適切にドキュメンテーションする
    ● 命名の一貫性
    ● レスポンスの設計
    良いAPIとは?
    CARTA HOLDINGS Inc.

    View Slide

  33. APIの形式によって気をつけたいことも変わってくる
    RESTなら...
    ● エンドポイントのURIはわかりやすいか
    ● クエリパラメータやリクエストボディの設計
    GraphQLなら...
    ● スキーマ設計
    ○ 命名の一貫性
    ○ nullの使い分け
    ● Production Ready GraphQL という本がおすすめ
    例えば
    CARTA HOLDINGS Inc.

    View Slide

  34. テストの話

    View Slide

  35. ● ユニットテスト
    ○ あるモジュール単体の振る舞いに対するテスト
    ● インテグレーションテスト
    ○ 複数のモジュールを跨いだテスト
    ○ DBのような、アプリケーションの外側とのテストも含む
    APIサービスに対するテストは色々ある
    CARTA HOLDINGS Inc.

    View Slide

  36. Q. どのテストを書けばいい?
    CARTA HOLDINGS Inc.

    View Slide

  37. A. 全部書けばいいやん
    Q. どのテストを書けばいい?
    CARTA HOLDINGS Inc.

    View Slide

  38. A. 全部書けばいいやん
    Q. どのテストを書けばいい?
    CARTA HOLDINGS Inc.

    View Slide

  39. ● リリース前にバグに気づく
    ● 変更することに対する安全性、容易性
    ● テスト対象のコードの理解を助ける
    ● etc…
    つまり、開発における様々な不安を取り除く
    なぜテストを書きたいのか
    CARTA HOLDINGS Inc.

    View Slide

  40. テストを書くことで、不安を取り除きたい箇所
    ● リリース後に壊れると致命的な箇所
    ○ お金が絡んだりしてあとから直すのが辛いとか
    ● サービス的に大事なロジックが書かれている
    ○ ECサイトなら決済とか、注文のキャンセルとか
    ○ いわゆるビジネスロジック
    どこにテストを書きたい?
    CARTA HOLDINGS Inc.

    View Slide

  41. 特段不安がないとか、テストのコスパが悪そうな箇所にはテストは書かない
    ● テストコードにもメンテコストはかかる
    ● テストの実行に時間がかかると人々はテストしなくなる
    → テストしたいところだけテストする
    テストを書かないという選択
    CARTA HOLDINGS Inc.

    View Slide

  42. ● 公開された振る舞い
    ○ 依存しているモジュールから呼び出されるようなメソッド
    ● 実装詳細
    ○ モジュール内で完結しているメソッド
    ○ 外部から利用されることはない
    公開された振る舞いと実装詳細
    CARTA HOLDINGS Inc.

    View Slide

  43. 基本的に公開された振る舞いしかテストしない
    ● 外部から見える振る舞いが担保されてればよい
    ● 詳細がテストされていると、リファクタリングしにくい
    ○ 振る舞いは変わらないがその中身が変わるときに、テストも直す必要が出てくる
    実装の詳細はテストしない
    CARTA HOLDINGS Inc.

    View Slide

  44. 右図のような構造で、以下のことを考えてみる
    ● 何のテストを書きたいか
    ● 何のテストを書かないか
    各レイヤーの関心事
    ● handler: HTTP req/res
    ● usecase: ビジネスロジック
    ● repository: DBとのやりとり
    ● entiry: ビジネスオブジェクトとその振る舞い

    CARTA HOLDINGS Inc.

    View Slide

  45. あくまで例、サービスの特徴によって変わる
    単純な構造なので、書きたいテストはそんな多くない
    ● usecase層のユニットテスト
    ● (ロジックがあれば)entity層のユニットテスト
    ● handler ~ repositoryまで一気通貫のインテグレーションテスト
    何のテストを書きたいか
    CARTA HOLDINGS Inc.

    View Slide

  46. あくまで例(ry
    ● handlerのユニットテスト
    ● repositoryのユニットテスト
    ● repository - DB間のインテグレーションテスト
    何のテストを書かないか
    CARTA HOLDINGS Inc.

    View Slide

  47. handlerのユニットテスト
    ● HTTP req/resが関心事
    ○ それ以外の殆どの処理は他の層に移譲している
    ○ つまり、テストしたいロジックがほとんどない
    ● この層にテストしたいロジックがあったら、関心事の分離がうまくできていないかも?
    なんで書かない?の一例
    CARTA HOLDINGS Inc.

    View Slide

  48. ● なぜテストを書き、何をテストしたいのか
    ● 意図がわからないテストは後々辛い
    ○ プロダクションコードの変更でテストがコケたとき直しづらい
    ○ そのテストの存在理由がわからないとメンテもされない
    本当にテストしたいところにテストを書こう
    テストは意図が大事
    CARTA HOLDINGS Inc.

    View Slide

  49. 思想を言語化しよう

    View Slide

  50. ● なぜこのアーキテクチャにした?
    ● なぜこの言語を選んだ?
    ● なぜGraphQLを採用した?
    こうしたWhyに対する答えは、意図的に言語化しないと残らない
    Whyはコードを読んでもわからない
    CARTA HOLDINGS Inc.

    View Slide

  51. ● 理解の助けになる
    ● あとから反省する材料になる
    ● アーキテクチャやテストに手を入れる際、既存のものの意図を知ることは大事
    ○ 今あるものがなぜこうなっているかを知った上で、どう変えると良いかを考える
    Whyの言語化はなぜ大事なのか
    CARTA HOLDINGS Inc.

    View Slide

  52. システムを作り始める前に書く地図のようなもの
    ● これから作るシステムが目指すゴール
    ● どういう設計で作るのか
    ● システムがスコープとしないこと、やらないこと
    などを書く
    ● システムを作るにあたって必要な意思決定が言語化される
    ● 意思決定に至ったWhyも書く
    Design Docを見ればシステムのゴール、意思決定の Whyが分かる状態にする
    Design Doc
    CARTA HOLDINGS Inc.

    View Slide

  53. 特定の意思決定に関することを記述する
    ● 背景
    ● なぜこの意思決定をしたのか
    ● 他にどんな選択肢があったのか
    作り始めてから行われる変化の意思決定は ADRで言語化するとわかりやすい
    Architecture Decision Record (ADR)
    CARTA HOLDINGS Inc.

    View Slide

  54. ● 認知負荷を意識して開発する
    ● アーキテクチャもテストも必要だと思ったことをやればよい
    ○ 必要に応じてあとから変化させれば良い
    ● なぜやる(やらない)のかが大事
    ● コードでは伝わらないことは積極的に言語化していこう
    おわりに
    CARTA HOLDINGS Inc.

    View Slide

  55. CARTA HOLDINGSのテックブログを読んでみてね
    ● https://techblog.cartaholdings.co.jp/entry/2022/10/20/100730
    今日の内容を実践した話
    CARTA HOLDINGS Inc.

    View Slide

  56. もの創り実践プログラム
    「Treasure」
    ● 内容
    「Go言語を使って学ぶ、
    価値のあるもの創りとチーム開発」
    ● 日時
    8/7~8/25(10:00~18:30)
    ● 形式
    オンライン+オフィス開催(渋谷)
    ● 定員:30名程度
    ● 学年:2025年4月以降に入社可能な方
          ※文理不問、条件に合えば学年不問

    View Slide

  57. 大規模サービス構築プログラム
    「Sunrise」
    ● 内容
    Goの広告アプリケーションサーバを
    AWSに構築し、改修
    大規模リクエストを捌くために必要な
    設計・構築について学べます
    ● 日時
    9/11~9/15(10:00~18:30)
    ● 形式
    オフライン開催(渋谷オフィス)
    ● 定員:16名程度
    ● 学年:2025年4月以降に入社可能な方
          ※文理不問、条件に合えば学年不問

    View Slide