Findy Engineer Lab

エンジニアの"ちょい先"を考えるメディア

Rustを学ぶなら、エラーメッセージを読め? アウトプット重視の「コンパイルエラードリブン学習」とは

f:id:poniki:20220101120636p:plain

モダンな言語の一つであるRust。実行速度の速さや型の多さ、コンパイルの優秀さなど、さまざまなメリットがある一方で、「所有権」など独特の概念があり、難しい印象を持っている人も少なくないのではないでしょうか。
また、プロダクト開発においてRustを採用する企業が少しずつ増えているものの、まだまだ少数派であり、言語自体の特徴や開発する上でのメリット・デメリットについては知られていないことも少なくありません。
FindyではRustの魅力を広めるため、2021年11月11日(木)に、4回目となる最新バックエンド井戸端会議を開催しました。製造業のDXを進めているキャディの長田さんと、経済活動のデジタル化を推進しているLayerXの須藤さんをお招きし、Rustで開発していて感じたことや学習方法について語っていただきました。

本稿ではイベントで語られた中から一部を抜粋し、Rustのメリットや苦労話、学習のコツについてまとめています。

パネリスト
長田 歌菜さん/(キャディ株式会社)@ngtkana
キャディ株式会社で活躍。3D CAD 解析、製造原価計算を経て、現在は画像形式の図面から制作物の仕様を読み取るアルゴリズムを書いている。

須藤 欧佑さん/(株式会社LayerX)@zoom_zoomzo
LayerX創業期に参画し一貫してデータのプライバシー保護の研究開発をリード。暗号学的手法を用いたプライバシー保護プロトコルやCPUセキュリティ機能を応用したAnonifyを新規に開発し、現在はデータ分析におけるプライバシー保護手法の開発に従事。

モデレーター
佐藤 将高/(ファインディ株式会社) @ma3tk
東京大学 情報理工学系研究科 創造情報学専攻卒業後、グリーに入社し、フルスタックエンジニアとして勤務する。2016年6月にファインディ立上げに伴い取締役CTO就任。

使用している企業が少ない中で、なぜRustを採用したのか?キーワードは「スピード」「コンパイル」「特殊なライブラリ」

まず初めに、キャディとLayerXがRustを採用した背景についてお伺いしました。

長田さん「Rustを採用したきっかけは、生産管理・原価計算というプロダクトを内製化するプロジェクトだと聞いています。当時のキャディではC++やPythonなど、さまざまな言語を使用していたのですが、新しいプロジェクトを始めるにあたり、堅牢なものを作っていくには、コンパイル時の検査が強いことに加えて高速であることを条件に掲げていました。最初は、Rust/Go/Kotlin/Javaが候補に挙がり、そこからスピード重視でRustとGoの二択となり、最後は社内にRustを使えるエンジニアが数名いたため、そのまま採用することになったようです。」

──会社の中にいるエンジニアによって言語選定の方向は変わっていきますよね。LayerXでRustを採用された理由もお教えいただけますか?

須藤さん「そもそもの背景からお話しすると、現在私が所属しているチームでは、プライバシーの保護や秘匿化といったところをRustで開発しています。

Rustを採用したのは2019年の初めで、当時はチームではなく、私一人のプロジェクトという形でした。その時は暗号技術を使った秘匿化プロトコルの開発に取り組んでいて、ゼロ知識証明といった高度な暗号ライブラリが充実しているのがRustしかないという状況でした。CPUのセキュリティ機能を活用したアプリケーション開発で実際に使ってみたら、Rust SDKが優れていたので、そのまま継続してRustを利用しているという流れです。」

それぞれに採用理由は異なるものの、大きな理由としては、スピード、コンパイル、特殊なライブラリが使えるという3つが挙げられました。

また、長田さんと須藤さんは会社で導入するまでRustの使用経験がなかったそうで、学習方法については「社内でRustを使えるエンジニアに教えてもらいました(長田さん)」「O'ReillyのRustに関する本でイチから学習しました(須藤さん)」とお話しされていました。

Rustを使っていて嬉しいと感じる瞬間は、整理された形でコードを管理できた時

プロダクト開発でRustを使用する中で感じたメリットについても語っていただきました。

