Postman v10 が発表された

Postman v10 のリリースが発表されました。 https://blog.postman.com/announcing-postman-v10/

面白そうなアップデートが結構あったので、内容を簡単にまとめてみます。

Postman CLI

自動APIテストとかに使えるかも。

gRPC サポート

  • GraphQL に続き gRPC がサポートされた。
  • gRPC のURLをURLバーに打ち込むだけで、使えるメソッドをセットしてくれる。
    • サーバーリフレクションというらしいんだけど、サーバーに問い合わせて使えるメソッドを取得しているのかな?
  • https://blog.postman.com/postman-v10-and-grpc-what-you-can-do/

重い腰を上げて gRPC を始める機が熟したか...。

パートナーワークスペース

「チームに入れるとコストが気になるけど、同じワークスペースは使ってほしい業務委託メンバーが複数人いる」みたいなケースで嬉しいかな?

API Security

API 定義のレビューってミスを見逃しがちな気がするから良いかも。 というかそもそも脆弱な定義とか全然知らないからこれを使って学んでいきたい。

API Governance

スタイルガイドがきちんとある組織ならかなり活きそう。 スタイルガイド作るのが大変そうだけど。

あまり理解できなかった

  • API Builder の改善
  • Private API Network

使ったことなくてイメージ付きませんでした...。

Goで文字幅操作

golang.org/x/text/widthパッケージはテキストの文字列の操作ができる。

全角に変換

s := "ハンカクカラゼンカク"
w := width.Widen.String(s)
fmt.Println(s)
fmt.Println(w)

// output:
// ハンカクカラゼンカク
// ハンカクカラゼンカク
s := "モトモトゼンカク"
w := width.Widen.String(s)
fmt.Println(s)
fmt.Println(w)
output:
モトモトゼンカク
モトモトゼンカク

全角を引数にwidth.Widen.String()を実行しても全角のままである。

半角に変換

s := "ゼンカクカラハンカク"
h := width.Narrow.String(s)
fmt.Println(s)
fmt.Println(h)
output:
ゼンカクカラハンカク
ゼンカクカラハンカク

濁点が変換されない。

解決策を紹介している記事を見つけた。

これを解消するには,安直な手段だが,いったん NFD 正規化で合成列に変換してから変換するとよい。

text.baldanders.info

s := "ゼンカクカラハンカク"
h := width.Narrow.String(norm.NFD.String(s))
fmt.Println(s)
fmt.Println(h)
output:
ゼンカクカラハンカク
ゼンカクカラハンカク

NFD 正規化については後からちゃんと調べよう。

正規の幅に変換

s := "カタカナabc"
f := width.Fold.String(s)
fmt.Println(s)
fmt.Println(f)
output:
カタカナabc
カタカナabc

所感

文字コードちゃんと勉強する。

base64のまとめ

base64とはすべてのデータをアルファベット(a-z,A-Z)と数字(0~9)、一部の記号(+,/)で表す変換方式である。 データの長さを揃えるのに、空白に詰める無意味なデータ(パディング)として=を使用する。 URLや正規表現の中では+,-は特別な意味を持つことがあるので-,_が用いられることもある。

電子メールをやりとりするプロトコルSMTPでは、ASCIIという7bitで表現される英数字しか送受信できなかった。 つまり画像や音声、バイナリデータの送受信はできなかった。 MIME(Multipurpose Internet Mail Extensions)という規格が登場し、その中でbase64が定められた。 MIMEに則ってエンコード、デコードすることで画像や音声、バイナリデータの送受信可能となった。

変換方法まとめ

  1. ファイルの内容(文字列)をbyteに変換して、*1
  2. 6bitずつに分けて、*2
  3. 最後のかたまりが6bitに満たない場合はパディングに0を使用して、*3
  4. base64の変換表をもとに64文字のいずれかに変換して、*4
  5. 変換後の文字列を4文字ずつ分けて、*5
  6. 最後のかたまりが4文字に満たない場合はパディングに=を使用する*6

*1: "文字a" => 11100110 10010110 10000111 11100101 10101101 10010111 01100001

*2:111001 101001 011010 000111 111001 011010 110110 010111 011000 01

*3:111001 101001 011010 000111 111001 011010 110110 010111 011000 010000

*4:5 p a H 5 a 2 X Y Q

*5:5paH 5a2X YQ

*6:5paH 5a2X YQ==

GoでPythonのlambdaっぽいプログラムを書いた

Pythonのlambdaって分かりやすい - Qiita

を読んでGoならどうやって書けるかなーと気になったので書いてみた。

