実務でRustを使ううえで苦労したこと

高橋優輔氏(以下、高橋):高橋と申します。前職はC++でずっとデスクトップアプリケーションを開発していました。この会社に来て、Rustを2年ぐらい使っているところです。良くも悪くもこの会にちょうどよいRustの理解度を持っているということで、視聴者目線のディスカッションを進行できればと思っています。よろしくお願いします。

ということで、さっそく最初のテーマにいきたいと思います。

お三方のお話をうかがっている限り、ご自身で手を動かしながらゴリゴリRustを勉強していたというのはあると思っています。ただ、実際にキャディに入って、システムの開発の主要言語としてRustを使うという業務経験は、たぶん初めてなんだろうと思っています。

そこには自分で勉強した時と別の苦労があるのではないかなと思っているので、そのへんの話をちょっとうかがいたいと思っています。まず冨田さん、お願いできますか。何かこういうところで苦労はありましたか。

冨田陽介氏(以下、冨田):そうですね。しばらく苦労しかないな(笑)。Rust特有の難しさもあるかもしれませんが、キャディの「Klein」というプロダクトはかなり尖った作りになっています。

例えば、データベースも攻めた作りになっているし、さらにイベント駆動で非同期の処理がガンガン入っていたり、CQRSでリードも出るとライトがきれいに分かれていたり、かなり処理が複雑になっています。

キャディの業務ドメインという複雑さ、プラスそのアプリケーションがすごく攻めた作りになっている、プラスRustという初めての言語の3つが合わさって、けっこう苦労したというのが正直なところです(笑)。

Rustで苦労したのか、その作りで苦労したのかはちょっとわかりませんが、たぶんお二人は、私よりもRustの準備をしたうえで入られていると思うので、そのあたりの肌感覚は聞いてみたいです。

エラーメッセージに対する免疫をつける必要がある

高橋:先ほど八巻さんに、「非同期」という言葉を資料で出してもらいました。やはりKleinの設計というか、出てくる概念の多さとRustには苦労しましたか?

八巻紘士氏(以下、八巻):そうですね。やはり冨田さんが言っていた、アーキテクチャの難しさも一定はあるかなとは思っています。単純にまずディレクトリ構造がどうなっているんだ、どこからどう手をつけたらいいんだみたいなところがありました。

やはり自分で学習する時は基本イチから作るので、どこに何があるかはさすがにわかると思うのですが、実際に動いているプロダクトに入っていくと、まずどこに何があるのか、どこから読めばいいのかという部分に一番苦労したかなと思います。

高橋:なるほど。刈部さんはどうですか、逆に違う感覚などはあったりしますか?

刈部拓未氏(以下、刈部):似たような話になってしまいますが、大規模なものを作ったことはないので、やはり大規模なプログラムの型パズルはけっこう難しいなとは思います。それこそ、先ほど冨田さんが発表していたように、コンパイルエラーを見て、型パズルを直していくみたいなところは、ちょっと免疫をつけながらやっていかないとけっこう大変かなと思います。

proc-macroが多いことで苦労したこと

八巻:あとアレですね。キャディはけっこうproc-macroが多いですね。

高橋:そうそう。

八巻:私のエディタの問題なのかもしれませんが、ちょっと前までCLionとかJetBrainsでマクロの展開があまりうまくいかなくて、コードリーディングをしているだけなのに、途中で読めなくなることが起こっていました。なので、Vimに切り替えて、そこだけ他の解析を使って読むとか、VS Codeにするとかやっていました。そういう変な苦労はありましたね。

刈部:それはVS Codeもありますね。型を頼りに開発していたらrust-analyzerが止まってしまって、急に何もない状態でRustを書かなきゃいけないというのはたまにありますね。

八巻:そうですよね。proc-macro周りでやられることがありますね。

高橋:あのへんはまだツールもちょっとね、未対応なものが多い印象はありますね。私は、rust-analyzerにはVS Codeを使っているのですが、個人的にはけっこう最近がんばっているなあという気はしています。

