Penpen7のブログ

Penpen7のエンジニアブログ

📚 Software Design 9月号 読書メモ

第1特集GraphQLでアプリケーション開発現場における使いこなし方を徹底チェック

第1章:GraphQLとは利点・注意点を整理して輪郭をつかむ…… 和田 祐汰

  • GraphQL=APIのためのクエリ言語

第2章:GraphQL導入クエリを書いてデータ取得を試してみよう…… 浦 優太

  • ルートタイプも一つのタイプになっている(Queryなど)
  • non-nullableが!で表現できるようになっている
  • オブジェクトタイプの場合は少なくとも一つのフィールドを指定する必要がある
    • SelectionSetsと呼ぶ
  • fragmentで部分型みたいなのを作れるのは便利ですね
    • 使いまわせるのが良さげ

第3章:サーバサイドの実装TypeScript+Apollo Serverでサーバを構築する…… 金井 祐樹

  • server実装
  • 今回のスキーマはこれ

https://github.com/quipper/software-design-2024-09-graphql/blob/main/03_server/schema.graphql

  • 実際のデータを取るのはリゾルバで定義
    • GraphQLでは柔軟にデータを取れるので実装が難しそうだなと思ったが、意外とコードは単純だった
    • 型が一致していないとどうなるんだろう
      • 静的解析で解決してくれるのか?

https://github.com/quipper/software-design-2024-09-graphql/blob/main/03_server/src/index.ts#L12-L26


  • 定義してない値はdefault resolverでいい感じに展開してくれるようだ

  • DataSourceを使うとN+1問題を解消できるようだ

    • すぐにクエリを投げるのではなく一旦アクセスする必要のある条件を貯めておいて、あとでまとめて投げるみたい

      • loaderで実際の取得処理を記述して、メソッドでloader.loadを呼んで取り出す感じか
      class PostsDataSource {
        private loader = new DataLoader(async (keys: number[]) => {
          // 実際の GraphQL サーバーで発行されることが想定されるクエリをログに出力します
          console.log(`SELECT * FROM post WHERE author_id IN (${keys.join(",")})`);
          const results = posts.filter(post => keys.includes(post.author_id));
      
          return keys.map((key: number) => results.filter(post => post.author_id === key));
        });
      
        async getPostsBy(author_id: number) {
          return this.loader.load(author_id);
        }
      }
      
  • よくわからないコードがあったので聞いてみた

    const results = posts.filter(post => keys.includes(post.author_id));
    
    return keys.map((key: number) => results.filter(post => post.author_id === key));
    

    最初の行 const results = posts.filter(post => keys.includes(post.author_id)); では、posts 配列から author_idkeys 配列に含まれている投稿のみをフィルタリングしています。keys 配列には、データローダーが投稿を取得するための著者IDのリストが含まれていると考えられます。このフィルタリング操作により、後続のステップで処理される投稿が関連するものだけになるようにしています。
    次の行 return keys.map((key: number) => results.filter(post => post.author_id === key)); では、keys 配列の各キーに対して results 配列をフィルタリングし、現在のキーと一致する author_id を持つ投稿のみを含めています。これにより、投稿がそれぞれの author_id ごとにグループ化され、特定の著者に関連する投稿の配列が返されます。

    • 最初で処理対象だけをfilterしておき、returnで最終的な形(author_id→postの配列の辞書)に変形している感じか
  • サーバを起動するとGUI上でQueryを叩けたり、スキーマ定義を見れたり便利

第4章:クライアントアプリケーションの実装GraphQLならではの設計と実装を押さえる…… 内山 高広

  • queryをミスると静的にチェックしてくれるんですね
    • typescriptでいい感じに型を組んでいるような気がするがどういう仕組みなんだろう
  • Fragment Colocationいいですね
    • フロントエンドだとコンポーネント指向ですが、コンポーネントごとに必要なデータをfragmentを使って定義しておけば良いということですね
    • 値を使用する際にはprops的に使う感じになるのか
  • フロントエンド開発する際にはぜひGraphQLを使いたいと思いました!

第5章:GraphQLアプリケーションの実運用パフォーマンス改善,セキュリティ対策,APIの進化戦略のプラクティスを押さえる…… 上原 拓也

  • 200になっていたり、エラーが起きてきたフィールドはnullにする
    • 何を失敗にするのかが難しい
  • 再帰的にクエリが組めて負荷をかけやすいのは怖いですね
    • 外部公開するときにはDepth Limiting,Query Cost Analysisは必須だな
    • 簡単に制約かけられるのかな
  • Persisted Query
    • クエリのホワイトリスト
  • Signed Query
    • 共通鍵を用いてクエリの信頼性を検証
  • APIの廃止の判断についてもTrusted Documentの仕組みを使うなど勉強になりました!
  • GraphQLでカラムのリネーム削除等はどう対応するんだろうか?
    • バージョニングする?

