GraphQLのインラインフラグメントが難しい(難しい)
GraphQLのインラインフラグメントが難しい - yujioramaの日記
GraphQLの「境界条件(コーナーケース)」における挙動を、複数の言語実装(Go, Node.js, Ruby, Perl)とルーター(Apollo Router, Apollo Gateway, Cosmo)の組み合わせで検証した結果をまとめました。
検証の背景と環境
GraphQLのスキーマが複雑になった際、インラインフラグメントで定義したフィールドが正しくマージされるかは、実装によって差異があるのではないか?という疑問というか実際に困った経験から検証をスタートしました。
検証用に作成した環境は以下の通りです。
- 共通スキーマ:
AbstractProductやAbstractItemといったインターフェースを含む構成 - バックエンド実装:
- Go: gqlgen
- Node.js: Apollo Server
- Ruby: graphql-ruby
- Perl: graphql-perl
- ルーター (Federation):
実験1:インラインフラグメントにネストしたオブジェクトのマージ
検証内容
インターフェース(AbstractProduct)に対するインラインフラグメントの中で、ルートフィールドと同じオブジェクト(package)をさらに深く選択した場合に、正しくマージされるかを検証します。
クエリ:
query MergeConcreteTypeInRootFieldAndInterfaceFragment { productA { package { id name } ... on AbstractProduct { ...ProductDetail } } } fragment ProductDetail on AbstractProduct { ... on ProductA { package { displayOwner: owner { name } owners { name } } } }
検証結果
期待される動作は、ルートで指定した id, name と、フラグメント内で指定した displayOwner 等が合体して返ってくることです。
| 構成 | 結果 | 備考 |
|---|---|---|
| バックエンド単体 (Go, Node, Perl, Ruby) | ✅ 成功 | すべての実装で正しくマージされました |
| Apollo Router | ✅ 成功 | |
| Apollo Gateway | ❌ 失敗 | フラグメント内のネストしたフィールドが消える |
| WunderGraph Cosmo | ❌ 失敗 | 同上 |
Apollo GatewayやCosmoでは、インラインフラグメント側のネストしたフィールドが無視されてしまうという興味深い結果になりました。
実験2:リスト型フィールドを含むインラインフラグメントのマージ
検証内容
リスト型のフィールド(productList)を持つインターフェースに対して、フラグメントを介してデータを取得する際の挙動を検証します。
クエリ:
query MergeInlineFragment { itemList { __typename ...ItemA ...ItemB } } fragment ItemA on ItemA { name productList { package { id } } }
検証結果
このケースでは、バックエンドの実装レベルで明確な差が出ました。
| バックエンド実装 | 結果 | エラー内容 |
|---|---|---|
| Go (gqlgen) | ✅ 成功 | |
| Node.js (Apollo) | ✅ 成功 | |
| Perl (graphql-perl) | ❌ 失敗 | Can't call method "isa" on an undefined value |
| Ruby (graphql-ruby) | ❌ 失敗 | 500 Internal Server Error |
PerlやRubyの実装では、ルーターの有無にかかわらずバックエンド単体で実行しても、リスト型のインターフェース処理中に内部エラーが発生しました。 複雑なフラグメントとリストが組み合わさるケースでは、ライブラリの成熟度が影響するようです。
まとめ
今回の検証を通じて、以下のことが分かりました。
- ルーターによる挙動の差: Apollo Routerはマージ処理が強力ですが、Apollo GatewayやCosmoでは一部のネストした選択セットが欠落する場合があります。
- 言語実装による制限: GoやNode.jsの実装は安定していますが、PerlやRubyの実装では、複雑なリスト・インターフェースの組み合わせでランタイムエラーが発生することがあります。
- フィールドリゾルバーの実装方法によっては正しい挙動になる可能性があります
- 各ライブラリのバージョンアップにより挙動が改善される可能性があります
GraphQLは「どこでも同じように動く」ことが期待されますが、Federation構成や複雑なスキーマを扱う際は、事前の互換性検証が重要であると改めて実感しました。
検証コードは GitHub - yujiorama/graphql-test: testing GraphQL corner case に置いてあります。
GraphQLのインラインフラグメントが難しい
この記事ははてなエンジニア Advent Calendar 2025 21日目の記事です。 昨日の担当は id:fxwx23 さんの SwiftUI.SectionのFooterの末端要素を画面下端にalignさせるテク - 23's blog でした。
GraphQLを使いこなしていくと、インターフェースや共用体(Union)を扱う場面でインラインフラグメント(... on Type)は避けて通れません。
しかし、フラグメントが複雑に組み合わさると、一見正しいはずのクエリが意図しないレスポンスを返したり、ランタイムエラーを引き起こしたりすることがあります。
この記事では、開発現場で発生した問題をベースに、GraphQL Specification(October 2021)の仕様と照らし合わせながら、その正体を解明していきます。
- 前提:検証に使用するGraphQLスキーマ
- 問題1:インラインフラグメントに定義したエイリアスフィールドが消失する
- 問題2:インラインフラグメントによるルートフィールドのマージと消失
- 問題3:インラインフラグメントに同じ名前で異なる型のリストフィールドがあると実行時エラー
- 実際、どの実装なら正しく動くのか?
前提:検証に使用するGraphQLスキーマ
今回の各ケースでは、以下のスキーマ定義を前提としています。AbstractProduct を実装した ProductA/B と、それらをリストで保持する ItemA/B という構造です。
type Package { id: ID! name: String! owner: PackageOwner owners: [PackageOwner!]! } interface AbstractProduct { package: Package! } type PackageOwner { name: String! } type ProductA implements AbstractProduct { package: Package! } type ProductB implements AbstractProduct { package: Package! } interface AbstractItem { name: String! } type ItemA implements AbstractItem { name: String! productList: [ProductA!]! } type ItemB implements AbstractItem { name: String! productList: [ProductB!]! } type Query { productA: ProductA itemList: [AbstractItem!]! }
問題1:インラインフラグメントに定義したエイリアスフィールドが消失する
クエリ
query { productA { __typename package { __typename id name } ... on AbstractProduct { ...ProductDetail } } } fragment ProductDetail on AbstractProduct { ... on ProductB { __typename package { __typename id name displayOwner: owner { __typename name } owners { __typename name } } } ... on ProductA { __typename package { __typename id name displayOwner: owner { name } owners { __typename name } } } }
クエリ構造の視覚化
graph TD
Root[Query] --> productA
subgraph "Selection Set for productA"
productA --> P_Root["package (id, name)"]
productA --> Fragment["... on AbstractProduct (ProductDetail)"]
subgraph "Merged Selection Set for package"
Fragment --> P_Frag["package (id, name, displayOwner: owner, owners)"]
end
end
P_Root -.-> Merge{Merge?}
P_Frag -.-> Merge
Merge --> Final["Problem: displayOwner field might disappear"]
解説:Field Selection Merging の落とし穴
このクエリでは、productA 直下の package と、フラグメント内の package が重複しています。GraphQLの仕様上、これらは一つの選択集合としてマージされるべきです。
しかし、開発現場ではエイリアスフィールドの displayOwner が消失しました。
たぶん原因はサーバー側のマージアルゴリズムの問題で、ルートレベルの単純な定義が、フラグメント内の詳細なエイリアス定義を上書き・無視してしまうようでした。
問題2:インラインフラグメントによるルートフィールドのマージと消失
クエリ
query { productA { __typename package { __typename id name owner { __typename name } owners { __typename name } } ... on AbstractProduct { ...ProductDetail } } } fragment ProductDetail on AbstractProduct { ... on ProductB { __typename package { __typename id name } } ... on ProductA { __typename package { __typename id name } } }
クエリ構造の視覚化
graph LR
subgraph "Query Root Selection"
R["package { id, name, owner, owners }"]
end
subgraph "Fragment Selection"
F["package { id, name }"]
end
R -- "Merged by Spec" --- F
F -- "Masked by Implementation" --> Final["Result: package { id, name } (Missing owner)"]
解説:Selection Set Merging とマスキング
ここではルートで owner を要求していますが、フラグメント側では package を id と name のみで再定義しています。
- 関連仕様: Section 5.5: Fragments
仕様上は和集合になるはずですが開発現場では owner が消失しました。
たぶん原因はサーバー側のマージアルゴリズムの問題で、後から定義された「浅い定義」を優先してデータをフィルタリング(マスキング)してしまうようでした。
問題3:インラインフラグメントに同じ名前で異なる型のリストフィールドがあると実行時エラー
クエリ
query { itemList { ...ItemA ...ItemB } } fragment ItemA on ItemA { __typename name productList { __typename package { __typename id } } } fragment ItemB on ItemB { __typename name productList { __typename package { __typename id } } }
クエリ構造の視覚化
classDiagram
class productList {
<<field name>>
}
class Type_ItemA {
productList: [ProductA!]
}
class Type_ItemB {
productList: [ProductB!]
}
Type_ItemA --|> productList
Type_ItemB --|> productList
productList --|> Conflict : "Same Response Shape Rule Violation"
解説:Same Response Shape の制約
ItemA の productList は [ProductA!] 型であり、ItemB のそれは [ProductB!] 型です。
同一フィールド名(productList)でマージされる際、それらは同じレスポンス形状である必要があります。
現場では GraphQL Federation 環境において発生した問題で、通常の GraphQL サーバーでは発生していません。
ゲートウェイが「サブグラフから返ってきた ProductB は、ItemA 側の定義(ProductA)と互換性がない」と判断しているのかな、という感想です。
実際、どの実装なら正しく動くのか?
いろいろ調べたかったのだけど実験が終わってないので、別の機会にまとめようと思います。
- GraphQL Server: Node (Apollo), Go (gqlgen), Ruby, Perl
- Gateway/Router: Apollo Gateway, Apollo Router, WunderGraph Cosmo Router
参考資料
はてなエンジニア Advent Calendar 2025 明日の担当は id:chaya2z です。
Implementing Google BigQuery REST API (v2) jobs.query
これは はてなエンジニア Advent Calendar 2024 25日目の記事です。
Google BigQuery REST API (v2)のjobs.query を実装した Perl モジュールを作りました。
おすすめポイント
- 列の値をフラットな hashref へ変換します
->{f}->[0]->{v}みたいな値の探り方をしなくていいので便利です- なぜこういうデータ構造になっているのか全然わからない
- 列の値のデータ型を JSON Schema で定義できるようになっています
- データ入出力の境界には型があると安心です
やったこと
MinillaでPerlモジュールの雛形を作るだけでした。簡単。
モジュールを作ろうと思った理由
Google::BigQuery は Discovery document という仕組みを使っていて、リクエスト先のURLを実行時に組み立てるようになっています。
しかし、いつからか Discovery document の返り値の path 要素に含まれるパス変数の形式が変化してしまい、動かなくなってしまっていました。
- 期待値
projects/{projectId}/queries- https://metacpan.org/release/SHOJIKAI/Google-BigQuery-1.02/source/lib/Google/BigQuery/V2.pm#L40-44
my $path = join('/', $self->{GOOGLE_BIGQUERY_API_BASE_URL}, $rest_description->{path}); $path =~ s/{projectId}/$project_id/; $path =~ s/{datasetId}/$dataset_id/; $path =~ s/{tableId}/$table_id/; $path =~ s/{jobId}/$job_id/;
- 実際の値
projects/{+projectId}/queries"query": { "description": "Runs a BigQuery SQL query synchronously and returns query results if the query completes within a specified timeout.", "flatPath": "projects/{projectsId}/queries", "httpMethod": "POST", "id": "bigquery.jobs.query", "parameterOrder": [ "projectId" ], "parameters": { "projectId": { "description": "Required. Project ID of the query request.", "location": "path", "pattern": "^[^/]+$", "required": true, "type": "string" } }, "path": "projects/{+projectId}/queries", "request": { "$ref": "QueryRequest" }, "response": { "$ref": "QueryResponse" }, "scopes": [ "https://www.googleapis.com/auth/bigquery", "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/cloud-platform.read-only" ] }
やらなかったこと
CPANへの登録
perlnewmod - 新しいモジュールを配布するには - perldoc.jp を読んで片手間ではやりきれんな、と思ってやめました。
Google::BigQuery に変更を提案
10年前に作られたモジュールで、GitHub リポジトリも消えているので、これ以上時間かけてもな、と思ってやめました。
明日の担当は id:k1s1eee さんです。
主体や目的を具体的に示す+結果をどう扱うかを示す
LLMは最大公約数的な答えを返してくれるので便利だな。 主体や目的を具体的に示すことは意識しているけど、結果をどう扱うかも示すようにしよう。
問いかけ
「コマンドを叩く」「コマンドを打つ」「APIに投げる」「 APIを叩く」「レビュー依頼を投げる」など、責任を押し付けるような言葉使いを憂いているので、どうすれば改善できるか建設的な意見を1000文字以内でまとめて欲しい。
Geminiの答え
責任転嫁を連想させる言葉遣いの改善策
「コマンドを叩く」「APIに投げる」といった表現は、まるでコンピュータに仕事を丸投げしているかのような印象を与え、責任感の欠如や、他者への丸投げを連想させる可能性があります。これらの言葉遣いを改善し、より建設的なコミュニケーションを促進するためには、以下の点に留意することが重要です。
1. 行動主体を明確にする
- 「私が」コマンドを実行する
- 「私が」APIを呼び出す
- 「私が」レビュー依頼を行う このように、主語を明確にすることで、自分が主体的に行動していることを示し、責任感の有無を明確にします。
2. 行為の内容を具体的に説明する
- 「コマンドを実行して、~という処理を行う」
- 「APIを呼び出し、~というデータを取得する」
- 「レビュー依頼を行い、~という点について確認をお願いする」
単に「コマンドを叩く」と言うよりも、具体的な処理内容を説明することで、何をしているのかを周りに理解してもらいやすくなります。
3. 相手への配慮を示す言葉を選ぶ
- 「ご協力をお願いして、~を検証していただきたく」
- 「~について、ご意見を伺えれば幸いです」
一方的な指示ではなく、相手への配慮を示す言葉を選ぶことで、共同で作業を進めるという意識を醸成します。
4. 結果に対する責任を持つことを示す言葉を選ぶ
- 「この処理を実行した結果、~ということが確認できました」
- 「このAPIの呼び出しによって、~というデータを取得し、~という結論に至りました」
結果に対する責任を持つことを示す言葉を選ぶことで、単に作業を行っただけでなく、その結果について深く考えていることを示します。
5. 問題発生時の対応について言及する
- 「もしエラーが発生した場合には、~という対処を行います」
- 「レビューの結果、修正が必要な箇所が見つかった場合は、~という対応を行います」
問題が発生した場合の対応について言及することで、責任感を持っていることを示し、安心感を与えることができます。
その他
- 多様な表現を使う: 同じ言葉の繰り返しを避けることで、表現に変化を持たせ、単調さを解消します。
- 状況に合わせて言葉を選ぶ: 状況や相手に合わせて、適切な言葉を選ぶことが重要です。
- チームで共通の言葉遣いを決める: チーム内で共通の言葉遣いを決めることで、コミュニケーションの円滑化に繋がります。
これらの提案を参考に、状況に合わせて言葉を選ぶことで、より建設的なコミュニケーションを促進し、チーム全体の士気を高めることに繋がります。
まとめ
責任転嫁を連想させる言葉遣いを改善するためには、行動主体を明確にし、行為の内容を具体的に説明する、相手への配慮を示す言葉を選ぶ、結果に対する責任を持つことを示す言葉を選ぶ、問題発生時の対応について言及するなど、様々な工夫が考えられます。これらの提案を参考に、より良いコミュニケーションを目指しましょう。
ポイント
- 主語を明確にする
- 行為の内容を具体的に説明する
- 相手への配慮を示す
- 結果に対する責任を持つ
- 問題発生時の対応について言及する
補足
上記はあくまで一般的な提案であり、具体的な改善策は、チームの状況や個人の性格などによって異なります。
さらに良い表現例
| 従来の表現 | より良い表現 |
|---|---|
| コマンドを叩く | コマンドを実行する、スクリプトを実行する |
| APIに投げる | APIを呼び出す、APIリクエストを送信する |
| レビュー依頼を投げる | レビューをお願いする、レビュー依頼を送信する |
その他
- 「投げる」という表現は、物体を投げつけるイメージがあり、やや攻撃的な印象を与えます。
- 「叩く」という表現は、力任せに行うイメージがあり、丁寧さを欠く場合があります。
- 「依頼する」や「お願いする」といった言葉を使うことで、相手への敬意を示すことができます。
上記を参考に、状況に合わせて適切な言葉を選ぶようにしましょう。
ChatGPTの答え
現代の技術職や開発現場では、「コマンドを叩く」「APIを叩く」「レビュー依頼を投げる」といった表現が日常的に用いられます。しかし、これらの表現はそのまま受け取ると、曖昧さや責任を転嫁する意識が潜在的に含まれていると感じられる場合があります。そのため、より明確で責任を意識した言葉遣いに改善することが望ましいと考えられます。以下に具体的な改善策を提案します。
1. アクションの主体を明確にする
曖昧な表現はしばしば行為の主体を不明瞭にします。「コマンドを叩く」「APIを叩く」という言葉は単なる行為の発生を指しますが、「〇〇を実行する」「〇〇にリクエストを送信する」といった表現にすることで、何が行われているのかを具体的に説明できます。また、「レビュー依頼を投げる」という表現も、「〇〇さんにレビューを依頼する」と明確にすることで、依頼する人の名前を出し、責任の所在を明らかにすることができます。
2. 行動の目的を意識する
アクションの背景にある目的を言葉に含めると、表現の意味が具体化され、責任感が伴います。「APIに投げる」という表現を、「データを取得するためにAPIにリクエストを送る」とすることで、行動の目的が明確になります。目的を意識することで、行動の価値が共有され、他者にも正確に伝わります。
3. 曖昧な言葉を避ける
「叩く」「投げる」といった言葉は感覚的でカジュアルな印象を与えるため、状況によっては専門的な言語に置き換えるのが有効です。「コマンドを叩く」ではなく、「コマンドを実行する」「コマンドを入力する」と言い換えることで、具体性と共に責任が伝わります。チーム内のやりとりをフォーマルにする必要がある場合には特に有効です。
4. チーム文化の見直し
言葉遣いは文化や習慣から生まれるため、改善にはチーム全体での意識の共有が必要です。定期的に言葉遣いに関するワークショップを開くことで、より建設的で責任感のあるコミュニケーション方法を模索する場を設けるのも有効でしょう。また、コードレビューやフィードバックの場で、意識的に明確な言葉を使うことを推奨し、習慣化を目指します。
5. 誤解を防ぐ意識を持つ
相手に誤解を与えないことも大切です。「レビューを依頼する」という言葉は、「レビューの時間をお願いしている」という意識を伝えるために、「〇〇さんにレビューをお願いしてもよいでしょうか」といった丁寧な表現にすることが考えられます。これにより、相手の時間や負担に配慮する姿勢が伝わります。
このように、言葉を丁寧に選ぶことで責任感を伴ったコミュニケーションが可能になり、チーム全体の信頼感を高めることができます。
【未公開記事の発掘】AWS Lambda ファンクションのインスタンスをウォームアップ状態で維持したい