八巻:そうですね。

ペアオペレーションで感覚が掴めた

高橋:他のマクロだときちんと推論してくれるイメージがありますが、proc-macroはまだかな? そういうのって、プロダクトの規模が大きくなって初めて目の当たりにする問題だと思うのですが、実際、実務で直面する時はどうやって突破しているんですか。エラーメッセージをすごく解読していた冨田さんに聞いてみようかな。

冨田:そうですね。僕は最初、あまりに進捗が芳しくなかったので、ちょっとレイズして、いろいろなエンジニアの人にちょっとずつ時間をもらって。私の業務をペアオペ(ペアオペレーション)してもらいつつ、その人がどういうふうに解読してやっているのかを肌で学べたのはすごく勉強になりました。

先ほど、エラーメッセージに対する免疫という話がありましたが、別にみんなスラスラ空で書いて、それをコンパイルにパァンと通しているのではなくて、エラーメッセージを見ながらゴリゴリとやっているんだなというところが見えました。

「ああ、こうやってやっていくんだ」みたいな感覚がちょっと掴めたのは、自分の中の1つの大きな気づきというか。そういうのは一緒にやらないとなかなか見えないところなので、それはすごくよい経験だったなと思っています。

高橋:なるほど。実務ですでにサバイバルしている人たちから生き延びる術を伝授してもらうみたいな感じなんですかね。

冨田:まさしくそうですね。あとは、いろいろな人を回るたびに「おすすめのキャッチアップの方法ありますか」と聞いてみて、いろいろな勘やノウハウを蓄積するということをやっていました。

社内にはRustができる人が多くサポートも手厚い

高橋:逆にそこを聞かずに自分で突破しました、みたいなことはありますか? どなたでも。

八巻:どうですかね。キャディに関していうと、やはりRustをできる人が多いというのが、すごく得だなとは思っています。

もちろん自分で読むところはありますが、本気でわからなかったら、最悪、人に聞けるというのは、すごくラッキーだなと思っています。

高橋:うんうん。

刈部:難しい部分は、わりと設計周りとRust周りなんですが、今話にあったみたいに、設計周りについてはゼロから作った人たちが運良くまだ在籍しているので、聞けばなんとかなるというのはありますね。

Rust周りだと、同じチームにメチャクチャ仕様に詳しい人がいるので、その方に教えてもらいながら、本当になんかあった時は一緒にやってもらっていますね。

高橋:ざっくりまとめると、実務をやるにあたっては、チームのサポートもけっこう大きいという感じですかね。

刈部:そうですね。かなり手厚いとは思いますね。

高橋:そういう環境は確かに大事かもしれませんね。みなさん苦労はしていますが、チームメンバーの温かい支援もいろいろあったりして解決できている感じですかね。

Rustのメリットは、きちんとコンパイルが通ればバグなく動くという安心感

高橋:では次のトピックです。キャディは、基本的に製造業をやっています。自分で案件を受注しているので、当然その製造業でドメインを支えるためのシステムを作っているというところで、みなさんだいぶ製造業色が濃いプロダクト開発をされていると思います。

ここで開発をするうえで、Rustの良いところ、悪いところをふだん感じることがあるか、ちょっと言語寄りの話もうかがいたいと思っています。

まずメリットからいきたいのですが、今開発をしていて「やはりRustでよかった」みたいなところはありますか。じゃあこれは刈部さん、いってみます?

刈部:そうですね。ある程度そのドメインのモデルを厳密に型でしばっているので、コンパイル駆動で開発していけば、ある程度のものが作れるというのは、すごくメリットとして感じていますね。

あとは、弊社のブログにも載っているのですが、EntityのIDも型で定義しているので、不正な値も型レベルで弾いてくれるというのは、開発していて非常に楽だなとは思います。

