📕

#12 LayerXにおけるスキーマドリブンな開発とGoについて【ゲスト:ソフトウェアエンジニア中川さん】

文字起こしTranscript

松本:LayerX now!、第12回ですね。 今回も前回に引き続き中川さん、よろしくお願いします。
中川:はい、お願いします。
0:59 プロダクト開発の進め方
松本:中川さんに今回話していただいたいのが、僕らのプロダクト、ほとんどが中川さんのコードベースになっていると言っても過言じゃないと思っていて。
中川:いやそこまでは言い過ぎだと思います(笑)
松本:でもGoの設計思想とかって、どういうツール使おうかとか特に例えばO/Rマッパーのところとかは、どちらかというと中川さんが構築したもの使っていたりするじゃないですか。ああいったものを見ていて、我々のGoの設計思想の、凄く深いところに中川さんの考え方もあるので、そのへんを聞かせてもらいたいと思ってます。よろしくお願いします。 中川さんから見たLayerXの各SaaS事業の設計思想について聞いていきたいんですけど。まずどういったことを考えてこのプロダクトを開発進めていったんですか?
中川:そうですね、最初考えたこととしては、スキーマ駆動、スキーマドリブンで開発していけたらいいなと思っていたのと、自分が今まで慣れた開発手法とかっていうのは使っていて、あとは自分が書いててこれ厳しいなと思った箇所については修正を入れながら作り始めたのが去年(2020年)ですね。 割とGoもかなりの年数書いてきたので、ある程度自分の中にナレッジが貯まっていたというのがあったので、最初はそれをふんだんに入れて開始していました。
松本:前職から考えるとだいぶ長く開発されていますもんね。5年? 昔Goの勉強会とかしていたの懐かしいですね。
中川:そうですね!前職で一度やったあれはありますね。あと5、6年前とかはGoカンファレンスとかも何回か行って最近はあんまり顔は出せていないんですが。ブランクが開いてしまいましたがまた行ってみようと思います。
3:27 スキーマドリブンの背景
松本:書いてる量が相当あるんで、出せるネタがいっぱいあると思います。 特に最初出てきたのがスキーマドリブンってキーワードだったんですけど。スキーマドリブンをとることにした理由っていうか目的みたいなとこってあったんですか?
中川:元々考えていたのが、人間が書く箇所みたいなのは減らしたいって思っていたりしていて。例えばストラクトなフィールドだったりとかJSONのタグだったりとか、人間がポチポチ変えてメンテしていくのって結構やりたくないなって元々思っていて。自分でもやりたくないし、絶対自分もどこかで書き間違いとか起こすし、追加で入った人ももしかしてこれ間違ってる可能性がありますとかって担保ができないとかも長く続けていく上でよくないなと思ったりしたので。 そこで最初にスキーマファイル的なものを考えて定義して、そこからある程度のコードを生成して開発に入っていくというスタイルが自分はいいなと思っていて。それは最初に入れて、今の継続してできている箇所かなと思います。
松本:型のシステムを持った言語を使っていることが我々多いので、スキーマ駆動っていうかスキーマを使って書く型を生成して、間違っているところはシステマチックにあぶり出そうっていうのは結構スピード早くなるって意味でもいいですよね。
中川:ですね。あとはレビューが正確になったりしますね。このスキーマでやっていきますっていうのを最初に宣言するので、自分の頭の整理にもなります。見る人にとっても「あ、こういうことやろうとしているんだな」ってわかりやすいと思うので。
松本:確かにこういうAPIですけどドキュメントから先に入るわけですもんね。
中川:そうですね。あとはそういうコードをGoで書くの退屈だったりするので。 そこらへんは生成したものを使うっていうのが一番自分としてはしっくりきていました。
松本:GoでこういうAPIのハンドラー的なものを書き始めるとむちゃくちゃタイピングマラソンみたいになりますもんね。 もしくはそれをやらないと再利用性のないコードが多かったりして。
中川:結局、Web APIができることって、インプット与えられてそれをどこかしらのデータストアに扱いやすい形で保存していくみたいなことがメインの処理だったりするので。その入口になるインプットはHTTPのリクエストだったりとか出口になるデータベースの設計とかは先に決めてしまって、そこに入れるためのGoのデータモデルというかストラクトだったりは自動で作っちゃうというのが自分的にはしっくりくるなと思っていました。
松本:究極的にはもう、インターフェースにわたってきたオブジェクトをデータベースのオブジェクトに翻訳してあげて、終わり、みたいな世界ですもんね。
中川:そうですね。内部の処理はあとはそれを自分で中を書いていくっていうのが明確になるのでいいですね。
松本:その方がテストもしやすいですもんね。この型のオブジェクトがわたってくるというのがサービスレイヤーにわたしてみたいな時に。 GoのAPI書くにあたって結構クリーンアーキテクチャも設計されているじゃないですか。あちこちのリポジトリ見ていると。この辺の設計思想というか、どういうこと考えてこの設計にしていったのかって、結構論争になりますよね。Goでどういうパッケージ区切りをしていくのかみたいなところって。
中川:確かにそうですね。ここらへんは自分が書いてきたものが大部分にはあるっていうのと、あんまりこう最初いきなり複雑すぎて入るのは、どのプロジェクトでもそうですけどいい判断とは思えないので、最低限でしようっていうのは最初に決めていました。あまりに複雑にパッケージを切りすぎるとかはやりたくないなと思っていましたね。
松本:高江さんもおっしゃっていましたよね、最初は最小限で作ってだんだんと拡張して作るみたいな発想で作るというか。
中川:ですね。最初ベースをイニシャルコミット、ギットでイニシャルコミットしていくときに、mosaさんにせかされて始めたっていうのは1個あるかもしれないですが、ミニマムな形でスタートさせていくっていうのは最初からありましたね。 ある程度Goのコード書いてから事業の形が大きく変わるって形はあまりなかったりはしたんですけど、なるべく早く立ち上げるというか、最初のカスタマーになる自社でどれだけ早く使えるかっていうのは最初から意識されてたところですね。
松本:やっぱり未知のもの作っていると、正直完璧に作って無駄になるよりは、多少あらがあっても進めて、そのときに引き返しやすいアーキテクチャであることくらいを担保するくらいが大事かなっていうのがものすごい同意しますね。
中川:ですね。なので最初書き始めたときはこのサービスってこのドメインでいいんだっけ?って迷いながら、でもコミットはしているみたいな状態で進めていってました。 もちろんそれで間違っている箇所もあったりするので、それは途中で修正して直してみたいなことをやってましたね。やっぱり最初はコード書く人が経理の業務についてのドメインがあったわけではなかったので、この段階からある程度こうだよねっていうのを確かめながら進んでいたのはありますよね。
9:32 Goの好きなところ
松本:未知に対して向き合うときに、最小構成でさっと進められるというのはスタートアップの技術選定として大事だと思うんですけど、その点でいくとGoってどうなんですかね?サクっと書けるって意味では僕は好きなんですけど、人によっては冗長だ!みたいな話もあるじゃないですか。中川さんはどのへんが好きなのかなと思って。
中川:一番自分がいいなと思っているのは、Goのコードを読むのが苦痛な箇所がほぼないというのがあります。困ったらパッケージの中読めばいいし、使うライブラリについてもある程度中身のコードがああこうやっているんだってサクっと読めるので。そこが自分としては一番いいかなって。困ったらコード読めって言えてしまうくらいのシンプルさというのはあるかなと思います。
松本:わかります。標準パッケージすらほぼGoで書かれているので。HTTPパッケージのヘッダーまわりで困ったらパッケージをずっと読んでいたんですけどすぐ読めますもんね。
中川:ですね。なので一番ググって解決というか中のコード見て解決っていうのが自分の中で多かったりしますね。そこらへんはすごくいいなって思いますね。
松本:でもコード読んで解決するって本当はエンジニアの基本的なふるまいなのかもしれないなとも思うんですよね。いいコードってそこから学ぶじゃないですか。使われているツールのを読んで、こんな感じで書いてこんな感じでテストするんだって、僕Go始めた頃そんな印象がありましたね。
中川:そうですね。安易にスタックオーバーフローを読むよりも絶対コード読んだ方が早いみたいな感じはすごい自分も感じてて。なのでググるよりもエディタ内で定義ジャンプしてどんどん関数飛んで遡っていくっていうのがメインになりますね。
松本:書き方のバリエーションが少ないってところからやってくる読みやすさですよね。 一方で今後Goの2.0とかそれ以降のコードってジェネリクス入ってくるじゃないですか。 あの辺ってこの環境変わりそうですね。
中川:でも1.7のジェネリクスのドラフトみたいなのも読んだりもしたんですけど、そこまで扱いに困るかなって感じは受けなかったりしたので、そこはちょっと2.0の方がどれくらい変わるかわからないですけど、自分としてはそんなにデメリットには感じていないですね。
松本:あの処理が簡単になるくらいだと嬉しいですね。もうfor文回しまくるの疲れたよって。
中川:このコード何回書いたんだっていうことがやり始めるとすごく増えますもんね。
松本:あれの中から検索するとか、フィルター抜くとか、めっちゃ書きますよね。ソートするとか。ブラッドフィッツさんの書き方が入ってきてからは割りと楽になりましたけど。ファンクションを出せるようになったやつ。Go2.0とかGo1.17か、とか来たらさっと入れてはみたいですね。
中川:そうですね。今もまあそんなに困っているわけではないんですけども。キャッチアッパーというか追随は絶対に必要になるので。
松本:なんかそれがもし主流になるとね、ついていかざるを得ない時期がこう後にやってくると辛いですし、MySQLのバージョンがどんどん上がっていって追いつけなくなったみたいな辛い話を聞くのは嫌ですからね。
中川:それでいうとまだこのプロダクトは始まってまだ一年経ってないくらいだったりするので、結構モダンな形で始められたっていうのはありますね。やっぱり5、6年経っていると痛む箇所がどんなプロダクトでもあったりすると思うので。
11:45 これから挑戦していきたいこと
松本:やっぱりパッケージの考え方やテストの考え方は5年でだいぶ成熟しましたよね。あと周辺ツールいっぱいあるし。 このGoの開発とか、サーバーサイドとかプロダクト全般でもいいんですけど、ここから1年中川さん的にはこの辺挑戦していきたいなみたいなのってあったりします?
中川:そうですね、やっぱり若干ビジネスロジック、最初に書いたロジックが複雑だったりするので、そこらへんはリファクタリングの予知はあったりするので。ただいかんせん今は手が回っていないのでここやりたいけど…を残しつつ、新しいのに入っていったりは今のメンバー的にそういう形になっていたりするので。どっかでキレイに、今後増えていく人に対しても、わかりやすい箇所は作っていきたいなと思いつつ、あと技術的なことでいくと今まさにやっていたりするんですけど、もうちょっと最初に話したGoでコードをジェネレートする箇所とか、そういった箇所をもうちょっと増やせたらなっていうのは考えていたりしますね。
松本:それってどこらへんを?今プロトコルをGraphQLにしたりしているじゃないですか。そういったところもですか?
中川:ですね。中で使うデータベース、データベースに入れる値ではなくてちょっとこう多少ビジネスロジックが必要な箇所とかっていうのも今まさにやっている箇所とかはあったりしていて。そこはもう少し使えたらなっていうのは思っていたりしますね。特定してしまうとユーザーの権限周りのコードの部分とか、どういう風に権限っていうのを定義してリソースアクセスとめてっていうのの設計を多少やっていたりするので、そこらへんはこう訂正したコードを一部で使っていたりはします。
松本:確かに。別なドキュメントか何かで定義した権限リストに従って、勝手にコードでブロックしてくれてるみたいなのは言われてみると確かにかっこいいですね。
中川:すごい具体を言うと、スペックを定義してそのスペックでアクセスが許可されているか否かは宣言的に書いておいて、それでアクセスがAllowになるかdenyになるかは生成したコード内で判断するというか。そういう箇所は今まさにやっていたりはしますね。
松本:具体的にはどのレイヤーにジェネッたコードが入っていくような設計になっているんですか?聞いている人のイメージを膨らませるために。
中川:それでいうとREST APIとかだとAPIパスによってリソースが決まっていると思うので、そのリソースパスと権限を先に決めておいて、このアクセス、このユーザーっていうのはこの定型パス入ってもいいかっていうのは定義から判断されたコードでミドルウェア内でハンドルされるとかって感じですね。
松本:じゃあSwaggerの定義ドキュメントから、Swagger.yamlのそういうのをジェネってくるって感じですか。
中川:そうですね。あとはこの権限ってどのアクションはしていいんだっけっていうのを定義で書いておくってイメージですかね。
松本:ロボットがスペックを書いたら人に書かせない!っていう思想を感じますね。
中川:ですね!なので最初に吐き出すジェネレートするコードの設計を間違うと結構後戻りが大変なことになってしまうので、そこはちょっと頭を使いながらかなと思っていますね。それも結局最初にやりたいことが明確に決められるものではあるので、スペックとして書いていた方が後々楽だろうなっていうのは思いますね。
松本:後はスペックを見ればふるまいが予測できて、今度は品質補償にも活かせたりとか。最近Autifyで自動化していたりすると思うんですけど。あのへんにもドキュメントを渡せばすぐAutifyの方でどう書くべきか理解できるみたいなのはいいですよね。
中川:そうですね。スペックファイル書くと人間が読む分にも優しい箇所もあったりするんですけど、一番いいのは機械がそのスペックを解釈できるというか。そこは自分としては書いていて楽しい箇所というか、うまいことこのスペックからGoのプログラミング使って、またGoのコードを作るみたいな。そういうことをやる時間は楽しかったりします。
松本:ここから時間が進んでくるとどんどん人が、ほんとビジネスロジックそのものに集中していって、それ以外はもうスペック書いたら終わりますみたいな。
中川:ですね。その世界は早く来ないかなって思いますね(笑)
松本:来ないかなとというよりは作っているあたりが。
中川:そうですね。そこがやっぱりあるべきというか、目指すべき姿かなとちょっと思ったりはしますね。不用意に人間が書いていくのではなくて、ある程度生成したものの中で、できない箇所だけ自分で書くとか。そういう基盤は整えていきたいですね。
松本:あとはこういうことに楽しさを見出してくれる人には来てほしいですね。
中川:そうですね!それを考えながら作っていけるので。
松本:多分3、4年前に考えていたGoの書き方とは全然違う世界になっているじゃないですか。スペック書いてジェネって、あとはちょっと糊付けをするみたいな。そういう新しい地平を切り開こうぜみたいなのはどんどんやっていきたいですよね。結構Goのカンファレンスの界隈とか、結構Goジェネレートをずっと研究していると思うんですけど。どんどんうちの事業でもやっていきたいですね。
中川:そうですね!なんかほんとに、よくあるHTTPを生成するとか、データベースをスキーマからストラクト作るとか、結構汎用というかメジャーな手段になってきていると思うんですけど、ある程度さっき話した権限とか、ちょっとしたビジネスのドメインが関わる箇所も、作っていけたらいいなと考えていますね。
松本:いやしかし、こうやって話していて、まったくブロックチェーンの話が出てこないあたりが、もうブロックチェーンの会社になったなって感じがしますね。
中川:ですね。
20:47 LayerXに来て欲しい人
松本:ちょうどお時間が近づいてきたので、後ろの予定もあるかなと思うので、このへんにしようかなとは思っていますけれど。一緒にGoでどうあるべきか、われわれの設計はこういう風にあるべきとよりお客さんの価値を届けることに集中できるよねみたいな。そこに集中するための基盤を作っていくことを面白い!と感じてくれるエンジニアだったら凄く楽しいんじゃないかなって雰囲気を勝手に感じました!と勝手にまとめました。最後中川さんから伝えておきたいこととか、こういう人来てほしいなとかこういうポジション募集中ですみたいなのがあれば。
中川:そうですね。もちろん正社員でのエンジニアの採用もあったりするんですけど、Bizサイドもエンジニアサイドも、最近、先週インターンの開始もあったりしたので是非インターンで入りたいって人は。自分もそうだったので。大学のインターンからエンジニアとかのキャリアをスタートしたので、興味ある人は是非って感じで思いますね。
松本:いいですね。是非一緒にGoを書きたい学生さんでもいいですし、一緒にビジネスやりたい学生さんでもいいですし、インターン来てほしいですね。ありがとうございます。 というわけでLayerXNOW!、第12回、前回に引き続いて中川さんに来ていただいてGoの話なんかをさせていただきました。ありがとうございました!
中川:ありがとうございました!