Upgrade to Pro — share decks privately, control downloads, hide ads and more …

社内勉強会vol.2@ごーふぁー荘

Aya Ebata
November 18, 2022

 社内勉強会vol.2@ごーふぁー荘

Aya Ebata

November 18, 2022
Tweet

More Decks by Aya Ebata

Other Decks in Programming

Transcript

  1. こんな感じのサービス作ってます CRMツール 決済基盤 ・エクセルなど複数のシステムに分散  している卒業生・寄付者名簿を  名寄せ・統合して管理 ・名簿情報をさまざまな項目で簡単に  フィルタリングして抽出 ・HTMLメールをパソコン画面上で  簡単に作成し、名簿から配信可能

    ・配信したメールの到達率、開封率など  の分析機能も標準で提供 ・寄付決済、会費決済向けの様々な  決済手段をワンストップで提供 ・決済情報は名簿情報と自動的に連携 大学支援者・関係者の名寄せ〜名簿管理 寄付マーケティングに必要なツール群 寄付者のデータが名簿に 自動連携される決済ツール コミュニティ ・卒業生検索・キャリアサービスなど  在校生や卒業生への便益提供が可能 ・名簿情報と自動連携されており、  最新の個人情報に更新できる 在校生・卒業生ネットワークの アクティベーション
  2. OpenAPI - RESTful APIのインターフェースを定義するための言語 - OpenaAPIを使うことで人間とコンピュータの両方が理解しやすくなる - OpenAPIを使用することで… - GUIでドキュメントを表示することができる

    - サーバーとクライアントコードを生成できる  など、いろんな使い方がある Swagger - OpenAPIを使ってRESTful APIを設計するためのツールセットのこと - エディタ、ドキュメントの表示、生成などをするためのツールが提供されている OpenAPIとは?
  3. - スキーマ駆動ができる! - バックエンドとフロントエンドで意思疎通しやすい!! - めちゃくちゃ恩恵受けれた - バックエンドだけでなくフロントエンドも自動生成できる! - ドキュメントとして使うだけではない!!

    - 十分にプロダクトで使えるソースコードを生成できる - mockサーバを立ち上げられる - SDKなどを使って別リポジトリにすると言語依存がある - OpenAPIなら言語関係なくHTTPでやり取りできるインターフェースが書ける - クライアントコードも生成できるので書きやすい OpenAPIを使うことにした背景
  4. ドキュメントを書くためのエディタ - Swagger Editor - https://editor.swagger.io/ - Goland - OpenAPI

    Specificationのプラグインを用いて ドキュメントの表示 - 現状サーバにあげたりしてないのでエディタのプレビュー機能で表示 使用ツール
  5. Alumnoteの場合 - Dockerで実行できるコマンドを用意 - バージョン依存を避けるため - makeコマンドを用意 - コマンド共有めんどくさいのでw -

    modelとserverとspecで分けて生成してる - configファイル書いて分けてる 生成方法 $ go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest $ oapi-codegen petstore-expanded.yaml > petstore.gen.go
  6. OpenAPIのドキュメント docs/  └ openapi/    ├ crm.yaml    └ foundation.yaml ディレクトリ構成 Goのソースコード

    alumnote-crm-api/  └ src/    └ openapi/      ├ model.cfg.yaml … modelの設定ファイル      ├ model.gen.go … modelの生成されたファイル      ├ server.cfg.yaml … serverの設定ファイル      ├ server.gen.go … serverの生成されたファイル      ├ spec.cfg.yaml … specの設定ファイル      └ spec.gen.go … specの生成されたファイル
  7. 深い構造のjsonでrefを切らない場合… OpenAPIのドキュメント → 工夫したこと ListUsersResponse: type: object required: - data

    - total properties: data: type: array items: type: object required: - id - organization_id properties: id: type: string format: uuid organization_id: type: string format: uuid total: type: integer
  8. 深い構造のjsonでrefを切らない場合… 生成されたソースコード ↓ - 構造体の構造体になってしまう… - しかも配列なのでforループで回して代入したい時にやりにくい… 工夫したこと // ListUsersResponse

    defines model for ListUsersResponse. type ListUsersResponse struct { Data []struct { Id openapi_types.UUID `json:"id"` OrganizationId openapi_types.UUID `json:"organization_id"` } `json:"data"` Total int `json:"total"` }
  9. 深い構造のjsonでrefを切った場合… OpenAPIのドキュメント ↓ 工夫したこと ListUsersResponse: type: object required: - data

    - total properties: data: type: array items: $ref: '#/components/schemas/User' total: type: integer User: type: object required: - id - organization_id properties: id: type: string format: uuid organization_id: type: string format: uuid
  10. 深い構造のjsonでrefを切った場合… 生成されたソースコード ↓ - 別の構造体に生成してくれるため、使いやすい! 工夫したこと // ListUsersResponse defines model

    for ListUsersResponse. type ListUsersResponse struct { Data []User `json:"data"` Total int `json:"total"` } // User defines model for User. type User struct { Id openapi_types.UUID `json:"id"` OrganizationId openapi_types.UUID `json:"organization_id"` }
  11. requiredなしの場合… OpenAPIのドキュメント ↓ 工夫したこと ListUsersResponse: type: object properties: data: type:

    array items: $ref: '#/components/schemas/User' total: type: integer User: type: object properties: id: type: string format: uuid organization_id: type: string format: uuid
  12. requiredなしの場合… 生成されたソースコード ↓ - ポインタだらけ>< 工夫したこと // ListUsersResponse defines model

    for ListUsersResponse. type ListUsersResponse struct { Data *[]User `json:"data,omitempty"` Total *int `json:"total,omitempty"` } // User defines model for User. type User struct { Id *openapi_types.UUID `json:"id,omitempty"` OrganizationId *openapi_types.UUID `json:"organization_id,omitempty"` }
  13. requiredありの場合… OpenAPIのドキュメント ↓ 工夫したこと ListUsersResponse: type: object required: - data

    - total properties: data: type: array items: $ref: '#/components/schemas/User' total: type: integer User: type: object required: - id - organization_id properties: id: type: string format: uuid organization_id: type: string format: uuid
  14. requiredありの場合… 生成されたソースコード ↓ - ポインタじゃなくなる! 工夫したこと // ListUsersResponse defines model

    for ListUsersResponse. type ListUsersResponse struct { Data []User `json:"data"` Total int `json:"total"` } // User defines model for User. type User struct { Id openapi_types.UUID `json:"id"` OrganizationId openapi_types.UUID `json:"organization_id"` }
  15. OpenAPIのドキュメント ↓ 工夫したこと ProfileRowForSearchConditionModel: description: 範囲指定をする場合は dateRangeを使う。 type: object required:

    - profile_column_id - value properties: profile_column_id: type: string format: uuid value: oneOf: - $ref: '#/components/schemas/ProfileRowValue' - $ref: '#/components/schemas/DateRange'
  16. 生成されたソースコード ↓ 工夫したこと // 範囲指定をする場合は dateRangeを使う。 type ProfileRowForSearchConditionModel struct {

    ProfileColumnId openapi_types.UUID `json:"profile_column_id"` Value interface{} `json:"value"` } // ProfileRowValue defines model for ProfileRowValue. type ProfileRowValue interface{} // DateRange defines model for DateRange. type DateRange struct { End *openapi_types.Date `json:"end,omitempty"` Start *openapi_types.Date `json:"start,omitempty"` }
  17. - CIで自動生成 - 差分のプルリクを自動で投げるなど… - 開発人数増えると生成のタイミングとフローが改修に影響するからどうするか - Aさん: OpenAPIのドキュメントを変更し、ソースコード側の変更を忘れる… -

    Bさん: OpenAPIのドキュメントを変更し生成したら自分が変更したところ以外も差分が 出る -> 修正範囲が大きくなる - ↑みたいになりそう、とか… 今後工夫していきたいこと