長田さん「Rustのメリットは大きく3つあると思っています。一つ目は、環境構築が簡単にできて、ビルドの再現性も高いというところ。比較対象の言語によって少し異なる部分もありますが、ビルドって難しいと思うんですよね。Rustはビルドを再現する難易度も低いですし、静的チェックが充実しているので、テストが少なくて済む。Rustを習得している人であれば、オンボーディングコストが低いというのもポイントです。

二つ目は型の強さですね。型自体が要件を表しているので、別の人に引き継ぐ時でも型そのものがコメントの役割を一部果たしてくれます。そのため、結果的にコミュニケーションコストを下げられるんです。

最後は実行速度の速さ。オブジェクトを作ると遅くなるとか、抽象化するとコストがかかるとか、読みやすさと実行速度がトレードオフになるというのは珍しくないことだと思うのですが、Rustは書きやすい上に早く実行できるので、その辺の喧嘩がないです。」

Rustを書きやすい言語だと評価する長田さん。須藤さんは、メモリの安全性やスピードをメリットにあげつつ、実装レベルでの設計のしやすさが気に入っていると話します。

須藤さん「Rustは手続き型言語すぎず、型に最低限の振る舞いを定義していく感覚でコードを管理できます。そのため、レビュー時も読みやすいし、コードベースが大きくなっていったとしても管理しやすいんですよ。

あと、フレームワーク的なプロトコル実装をする際、フレームワークのような部分を抽象的に書いていけるし、コードの管理もできる。   ▲具体例

上のコードは少しわかりにくいかもしれないのですが、実際のEcall Controllerみたいな関連型として、『こういった振る舞いをして欲しい』『このプレートにはこういう型が定義されて欲しい』ということを抽象的に書けたり、整理された形で管理できたりするのは、Rustを使っていて嬉しいところです。」

続けて、Rustのビルド兼パッケージマネージャである「Cargo」の優秀さについても語られました。

須藤さん「長田さんがお話しされていた『型の強さ』にも影響してくるところで、Rustはエラーのメッセージがすごい優秀なんです。どこがどう間違えているのかということに加えて、参考リンクも教えてくれるので、エラーが出たとしても高速に実装できる。Cargoに助けられているなと感じます。」

発展途上だからこその“成長痛”もある。伸び代のある言語を使う面白さ

長田さんと須藤さんは、ビルドの再現性が高い、型が強い、設計がしやすいなど、Rustのメリットについて語る中で、モダンな言語だからこそのデメリットもあると話してくれました。

長田さん「ビルドの再現性が高いというのは事実ではあるのですが、少し時間がかかってしまうのと、キャッシュが大きいというのはデメリットだと感じます。キャディのバックエンドは大体Rustで開発しているのですが、複数プロジェクトを動かして並行してビルドすると、すぐにディスク容量がいっぱいになってしまい、泣く泣くプロジェクトを消すなんてことも……(苦笑)。

あと、ライブラリや言語機能に発展途上の部分が多いという点も、Rustを使う上で避けては通れない課題です。例えばRustのバージョンアップに追従してサードパーティライブラリがバージョンアップしたものの、互換性がないなんてことも。

アップデートの際に発生する互換性の問題やライブラリの不具合など、“成長痛”のようなものがある一方で、長田さんはそれはポジティブなことにも捉えられると話します。

長田さん「発展途上の部分が多いというのは、“発展する余地がある”とも言い換えられます。まだまだ伸び代のある言語だということですし、今後に期待ですね。また、Rustには大きなフレームみたいなものがないので、自分たちで構成を考えないといけない。それは大変だと感じることもあるかもしれませんが、人によっては楽しいところだと思います。」

──ありがとうございます。須藤さんはどうお考えですか?

須藤さん「長田さんと重複するところもあるのですが、コンパイル、ビルドが遅いのはやはりデメリットだと思います。アップデートで改善されてきてはいますが、まだまだ遅いし、キャッシュのバイナリも大きくなってしまう。CIが遅くなってしまうのも辛いところです。大きいプロジェクトでシェアする時は、ちゃんと並列化するなど工夫してあげる必要があります。

あと、非対応のSDKやライブラリがあるのもデメリットであり、相性がいいコミュニティとそうでないものがあるという気がしていますね。」

──クラウドやサービスのSDKは、JSやPythonが主流ですしね。

須藤さん「AWSは最近オフィシャルなものが提供され始めている状況なので、今後に期待ですね。」