第2特集Goのエラーハンドリングと向き合うベストな設計戦略を徹底解剖

第1章:Goのエラー処理を理解する「early return」が推奨される理由とその効果…… mattn

  • エラーハンドリングで悩むところ
    • スタックトレースがうまくだせない
    • エラーの種類でステータスコードを出し分けたい場合に漏れが発生する可能性があるところ
    • ここら辺が解決できる話が聞けるといいなぁと思う
  • とはいえ、例外よりかは良い仕組みだと思っている
  • javaの検査例外とは?
    • 例外が発生しうる
    • エラー処理は難しい…そうですねぇ
  • Goのよくあるエラーハンドリングのイディオム短くするためのissueがあるんですね〜
    • 後置ifも1行書きも却下されている
  • early returnは個人的には好み
    • 下に読んでいけば行くほど頭の中で考えないといけない事前条件が減っていって認知負荷が下がっていくため
    • 自動early returnで後処理を忘れないようにとあるが、逆にgoの方は後処理の後のreturnを忘れることがたまにあるんですよねぇ…
      • 大体テストコードを書いているときに気づく
      • 逆に?だけ書いてあったら後処理してないかもという気づきはあると思う
  • GoでResult型が使えるとめちゃくちゃ使い勝手は良くなりそうだなと思いつつ、Goの思想的にうまく組み込むスキームを考えるのが大変そうだなと感じました