起動に時間のかかるファンクションで困っていたのかもしれない。
背景
- HTTP リクエストを処理するだけの Lambda ファンクションがある
- ほとんどリクエストがこないのでそのたびに新規作成してる
- リクエストの送信元が設定している応答タイムアウト時間が短くて、エラーになりやすい
目的
世の中の知見
- GitHub - juanjoDiaz/serverless-plugin-warmup: Keep your lambdas warm during winter. ♨
- Lambda Warmer: Optimize AWS Lambda Function Cold Starts - Jeremy Daly
- Serverless Frameworkで行うLambdaのコールドスタート対策 - Qiita
ソリューション
Lambda ファンクションのインスタンスは VPC で実行するなら15分、そうでないなら5分くらいで廃棄されるようです。
廃棄までの時間内に新しいイベントが到着すれば、継続して動き続けるはず。
できるだけ費用がかからないように、という前提があっても、定期的にリクエストを送信する方法はいろいろ考えられます。
- 外形監視サービスを利用する
- インテグレーションサービスを利用する
- Get Started - IFTTT で指定した URL へアクセスするだけのアプリを定期実行する
- スクリプトサービスを利用する
- Apps Script – Google Apps Script で指定した URL へアクセスするだけのスクリプトを定期実行する
- 作業PCのスケジューラーを利用する
- ログオンしているときだけ定期的に実行するコマンドを作る
- どこかに用意した仮想マシンを利用する
- 指定した URL へアクセスするだけのスクリプトを定期実行する
第7回 Data-Oriented Programming 読書会
- JavaEE勉強会の読書会
- 開催場所はDiscordのjavaee-study-jp
- 今回
- 13.4から最後まで
- 次回
- 今回が最終回です
- 参加者トピック
- nextbook
- ディスカッション
- 13.4 Multimethods with dynamic dispatch
- 13.5 Integrating multimethods in a production system
- 13 Summary
- 14 Advanced data manipulation
- 14.1 Updating a value in a map with eloquence
- 14.2 Manipulating nested data
- 14.3 Using the best tool for the job
- 14.4 Unwinding at ease
- 14 Summary
- 15 Debugging
- 15.1 Determinism in programming
- 15.2 Reproducibility with numbers and strings
- 15.3 Reproducibility with any data
- 15.4 Unit tests
- 15.5 Dealing with external data sources
- 15 Summary
- 参考情報
参加者トピック
- 引き続き chatGPT 話題
- 最近は Edge で Bing AI を使うことが増えている
- ライブラリの選定に使っている人がいたりする
- ステージマネージャ は便利なのでお勧め
- Anker が古くなったモバイルバッテリーを引き取るキャンペーンをしている
nextbook
- Patterns of Distributed Systemsがよさそうだけど9月にならないと公式版にならない
- 先に短めの本を挟んではどうか
- どれを見ても300ページ以上ある
- タイムボックスを決めて読める分だけ読むのはどうか
- System Design
- 2章くらいしか進められなさそう
- 第5章は面白そうということだった
- 9月まではWebページを読んで過ごすとどうか
- 先に短めの本を挟んではどうか
『決定】System Design の第5章を読んでいく
セキュリティ
- テスティング
- キャリア
- アーキテクチャ
ディスカッション
13.4 Multimethods with dynamic dispatch
- 実行時のデータに基づいて呼び出す関数を決める仕組みのことだった
- 汎用データ構造でも静的型付け言語と同じようなことができる、ということなのかな
13.5 Integrating multimethods in a production system
- 普通はプレゼンテーションに近いところで書式を指定するものだけど、モデルのすぐそばで判断、加工しているのは不思議
13 Summary
14 Advanced data manipulation
14.1 Updating a value in a map with eloquence
- データを取得して加工して設定するのではなく、データを加工する関数を渡すようにする
14.2 Manipulating nested data
flatMapとflatten + mapのどちらが分かりやすいか議論している
14.3 Using the best tool for the job
forEachを撲滅したい
14.4 Unwinding at ease
- MongoDB の
$unwindオペレータは便利
14 Summary
15 Debugging
15.1 Determinism in programming
- いろんな層の言葉が乱用されているし、基本的な事実を新発見のように説明しているので、読んでいてつらい
- 経験主義というやつだろうか
15.2 Reproducibility with numbers and strings
- print デバッグの方法を紹介している
15.3 Reproducibility with any data
- print デバッグの方法を紹介している
15.4 Unit tests
15.5 Dealing with external data sources
15 Summary
参考情報
第6回 Data-Oriented Programming 読書会
- JavaEE勉強会の読書会
- 開催場所はDiscordのjavaee-study-jp
- 今回
- 11章の途中から13.3まで
- 次回
- 第7回 Data-Oriented Programming 読書会 - connpass
- 13.4から
- 2023/5/21(日)
- 参加者トピック
- ディスカッション
- 11.3 Representing a client request as a map
- 11.4 Representing a server response as a map
- 11.5 Passing information forward
- 11.6 Search result enrichment in action
- 11 Summary
- Part 3. Maintainability
- 12 Advanced data validation
- 12.1 Function arguments validation
- 12.2 Return value validation
- 12.3 Advanced data validation
- 12.4 Automatic generation of data model diagrams
- 12.5 Automatic generation of schema-based unit tests
- 12.6 A new gift
- 12 Summary
- 13 Polymorphism
- 13.1 The essence of polymorphism
- 13.2 Multimethods with single dispatch
- 13.3 Multimethods with multiple dispatch
- 参考情報
参加者トピック
- chatGPT の話ばかりしてる
- GitHub Copilot の OSS メンテナ認定は雑すぎて助かる
- GPU ボードのメモリは 16 GB ないと厳しい
ディスカッション
11.3 Representing a client request as a map
- 最初から汎用的なAPIにするのは早すぎる最適化だと思う
11.4 Representing a server response as a map
propertiesにフィールド名を書かなくてもrequiredに書いただけでフィールドを生やすらしい
11.5 Passing information forward
特になし
11.6 Search result enrichment in action
特になし
11 Summary
特になし
Part 3. Maintainability
特になし
12 Advanced data validation
特になし
12.1 Function arguments validation
- 保守を任されたシステムで、最初の仕事がデータの型付けだったら辛すぎる
- JSON Schema に静的型付け言語と同じような表現力を求めている
12.2 Return value validation
特になし
12.3 Advanced data validation
LOCALE=C dateの出力を見るとformat="date"が受け入れてもらえる気がしない- 不安なので正規表現を書いてしまう、と思う
12.4 Automatic generation of data model diagrams
12.5 Automatic generation of schema-based unit tests
- GitHub - json-schema-faker/json-schema-faker: JSON-Schema + fake data generators
- GitHub - clj-kondo/clj-kondo: Static analyzer and linter for Clojure code that sparks joy
- faker としての使い方では不十分ではないか
- 境界値とか気になるときはどうするんだろう
12.6 A new gift
- JSON Schema はフィールドの値域が条件によって変わるようだと記述量が多くなりがちで困る
12 Summary
- OpenAPI は JSON Schema のスーパーセットでありサブセットでもあるので OpenAPI を使っていくとよさそう
13 Polymorphism
13.1 The essence of polymorphism
- (yujiorama) 多態性は OOP の特徴ではないような?
- 誤解だった オブジェクト指向は継承で多態するプログラミング - きしだのHatena
オブジェクト指向って継承による多態があるからこそなんだけど、継承が非推奨になって以降に雰囲気でオブジェクト指向を知った人には、継承はオプションでカプセル化だけでオブジェクト指向って言ってしまいがちに思います。
13.2 Multimethods with single dispatch
13.3 Multimethods with multiple dispatch
PlayCode - Javascript Playground