Rustを習得する際は、アウトプット重視の“コンパイルエラードリブン学習”がおすすめ

「Rustを習得したい」というエンジニアが少なくない反面、習得が難しいイメージがあるRust。長田さんと須藤さんは「とにかく挑戦してみることが大切だ」と話します。

須藤さん「Rustの言語仕様は良くも悪くも充実しているので、初期の学習コストが比較的高くなりがちだというのは事実だと思います。私も学習し始めた当初は『こんなにたくさん覚えることがあるんだ』と思いました。言語の仕様やSyntax的なものを覚えようと思ったらキリがないですよね。

そこで、イチからRustを勉強した実体験を踏まえて私が提案したいのが、“コンパイルエラードリブン学習”です。これは私が勝手に名付けました(笑)。これが何なのかというと、Rust by Example(以下:ドキュメント)に書かれている具体例をみて、最低限の知識が身に付いたら、簡単なものでいいのでRustを書いてみる。そうすると、最初はコンパイルエラーが頻発すると思うので、そのメッセージを受けて学習するというものです。実際に私もその方法で学びました。

Rustにはコンパイルだけでなく、linkerのようなレベルで警告してくれるClippyというツールもありますし、インプットよりもアウトプットして学習していくというのが、習得の一番の近道だと思います」

イベントでは、すでにRustを書いたことのあるエンジニアに向けて、須藤さんがよく利用されているcrates(ライブラリのようなもの)についてもご紹介いただきました。

須藤さん「便利なcratesもたくさんあるんですが、入れる量によっては機能が拡張されすぎてしまう。先ほどお話しした互換性問題に加えて、使えば使うほど内部で依存が起きてしまうんです。そのため、個人的な方針としては、cratesみたいなものは最小限にしたいと考えています。上記は私がよく使っているものをまとめたものなので、参考になれば幸いです。」

──ありがとうございます。長田さんはRustの学習方法についてどう思われますか?

長田さん「もともとどんな言語を使えるのかによって難易度は変わってくると思います。例えば、C++を書けるエンジニアであれば、Rustを学ぶ際にそれほど難しさを感じることないのではないでしょうか。逆にPythonやJavaScriptを中心に書いている人であれば、少し難しく感じることもあるかもしれません。

でも、個人的には独学に向いている言語だと思っています。先ほど須藤さんが挙げられていたドキュメントは10ページくらいでサッと読めますし、公式で管理している範囲が広いので情報に迷うことはありません。例えば『crates.io』で検索すると、Rustで使えるcratesが一覧で確認できるページがあるんですよ。

あと、コミュニティの皆さんはとても面倒見がよくて、人に教えるのが好きな方も多いので、Twitterとかで質問したらいろんな人が教えてくれます。rust-jpのSlackにも初心者用のチャンネルがあるので、とても優しい世界だと思います。」

エラーメッセージを読んで学習。まずは簡単なツール作成から試してみよう

イベントの終盤、須藤さんからRustを使う上でのポイントについて語られました。

須藤さん「Rustは色々工夫して書ける反面、かっこよく“書けすぎてしまう”こともあるのかなと思っていて。チームで開発する場合、Rustに慣れている人と不慣れな人がいるので、かっこよく書こうとした結果、コードの可読性が下がってしまい生産性の低下につながる可能性もあります。そういった意味では、Rustには“愚直なコード”が必要な時もあるのかもしれません。

色々お話しましたが、最初の学習を乗り切ることができたら、とても便利な言語だと思います。」

続けて長田さんからは、参加者に向けて下記のようなメッセージが送られました。

長田さん「Rustは対応している範囲が広いので、大体のものが作れるのではないでしょうか。CLIとかちょっとした自動化ツールとかだと、サクッと作れると思うので、興味のある方は、ぜひ試しみてください。」

今回のイベントでは、Rustのメリット・デメリットに加えて、学習方法やポイントについても語っていただきました。

「興味はあるけど難しそう」と思っていた人も、まずはドキュメントを読むところから、試してみてはいかがでしょうか。

Findyでは、Rustを採用している企業の求人を特集しています。 今回登壇いただいたキャディを含め、6社の求人が掲載。 「実務でRustを使いたい!」「Rustの技術をもっと磨いていきたい!」という方はぜひチェックして、気になる求人には「いいかも」してみてくださいね。
f:id:poniki:20211224130540p:plain Rust求人特集はこちら!