第2章:失敗しないGoのエラー設計戦略エラーの基本からアンチパターンへの対処まで…… 後藤 玲雄

  • errorsとfmtパッケージどっち使えばいいかなというのはまだよくわかっていない

  • センチネルエラー

    • テキストのみを含むエラー
    • テキストが一致しているかどうかで判定
    errors.New("message)
    
  • ラップして追加で情報を追加可能

    • uberにgo styleがあるのは初めて知ったので、あとで読み返しておく
  • early returnはいいですね(2回目)

  • errors.Asは型変換、errors.Isはboolで返すだけだと思えばいいのか

  • interfaceを定義しているかどうか、1行でチェックできてunwrapするの便利

    joinedErr := errors.Join(err1, err2)
    if errs, ok := joinedErr.(interface{ Unwrap() []error }); ok {
    	for _, err := range errs.Unwrap() {
    		fmt.Println(err)
    	}
    }
    
  • 関数抜けるときにdeferで実行したい関数をフックするとき発生したエラーをどうすれば良いかわからなかったけど、errors.Joinでまとめてやればいいのかーなるほど

  • アンチパターン

    • 関数内部でerrors.Newはダメ
      • 異なるポインタ値で作成されるため
      • 静的なやつじゃないとダメなんすねー
      • メッセージを変えるときにはfmt.Errorfで動的なエラーメッセージを埋め込んでwrapする
    • fmt.Errorfは%w でラップする…覚えました
  • DDDとかでレイヤーでエラーハンドリングするにはどうしたらいいんでしょうね

    • 結局独自エラー型で対処した気がするが
    • stacktraceが必要な場合はfmt.Errorfでwrapするとなくなるんですよねぇ…
    • fmt, errors, pkg/errorsと乱立しているので、うーんというところではある

第3章:GoのエラーハンドリングQ&Aエラーにまつわる疑問・モヤモヤを一挙解決…… 渋川 よしき

  • morikuni/failureよりかはcockroachdb/errorsを使った方が今後、シン・errorsが出たときに移行しやすそうではある
    • スタックトレースによるパフォーマンス問題の話が紙面であったが、cockroachdb/errorsを使用すると重くなる話が確かあったな
  • Mustの接頭辞が入った関数はpanicしうる処理という慣例があるんですね
    • regex.MustCompileとかか
  • エラーはロガーと同様横断的に興味のあるものなので、クリーンアーキテクチャでも注意しないと外部に依存しちゃうんですよねぇ
  • ライブラリ内部ではエラー系のライブラリは標準ライブラリを使うだけに留めた方が良さそうですね
  • log/slogでjson形式でログを出せるようになったのは本当に便利になりました
  • 並列処理のエラーハンドリング
    • sync/errorgroupを使用するとエラーハンドリング含めて簡単に並行処理を組める
    • 最初に発生したエラーしか返せないので注意
  • linterで検査することが前提としつつも、linterの設定を頑張らないといけないのはなかなか…
    • ここいい感じの設定を知りたいですね
  • エラーハンドリングは本質的に難しいですね

連載

ITエンジニア必須の最新用語解説【189】Supabase……杉山 貴章

  • バックエンドを提供してくれるサービス
  • Firebaseのオープンソース版みたいな感じ
  • PostgreSQL使えるのいいっすねー
  • Freeプランでも個人プロダクトであれば十分かも
  • 自前ホスティングもできる
    • 簡単に構築できるのかな
  • データベースのブランチ機能面白そう

万能IT技術研究所【28】低緯度オーロラが出現する未来や過去を眺めよう!――現在から江戸・鎌倉・紀元前まで,オーロラ出現をデータ分析……万能IT技術研究所

  • 誌面のコードを実行してオーロラの予測情報をプロットできた
    • 綺麗
  • Kp値や過去の太陽活動のデータを元に過去の自然現象について考察していくのは面白いですね

ドメイン解体新書【8】ドメイントラブルシューティング② DNS設定のトラブル……谷口 元紀

  • FQDN
  • CloudflareにDNS変更時承認を求める設定ってあるんだ
  • FQDNでのピリオド忘れ
    • 自分もやってしまいそうだな…
  • CDNはDNS周りの設定が大変
    • 頭に入れておこう
  • DNSの設定は反映されていることが分かりづらい
    • ネガティブキャッシュもあって複雑
    • 一つ一つ設定を確認していくことが大事なんですね
  • web上でのツールの紹介ためになります!

ハピネスチームビルディング【30】DX Criteriaでチームをアセスメントして改善点を見つけよう……小島 優介

  • チームの改善点を見つける手法の一つ
  • エンジニアも関係あるらしい
  • 全部やろうとすると320個…めちゃ多い…
    • チームだけだと64個なのでなんとかできそうかな
  • 定期的に計測するとチームの状態を見る良い指標になりそう

エンジニアのためのやる気UPエクササイズ【25】ITエンジニア向けおすすめエルゴノミクスツール3選……えくろプロテイン

  • 昇降デスク買いました!
    • IKEAのやつですがなかなかいいです
  • モニタも4Kのやつ買いました!
    • LGが安くていいですね
  • 分割キーボード興味ありますが、うまく使いこなせるか気になりです

【新連載】インターネットの姿をとらえる【1】そもそもインターネットって何だろう?……土屋 太二

  • ISPにいた頃を思い出しました
    • とはいえ、ネット回線に関する事業にいたわけではないので、ISPオペやっていたら内容面白かったんだろうなと思います

レガシーシステム攻略のプロセス【5】キャパシティコントロール可能なカートシステム……半澤 詩織,横田 工

  • カート決済チーム=ZOZOTOWNのカート投入処理から注文データ作成、決済処理を開発・運用
  • カート決済機能の既存コードは11万ステップ…でかい…
  • ドメイン知識をまず習得…確かに全体像がわからないと適切なアーキテクチャなんて分かりませんもんね…
  • カート投入でスパイクする=加熱商品
    • 転売目的のBOTによるもの…きついっすね
  • 注文まで在庫を確保するため在庫数を下げる→リクエストが多くなるとロック→クエリ滞留
  • キューイングすることで実現
  • リリースするタイミングを短くすることでエンジニアのモチベーションも上がる
    • 刷新長くなりがちだが、小さいゴールを設定するのは大事ですよねぇ

AWS活用ジャーニー【24】Amazon EC2インスタンスへの接続……杉金 晋

  • 接続方法たくさん出てきましたね…
  • EC2 Instance Connect エンドポイント
    • プライベートサブネットにいるEC2に接続できるのいいなぁ
    • 60分以内じゃないとセッションが切れるみたいなので、長時間作業が必要なときには使わない方が良さそう

あなたのスキルは社会に役立つ~エンジニアだからできる社会貢献~【153】アーバンデータチャレンジ~データの力をまちの力に~……岡本 紗季

  • 地理空間情報を使って地域課題の解決を図る
  • コミュニティ形成&コンテストの取り組み
    • 東京
  • Knight モード」で帰らナイト。
    • 安全な経路を検索してくれるアプリ
    • どういう仕組み重みを計算しているのか気になり
© Penpen7