package main

func double(n int) int {
   return n * 2
}

func main() {
   lambda := func(n int) int { return n * 2 }
   print(double(2) == lambda(2)) // true
}

結論、Goでも割とシンプルに書けました。

GraphQLのN+1問題に向き合う ~問題提起編~

はじめに

GraphQLを扱うデメリットとしてN+1問題が挙げられる。
なぜGraphQLだとN+1問題が起こってしまうのか考える。

そもそもN+1問題とは

そもそもN+1問題とはなにか。
N件のデータと、取得したそれぞれのデータに紐付くデータを取得する際に、DBへN+1回のアクセスが生じる問題のことをN+1問題という。

<例> ここに一つのブログシステムがある。扱うDBはRDBであり、ブログ投稿記事テーブル、ユーザテーブルの二つのテーブルでデータを管理する。 ブログ投稿記事一覧ページを表示する際に10件のブログ投稿記事を取得し、それぞれの記事の作者であるユーザも取得したい。このとき、ブログ記事はユーザのIDを持っており、そのユーザのIDを基にユーザの情報を取得する。

このような構成の場合、ブログ投稿記事一覧を取得するためのアクセス(1回)と、取得したそれぞれのブログ投稿記事に紐付くユーザを取得するためのアクセス(N回)が生じる。解消方法としては、JOIN句で一回のアクセスで取得してしまう、もしくは取得したブログ投稿記事が持つユーザIDを持つユーザだけを取得するSQLを作成して二回のアクセスで取得する。
以下の記事がわかりやすいと思う。

qiita.com

なぜGraphQLで問題視されるのか

上記の方法で取得すればなんの問題もないはずだが、なぜGraphQLで問題視されるのか。
気になって調べてみると二つの理由があった。

紐付いたリゾルバー切り出してしまった時の問題

こちらに関しては柔軟にしたばかりに、N+1問題が起きてしまったパターン。
どういうことかというと、GraphQLではリクエスト次第ではユーザ情報を含めないようレスポンスを要求することも可能なので、フィールド指定でユーザの情報が呼ばれた時にだけ、ユーザを取得するためのリゾルバが呼ばれるように切り出すことがある。確かにこの切り分けは便利で要求された時のみDBアクセスが走るのでパフォーマンスが良い。
だけども要求された時には毎回、内部でリゾルバーが呼び出されてN+1問題が生じるという話。

毎回網羅的に取得するようにしてしまったときの問題

かといって毎回、JOINなりEager Loadingするとフィールドが要求されていないにときにも、毎回紐付くデータまで取得してしまう。
要求されていないデータまで取得されてしまうことでパフォーマンスの劣化も考えられるという話。

解決策

DataLoaderを使うといいらしい。。。
そのうちまとめよう。

【AWS】最新の AMI を取得するコマンド


AWS の EC2インスタンスを利用する際に、最新の AMI を知りたい時があると思います。
そんな時には、CLIで以下のコマンドを叩きます。

aws ssm get-parameter \
  --name /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \               
  --region ap-northeast-1

ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2ap-northeast-1は適宜変更しましょう。

ページングのソートで気をつけること

バックエンドの実装で、ページングしたデータを返す際の話。
基本ライブラリに頼っているのであまり実装のことを考えたことがなかったので、結構苦戦した。

以下のような数字を降順で並べたリストのデータを、ページングでフロントエンドに返すとする。

7,6,5,4,3,2,1,0

ページごとの件数が3だとすると、1ページ目は7,6,5、2ページ目は4,3,2となる。
このときSQLを用いたデータベースへのアクセスだが、1ページ目から2ページ目の遷移は簡単で端っこの値を基に比較演算子を用いる。(5 > X)
3ページ目から2ページ目への遷移はどうだろう。
1,0から4,3,2を取得したい。
このときのポイントとして、全体の並び順が降順であってもDBから取得する際に並べ替えてからLIMITで件数を試ぼってはいけない。
1より大きい値を降順で3件欲しいわけだが、単純に1より大きい値を降順で3件要求すると取得できる値は7,6,5となってしまう。
要するにASCで3件取得した後にDESCで並べ替えなければいけないのだ。
ちなみに昇順でも同じように、前ページを取得する際には取得後の並べ替えでないといけない。

0,1,2,3,4,5,6,7

0,1,2->3,4,5 ASCで取得可能 6,7->3,4,5 DESCで3件取得した後にASCで並べ替え

きっとすぐに忘れるので、ちょっとでも考えるヒントになるように備忘録として残しておく。