Upgrade to Pro — share decks privately, control downloads, hide ads and more …

満を持して始めるRust

 満を持して始めるRust

Developers Summit(デブサミ)
9-B-9 02/09 17:45 ~ 18:25
「満を持して始めるRust」kenkoooo

RustはC++の代替となることが期待されていることから、低レイヤ向け言語という印象を持っている方も多いかもしれません。しかし、Rust 1.0のリリースから7年ほど経ち、言語そのものだけでなく周辺のライブラリやツールも充実し、普段遣いのプログラミング言語として快適に開発できる環境が整っています。

本セッションでは、今日からRustで開発をスタートすることを目指し、Rustそのものの紹介だけでなく、実際の開発におけるコードの書き方や、estieでの導入事例をご紹介します。

estie | エスティ

February 09, 2023
Tweet

More Decks by estie | エスティ

Other Decks in Programming

Transcript

  1. 満を持して始める Rust
    2023/02/09
    @kenkoooo
    株式会社 estie

    View Slide

  2. ようこそ!
    ● 今日から Rust を始める人

    View Slide

  3. 自己紹介
    ● @kenkoooo
    ● 株式会社 estie
    ● ソフトウェアエンジニア

    View Slide

  4. @kenkoooo
    1. ニート (自宅警備)
    2. 国立情報学研究所 (アルゴリズム研究補佐)
    3. リクルート (リアルタイム広告配信)
    4. SoundHound (車載 AI スピーカー)
    5. Indeed (求人検索サービス)
    6. estie (商業用不動産 SaaS )

    View Slide

  5. @kenkoooo
    競プロやってます!

    View Slide

  6. @kenkoooo
    競プロサイト作ってます!
    https://kenkoooo.com/atcoder/

    View Slide

  7. estie
    ● estie = 商業用不動産テック
    ● 新しく不動産業務用サービスを開発中
    ● フロントエンド : Next.js
    ● バックエンド : Rust

    View Slide

  8. Rust とは

    View Slide

  9. Rust とは?
    ● Mozilla で開発開始したプログラミング言語
    ● コンパイラがメモリ安全性を保証
    ● 1.0 リリースから 8 年弱
    ● 広く使われるようになってきた

    View Slide

  10. Firefox では Rust の初期の使用例のひとつ
    https://hacks.mozilla.org/2016/07/shipping-rust-in-firefox/

    View Slide

  11. Dropbox が同期エンジン Nucleus を Rust で実装
    https://dropbox.tech/infrastructure/rewriting-the-heart-of-our-sync-engine

    View Slide

  12. AWS のコンテナホスト用 Linux ディストリビューション
    https://aws.amazon.com/blogs/opensource/announcing-the-general-availability-of-bottlerocket-an-
    open-source-linux-distribution-purpose-built-to-run-containers/

    View Slide

  13. Windows の一部を Rust で実装
    https://msrc-blog.microsoft.com/2019/11/07/using-rust-in-windows/

    View Slide

  14. Android の一部を Rust で実装
    https://security.googleblog.com/2022/12/memory-safe-languages-in-android-13.html

    View Slide

  15. Linux カーネル

    View Slide

  16. 乗るしかない、このビッグウェーブに!

    View Slide

  17. Rust を始めよう!
    Q. でも難しいでしょ?
    A. 大丈夫!

    View Slide

  18. そもそもプログラミングが難しい!

    View Slide

  19. そもそもプログラミングが難しい!
    class Foo:
    def __init__(self, a):
    self.a = a
    def foo(self):
    self.a.append("Foo")
    class Bar:
    def __init__(self, a):
    self.a = a
    def bar(self):
    self.a.append("Bar")
    a = []
    foo = Foo(a)
    bar = Bar(a)
    foo.foo() # a = ["Foo"]
    bar.bar() # a = ["Foo", "Bar"]
    ● Foo:
    ○ a を変数にとる
    ○ a に要素を追加する
    ● Bar:
    ○ a を変数にとる
    ○ a に要素を追加する

    View Slide

  20. そもそもプログラミングが難しい!
    class Foo:
    def __init__(self, a):
    self.a = a
    def foo(self):
    self.a.append("Foo")
    class Bar:
    def __init__(self, a):
    self.a = a
    def bar(self):
    self.a.append("Bar")
    a = []
    foo = Foo(a)
    bar = Bar(a)
    foo.foo() # a = ["Foo"]
    bar.bar() # a = ["Foo", "Bar"]
    ● Foo:
    ○ a を変数にとる
    ○ a に要素を追加する
    ● Bar:
    ○ a を変数にとる
    ○ a に要素を追加する
    Rust ではコンパイルが通らない

    View Slide

  21. そもそもプログラミングが難しい!
    class Foo:
    def __init__(self, a):
    self.a = a
    def foo(self):
    self.a.append("Foo")
    class Bar:
    def __init__(self, a):
    self.a = a
    def bar(self):
    self.a.append("Bar")
    a = []
    foo = Foo(a)
    bar = Bar(a)
    foo.foo() # a = ["Foo"]
    bar.bar() # a = ["Foo", "Bar"]
    ● Foo は a を更新する
    ● Bar も a を更新する
    → メンバ変数が勝手に更新される

    View Slide

  22. そもそもプログラミングが難しい!
    class Foo:
    def __init__(self, a):
    self.a = a
    def foo(self):
    self.a.append("Foo")
    class Bar:
    def __init__(self, a):
    self.a = a
    def bar(self):
    self.a.append("Bar")
    a = []
    foo = Foo(a)
    bar = Bar(a)
    foo.foo() # a = ["Foo"]
    bar.bar() # a = ["Foo", "Bar"]
    ● Foo は a を更新する
    ● Bar も a を更新する
    → メンバ変数が勝手に更新される
    Foo も Bar も a も、
    どのタイミングで更新されるか、
    把握する必要がある。

    View Slide

  23. そもそもプログラミングが難しい!
    こういった状況に陥らないために……
    ● 「この変数は書き換えて良い?」を確認する
    ○ 誰も参照していなければ OK
    ● 人力で確認するのは大変
    ● コンパイラ!何とかしてくれ!

    View Slide

  24. コンパイラが強い
    ● Rust ではコンパイラが何とかしてくれる
    ● コンパイル時に弾く → 実行時は安心
    ● " 所有権 " によって解決
    ● 「一生コンパイルが通らない」
    ● コンパイラに概念を教えてもらえる

    View Slide

  25. 所有権
    所有権も難しくない(普通に使う分には)
    ● 自分が持っている変数
    ○ 好きにしていい
    ● 他人から借りている変数
    ○ 複数人で参照できる、かつ、誰も書き換えられない
    ○ 1 人しか参照できない、かつ、書き換えられる
    → コンパイラが自動でチェックしてくれる

    View Slide

  26. Rust は難しい?
    ● そもそもプログラミングが難しい!
    ● " 所有権 " によって解決
    ● コンパイラが教えてくれる

    View Slide

  27. Rust を始めよう!
    Q. でも OS もブラウザも作らないしなぁ……
    A. 普通に便利な機能がたくさん!

    View Slide

  28. Rust の便利機能
    ● Result
    ○ エラーハンドリングをシュッとできる
    ● enum
    ○ パターンマッチをシュッとできる
    ● trait
    ○ ジェネリック関数をシュッとできる

    View Slide

  29. Rust の便利機能
    ● Result
    ○ エラーハンドリングをシュッとできる
    ● enum
    ○ パターンマッチをシュッとできる
    ● trait
    ○ ジェネリック関数をシュッとできる

    View Slide

  30. よくある Java
    いかにも例外を投げそう!
    String readFile() throws IOException {
    ...

    View Slide

  31. よくある Java
    例外を投げなそう……?
    String readFile() {
    ...

    View Slide

  32. よくある Java
    残念!例外を投げます!
    インターフェースから判断がつかない!
    - 中身を読むしかない
    - 最悪、本番で踏むことに……
    String readFile() {
    ...
    throw new RuntimeException(ioException);
    }

    View Slide

  33. Rust では
    エラーを返すかもしれない関数は Result を返す
    エラーを返すかどうか、
    インターフェースから判断できる!
    fn read_file() -> Result {
    ...

    View Slide

  34. よくある Go
    インターフェースから判断できる
    func ReadFile() (string, error) {
    ...

    View Slide

  35. よくある Go
    型でエラーハンドリング忘れを防ぐ
    result, err := ReadFile()
    if err != nil {
    // ...
    }

    View Slide

  36. よくある Go
    よくある早期 return
    result, err := ReadFile()
    if err != nil {
    return nil, err
    }

    View Slide

  37. よくある Go
    これメッチャ書く
    if err != nil {
    return nil, err
    }

    View Slide

  38. Rust では
    Rust では "?" で早期 return できる
    "?" をつけた Result が Err なら、そのまま return
    let result = read_file()?;

    View Slide

  39. Result まとめ
    ● 失敗しうる関数は Result を返す
    ○ エラーハンドリングを見落とさない
    ● "?" で早期 return できる
    ○ if err != nil: からの解放
    Result 以外にも便利な機能がいっぱい!

    View Slide

  40. 簡単に始める Rust
    〜ライブラリ紹介〜

    View Slide

  41. Rust を始める
    Web フレームワーク "actix-web"
    他の言語と同じ感覚で作れる
    use actix_web::{get, web, Responder};
    #[get("/hello/{name}")]
    async fn greet(name: web::Path) -> impl Responder {
    format!("Hello {name}!")
    }

    View Slide

  42. Rust を始める
    フロントエンド "yew"
    ● ほぼ React
    ● Wasm に変換される
    use yew::prelude::*;
    #[function_component]
    fn App() -> Html {
    let counter = use_state(|| 0);
    let onclick = {
    let counter = counter.clone();
    move |_| {
    let value = *counter + 1;
    counter.set(value);
    }
    };
    html! {

    { "+1" }
    { *counter }

    }
    }
    fn main() {
    yew::Renderer::::new().render();
    }

    View Slide

  43. Rust を始める
    デスクトップアプリ "tauri"
    ● Electron のように JavaScript で実装する
    ● Rust でモジュールも書ける

    View Slide

  44. 今日から Rust 生活!

    View Slide

  45. 今から始める Rust
    2023/02/09
    @kenkoooo
    株式会社 estie

    View Slide

  46. Rust 導入事例
    2023/02/09
    @kenkoooo
    株式会社 estie

    View Slide

  47. estie でのウェブサービス開発事情
    ● 商業用不動産市場の課題を解決したい!
    ● 深く複雑な課題 → 単一プロダクトでは解決しきれない

    View Slide

  48. estie でのウェブサービス開発事情
    ● どんどん新しいプロダクトを作る
    ● 共通ライブラリ等そんなにない
    ○ プロダクトごとに、ユーザーの業態が違う
    ○ マイクロサービス化
    ● 内側の言語は気にならない
    ○ API 越しに話す

    View Slide

  49. estie でのウェブサービス開発事情

    View Slide

  50. estie での Rust 選定理由
    ● エラー処理・ Null 処理に強い
    ○ Result / Option で型レベルでチェック
    ○ 本番 try-catch 忘れ・ NullPointerException 回避
    ○ 人間が気をつける必要なし
    ● コンパイラが厳しい
    ○ チーム開発でコードの品質を担保
    ● 豊富な公式開発支援ツール
    ○ clippy: Linter
    ○ rust-analyzer: エディタを Rust IDE 化する

    View Slide

  51. すごいぜ clippy
    clippy の提案で Rust を勉強できる

    View Slide

  52. 開発者事情

    View Slide

  53. estie の Rust 開発者
    ● estie で初めて Rust に触るという人が多い
    ○ 前々から興味があった
    ○ たまたま配属先が Rust を使ってた
    ● バックグラウンド様々
    ○ JavaScript などフロントエンド
    ○ Ruby on Rails など動的型付け言語
    ○ C++ (競技プログラマ)

    View Slide

  54. estie の Rust 入門
    ● Rust 研修なし
    ● ハマるポイントが人それぞれ
    ● 稼働中のサービス
    ○ 動かしながら学ぶ
    ● ペアプロ・モブプロ
    ● コードレビュー

    View Slide

  55. ハマりポイント
    ● Result / Option
    ● マクロ
    ● 非同期処理
    ● 文字列操作
    ● 所有権

    View Slide

  56. Result / Option
    ● Result
    ○ 失敗しうる関数を try-catch しない
    ○ 戻り値が成功 or 失敗の情報を持つ
    ● Option
    ○ nullable な値
    ○ 型レベルで定義
    ○ null check 忘れを防ぐ

    View Slide

  57. マクロ
    ● コンパイル時にコードを生成する
    #[derive(Clone)]
    struct A {
    x: i64,
    s: String,
    }
    struct A {
    x: i64,
    s: String,
    }
    impl Clone for A {
    fn clone(&self) -> A {
    A {
    x: Clone::clone(&self.x),
    s: Clone::clone(&self.s),
    }
    }
    }
    マクロ展開

    View Slide

  58. マクロ
    ● コンパイル時にコードを生成する
    ● 「いったん理解せずにコピペ」になりがち
    ○ 必要になったら勉強する

    View Slide

  59. Rust に入門してみて
    ● 「目が慣れたら分かる」
    ○ "?" とかは最初は見慣れない
    ● 「 Result / Option は慣れるまで難しい」
    ○ 関数型言語の経験があると違うかも
    ● 「オブジェクト指向の考え方は通用する」
    ○ 「継承」ができないくらい
    ● 「難しい印象を持っていたが、そうでもない」
    ○ 直感的に書ける
    ○ 色々な書き方があるので、動くものは書ける

    View Slide

  60. 会社で Rust !

    View Slide

  61. ありがとうございました!

    View Slide