Slide 1

Slide 1 text

仕事でWeb API開発するときに考えているこ と 技育CAMP 2023 CARTA HOLDINGS Inc.

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

認知負荷の話 01 アプリケーションのアーキテクチャの 話 02 APIの設計について 03 テストの話 04 CARTA HOLDINGS Inc. 思想を言語化する 04

Slide 7

Slide 7 text

認知負荷の話

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

アーキテクチャの話

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

API設計の話

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

テストの話

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

思想を言語化しよう

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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