kmuto’s blog

はてな社でMackerel CREをやっています。料理と旅行といろんなIT技術

『Software Design』2023年7月号を読んだ

ようやく追い付いてきた、7月号を読む。

gihyo.jp

  • 「平林万能IT技術研究所」、スマホで撮影と音声入力をしてOpenAIのDALL-E APIで入力に基づく画像合成をする。言霊カメラというアイデア、面白い。
  • 「オンラインホワイトボード『Miro』徹底活用術」。偏愛マップでメンバー自己紹介や、ドラッカー風エクササイズで価値観確認は面白いかな。非公開モード中はほかの人の付箋内容が見えなくなって他人の書いている内容に引っ張られない、なるほど。ほか、ステークホルダーマップ、インセプションデッキについても。
  • 「gRPCで始めるWeb API開発」、第1特集。gRPC、ちゃんと知っておきたかったのでありがたい。
    • gRPCはGoogleによって開発されたオープンソース(2015〜。元はStubbyだったのを作り直し)のRPC(Remote Procedure Call)フレームワーク。2017〜でCNCFのプロジェクトとしてホストされている。マイクロサービス間の通信、モバイル-バックエンドサーバ間の通信に使うことを想定。
    • 特徴。Protocol Buffersによるサービスやデータのスキーマの定義とコードの自動生成。複数のメジャーなプログラミング言語への対応。HTTP/2による双方向ストリーミングの利用(ただしブラウザ-バックエンドサーバ間でgRPCは直接利用できない。gRPC-Web実装ならできる)。
    • RPCでは、クライアントはサーバーの処理の呼び出し方だけを知っていて実装の詳細は知らない。
    • Protocol BuffersをIDLとして使用する。gRPCはProtocol Buffersによって定義されたサービスからコード生成し、クライアント/サーバの開発に使用する。サーバーはサービスのインターフェイスを満たすような実装をし、クライアントは自動生成されたサービスのスタブ(APIクライアント)を使った実装をする。
    • Protocol Buffersはインターフェイスの記述のほか、メッセージのバイナリ形式を持っていてプログラミング言語のデータ構造と対応する形でシリアライズ/デシリアライズできる(言語間差異を吸収してProtocol Buffersのバイナリデータになる)。シリアライズ/デシリアライズはライブラリや自動生成コードで隠蔽化され意識する必要はない。任意のデータ形式にすることもできなくはないがそれぞれ実装する必要があるし、デフォルトで困ることは基本的にないはず。
    • RPCフレームワーク、現代的、高効率、どんな環境でも動作、オープンソース
    • gRPCにすると決めるだけで技術選定を絞れるしAPIスキーマも決まる。
    • スキーマ駆動開発、protocが現代的。インターセプタ(ミドルウェアみたいなの)を簡単に追加できる。ロガー、認証、トレーシングなどをプラグイン的にできる。フィールド番号、バリデーションコード。
    • HTTP/2の上に構築され、効率が良い。双方向ストリーミング。
    • マイクロサービスとの好相性。JSONよりもコンパクトで高効率。
    • Go/C++/Java/Node.js/Kotlin/Objective-C/Swiftなどなど。
    • 実装、protoc含めオープンソースブラックボックス化せしない。GitHub報告や修正貢献。
    • マイクロサービス間通信のパフォーマンス向上を目的として作られた。帯域幅やCPUの効率、低遅延な仕組み。
    • REST API。gRPCはCRUDの枠外に対応できる。REST APIはHTTPメソッドから操作種類を読み取れるのでCDNキャッシング判断を機械的にしやすいが、gRPCでは工夫が必要。
    • 対GraphQL。スキーマ駆動開発で開発体験は近い。
      • GraphQLはデータフェッチのラウンドトリップ回数を減らすことでAPI通信効率を上げることを目指している。GraphQLでは取得対象のオブジェクトフィールドをたどって1クエリに対するレスポンスにまとめて結果を返せるが、gRPCでは複数回のデータ取得か、アプリの各画面に対応して別のRPCメソッド実装が必要。クライアントでの複雑かつ柔軟なデータ取得を重要視するならGraphQLのほうがよい。
      • GraphQLには双方向ストリーミングはない。GraphQLはフィールドをたどっていくリゾルバ実装が必要なので、フィールドのアクセス制御やたどる深さ制御などを考える必要がある。
    • gRPC-Web。Envoy Proxyを使ってHTTP/1.1も利用可能。gRPC-GatewayはgRPC-JSON変換をする。Buf Tehnologies社のConnectも有望。
    • HTTP/2のメリット。1つのコネクションでの複数リクエスト/レスポンスの同時交換による通信効率の向上、ストリーム内のバイナリ形式によるネットワークリソースの効率化。低レイテンシーと高スループットで、gRPCもこの恩恵を受ける。
    • Protocol Buffers。スキーマAPIの仕様を標準化し、統一されたフォーマットで記述した設計書のようなもの)を定義する。取り扱うデータの構造や型、リクエスト/レスポンスの仕様。バイナリにシリアライズされる。Protocol Buffersのところでシリアライズ/デシリアライズをするので型制御が厳密であり、保証のないOpenAPIに対して強み。
    • gRPCのデメリット。HTTP/2通信となるのでインフラ難度(2020年10月までALBがHTTP/2通してなかった、とか)。curlでシュッとテストということはできずデバッグしづらい(grpccurl、Evansなどを使う)。情報が少ない。いずれも改善はしつつある。
    • protoファイルを書く。importで取り込んだりできるので、適切な粒度で分割するとよい。
    • RPCメソッドを集めたものをサービスと呼ぶ。型はメッセージ型、スカラー型に分かれる。メッセージ型はフィールド定義 型 フィールド名 = タグナンバー で、タグナンバーはメッセージ内で一意。フィールドを削除するときには再利用せずに廃番する。廃番はreservedで明記しておくとよい(reserved 4, 7 to 10で4、7、8、9、10を廃番宣言)。deprecatedオプションというのもある。スカラー型はプログラミング言語のプリミィティブ型相当、基本デフォルト値必須、optionalキーワードで未定義値化。repeated、enum、mapもあり。
    • Well Known Typesを活用する。google.protobufパッケージのインポートで、いろいろなメッセージ型が定義されている。
    • protoファイルにはコメントを記述できる。
    • protocコマンドでコード生成。Homebrewならprotobufをインストールしておく。
    • API設計。
      • ドキュメント化。エラー条件などがわかりにくい。proto-gen-docを使うと、protoファイルからコメントを取り出してMarkdown/HTMLなどの形式で出力できる。Javadoc形式だね。
      • 再利用性の高い型を使う。整数、文字列、ブール型。Well Known Types、Common Types。可読性・開発生産性・相互運用性につなげる。
      • バリデーション。たとえばサービスの許容文字や文字数など。go-proto-validators、protoc-gen-validate。
      • 分散トランザクションは不向き。メソッドはワンショットで完結させる。認証権限などのシンプルなものはメタデータトークン連携といった仕組みにする。
      • エラーはステータスコードで返される。protoファイルにコメントしておくのがよい。
      • OOP開放閉鎖原則、「モジュールは拡張に対して開いており、修正に対して閉じていなければならない」。互換性を意識してリクエストとレスポンスを設計し、将来的な拡張に対する柔軟性を高める。
      • リクエストとレスポンスは1つのメソッドごとにそれぞれ別のメッセージとして定義する。使い回すと変更の影響範囲が大きくなる、メソッドの期待するリクエスト/レスポンスがあいまいになる。
      • タグナンバーは変更しない。reservedで廃番管理。
      • フィールドの型を変更しない。互換性を損わない型変更(int32→int64など)ならOK。
      • デフォルト値を変更しない。
      • 後で複数になっても後方互換性を担保できるよう、繰り返しフィールドにはメッセージ型を利用する(スカラーenumでないほうがよい)。
      • enumにはデフォルト値として未指定値を含める。0番目の項目値。
    • インターセプター。認証、レート制限、トランザクション管理、分散トレーシング、エラーハンドリングなどなど。go-grpc-middleware。
    • メタデータ。インターセプターとあわせてよく使われる。REST APIのリクエストヘッダのようなもの。トークンやトレーシングキーなどの値をクライアントからサーバーに渡せる(逆方向も可)。スキーマレスで任意のK-Vペア、セキュリティには注意。
    • Buf CLI。Protocol Buffersによる開発フローを包括的に支援。Homebrewだとbufbuild/buf/buf。lintあり。
    • GitHub Actionsのbufbuiold/buf-breaking-actionでスキーマの破壊的変更に警告。bufbuild/buf-lint-actionでlint。
  • 「はじめようSvelte」第2特集。React、Vue.jsといった中でさらに覚えてくの、フロントエンドエンジニア過酷やな……。
    • コンパイラフレームワークで、仮想DOMを持たない。JavaScriptそのものがリアクティブ(データの変更が自動的に画面に反映)になり、状態管理ライブラリも不要、変数を代入すれば反映。テンプレートタグもuseStateも不要、コード量を減らす。
    • Vue.jsと同様にHTML・スタイル・ロジックを1ファイルに書くSFC(Single-File Component)。コード量が少なく学習コストが低い。
    • {#if...}条件分岐、{#each...}ループ、#{@html ...}文字列のHTML表現(XSS注意)。
    • on:ディレクティブでイベント処理。修飾子onceで1回だけに。createEventDispatcher関数でカスタムイベント作成。
    • バインディングコンポーネントの状態と、DOM要素や属性/プロパティの間にリンクを作成する。アプリケーション状態の変更でビューに反映され、逆も同様。
    • ライフサイクル関数。コンポーネントの特定のタイミングで実行できる。主なものとしてonMount, beforeUpdate, afterUpdate, tick。
    • ストア。アプリケーションの状態管理。リアクティブでストア値が変われば参照しているコンポーネントが更新。独自のカスタムストアを作成できる。
    • うーん、どうなんだろう。既存のものを移行するのは厳しそうで、ギリVueだと類似の書き方ということでいけるのかな。
  • GoFデザインパターン歴史探訪」。GoF本は1994年、翻訳は1995年で改訂版でも1999年かー。まさに古典。
  • 「メールセキュリティ対策の現場」、今回はDMARCレポート。本当にポリシーを変更してよいのか、見逃しているシステムがないかを判断するのに使う。Aggregate reportのアドレスにXML形式で毎日1回送られてくる。XMLの解析。著者はKibanaで分析したとのこと。ベンダーによるレポートの解析サービスがある。
  • Google Cloudを軸に実践するSREプラクティス」。今回もTerraformでGHAと組み合わせたCI/CD。TFからGoogle Cloud上のリソースを操作するための認証。google-github-actions/authアクションで、workload Identity連携(OIDCサポートあり)を利用するのがよい。
  • 「なるほど納得Go言語」、今回から本格的にロジックを書くフェーズ、だそうで。不要なelseを省く。else ifチェーンよりはswitchを使う。関数実行を関数がreturnされるまで後回しにするdeferを活用する(リソースの後片付けなど)。enum/列挙の代替としてiotaの活用。stringerコマンドでiota値の代わりに名前を文字列表現化させる方法。
  • AWS活用ジャーニー」。機械学習環境を提供するSageMaker。Jupyter Notebook、学習・推論のインスタンス、S3との読み書きなどをまとめて管理できて専念できる。
  • 「エンジニアも知っておきたい法律知識」。LLMとの関係。
    • 秘密情報として取り扱うことになっているソースコードをChatGPTに入れた。相手の同意なしならNDA違反可能性。自分の秘密情報だと不正競争防止法の「営業秘密」から外れて保護を受けられなくなる可能性。
    • GPLv3のソースコードをプロンプトにして、作業案件のコードを作成したが、作業案件はGPL非適用にしたい。LLMの規約が商用利用禁止だとそもそもダメ。出力結果が第三者権利侵害していると著作権侵害。類似性と依拠性の両方があるか。入力にコードを入れている時点で依拠性があり、そこに類似性があったら侵害となり得るし、GPL適用になる。