高橋:今、ドメインのモデリングをするのにRustの型の設計がやはり生きているという話があったのですが、そのへんをもうちょっと具体的に、例えばRustでこうモデリングできてよかったみたいな話は八巻さん、あったりしますか。

八巻:そうですね。モデリング自体というよりは、やはりWebサービスをやっていくうえで、どうしても型の変換は必要になってくると思うんですよね。httpから受け取って、ドメインの型に変換して、データベースに保存するというところでいうと、最低でも2回は型の変換をかけないといけないので。

そこから厳密な型で弾いてくれるというところでいうと、やはり型変換を書くのはちょっとボイラーっぽいので、つらいはつらいんですが、コンパイルを突破してしまえば、ある程度そこは安心して任せられる部分があるので。

モデリングもそうですが、単純にモデリングをしたうえで、きちんと型変換に真面目に取り組んでパスするということをリスクとしてやっていると、本番で動いた時に急におかしな動きをすることは少ないので。そういう意味でいうと、ちょっと安心感があると思いますね。

高橋:個人的な印象ですが、型変換は確かに負債がけっこう溜まりやすかったり、複雑になりがちな気がしています。きちんとコンパイルが通れば、バグなくバシッと動くというのは安心感があるのかもしれないですね。

Rustは明示的なので、バグが起きそうなところが一発でわかる

高橋:お三方はKleinという受発注のプロダクトを開発されていて、先ほどKleinの設計のここが最先端だという話もありましたが、そのドメインの話だけではなくて、Kleinで採用しているアーキテクチャについて、例えばRustでやっている時にこういうメリットがあったという話が聞けたらおもしろいなと思っています。このへんは冨田さん、いかがです?

冨田:そのへんの古い歴史的なところは正直、僕はあまり把握していないのですが、僕の単純な感想としては、Kleinを作り始めたのは2年とか3年前で、たぶん今よりもさらにエコシステムがない中で、あのWebシステムを作りきった人たちは「単純にすげえな」という感想しかないです(笑)。

高橋:なるほど。

冨田:本当にすごいなあと思っています。

八巻:そこでいうとRustはけっこう明示的です。よくエラーが起きるのは、エラー処理のところとNullが絡むところと、非同期のところだと思うのですが、そこも全部Null絡みはオプションだし、エラー絡みはリザルトだし、非同期はasyncとかが入ってくるというところで、わりと明示的に「ここは非同期で書くよ」「ここはNullがくるかもよ」「ここはエラーが起こるかもよ」と出してくれて、Rustをやっているとバグりそうなところが一発でわかりやすいなあという気がしますね。

高橋:そういう複雑なところもやはりRustだと静的に書いていけるというところなんですかね。

八巻:そうですね。他の言語だと、Nullが勝手に隠れたり、エラー処理を無視してもなんとかできたりするので。そこらへんは暗黙的ではなくて、明示的なよさなのかなという気はします。

高橋:なるほど。

Rustのデメリットはビルド時間

高橋:逆にデメリットを感じることはありますか。

一同:ビルド時間ですね。

高橋:ビルド時間、確かに。みんな今、声がそろいましたね。

八巻:あと、参考になる設計が、やはりまだ足りないという気はします。「DIはどう組んだらいいの?」みたいになった時に、今はキャディにいるから参考になるものがあるけれど、普通のWebを漁ってもなかなか「これが正解だ」というものを見つけるのは難しい気はしますね。

高橋:なるほど。デメリットはビルド時間ぐらいで、言語仕様としてはモダンでよい言語という印象ですかね。

刈部:コンパイルを通すのが大変というのもありますが、結局あとになって起こるバグを、今コンパイルエラーを吐いてくれているだけだと思っています。なので、総じて言語レベルでは、コストにそこまでデメリットを感じないですね。

高橋:なるほど。ではそろそろ時間なので、パネルディスカッションは以上とさせてもらえればと思います。みなさん、どうもありがとうございました。