またGoで半ばはまりかけた。
JSONを構造体に変換する際に「データの中身を確認したいなぁ」とReadAllすると、res.Bodyの中身が空っぽになる。
// 次の行をコメントアウトすれば期待通りにJSONが構造体に変換される。
body, _ := ioutil.ReadAll(res.Body)
data := &Data{}
json.NewDecoder(res.Body).Decode(data)
またGoで半ばはまりかけた。
JSONを構造体に変換する際に「データの中身を確認したいなぁ」とReadAllすると、res.Bodyの中身が空っぽになる。
// 次の行をコメントアウトすれば期待通りにJSONが構造体に変換される。
body, _ := ioutil.ReadAll(res.Body)
data := &Data{}
json.NewDecoder(res.Body).Decode(data)
バリデーションをわかりやすく実装するって難しいって話。 頭の中を整理するために書いているので、まとまってない状態。
ログイン時にIDとパスワードをポストするけど、受け取った側としてはその値が正しいかどうかを判断する。 この "正しいかどうかを判断する" ってのがやっかい。 IDとして正しいかどうか?というのは、
のような感じではあるが、これって 値が存在する前提の話 なんだよね。 まずは値が存在しているのかどうか?ってところから判断して、存在しない場合は正しいかどうかって判断できない。 だから、
ってのも確認しなければならない。
どうやって実装したら綺麗なのか?
if id, ok := param("id"); ok {
id.validation(required, max(8))
}
これでもいいんだけど、前提条件が揃っているか(パスワードが送られてきているか)を確認してから処理に移りたいよねって思う。
if (required("id", "password")) {
id := param("id")
pw := param("password")
}
そうなるとこんな感じかな?
だけど、他にもIDを保存しておくか?的なオプションがあって、keepidなんて項目まであったとする。
if (required("id", "password")) {
id := param("id")
pw := param("password")
if keep, ok := param("keep"); ok && len(keep) != 0 {
// IDを覚えておく処理
}
}
なんてのはすっきりしないなぁ…と。 だいたい、値が送られて来なくても、値が空文字列であっても『IDは必要だよ』って旨は表示するわけだし、この辺が実装と現実の乖離。
さらに 値がない場合は初期値としてこれを使いたい みたいな場合は厄介事が増えてしまう。
こういうを考えているとScalaのOptionとmatchの表現はすっきりでいいなぁ…と思えてしまう。
こういうときはGoではどう書けばすっきりするんだ?値の存在確認もバリデーションって言葉で片付けられることあるけど、その言葉には依存関係が存在することもあって、スマートな解決を求める場合は一言で表さない方がいいのでは?と思ったりした。 今回の場合は、
なのかな?と。全部まとめてバリデーションって表現もいいけど、実装上はこの差を明確にしておいた方がわかりやすいんじゃないかなと思った。 だけど、必ず存在していないと困るか?というとそういう項目ばかりではなくて…。
フレームワークって色々とやってくれるから便利ってのはもちろんのこと、この辺をあまり悩まなくて済むというのも大きなメリットだよな、と思ったのであった。
# コードハイライトの指定に "Go" がなくて "Python" にしちゃったよ。