じゃあ、おうちで学べる

本能を呼び覚ますこのコードに、君は抗えるか

2026-05-01から1ヶ月間の記事一覧

ドメイン規約を lint で表現する — `Order` に `is_paid + payment_id` を共存させない

はじめに 長年、動いた DB を覗くと、たいていこういうレコードが眠っています。 { "order_id": 12345, "is_paid": true, "payment_id": null } is_paid = true なのに payment_id は null。 ドメイン上、 同時に成立してはいけない組み合わせ が静かに残り…

`rowan` で自家製 lint を書く — rust-analyzer の心臓部を流用する

はじめに エディタで .unwrap() を書いた瞬間、 clippy が黄色い波線を引きます。match で variant が漏れた瞬間、コンパイラが赤い波線を引きます。これは魔法ではなく、 rust-analyzer が rowan で構文木を作り、その上をルールが歩いている というしくみ…

31歳、もちろん俺らは抵抗するで?筋肉で

はじめに ※この筋肉はイメージであり現実の肉体とは乖離がある場合があります。 ある誕生日の朝、通知が、なかった。 母親からだけ、メッセージが来ていた気がする。 俺の人生はLINEの量で決まるかと嘯きながら、LINEの誕生日表示を非公開にした。20代の、ど…

コンパイル時に未設定フィールドを禁止する type-state builder

はじめに Builder パターンで「url を設定する前に build() を呼んでしまった」事故を、 コンパイルエラーで止める 書き方があります。type-state pattern と呼ばれています。PhantomData を使って builder の進捗状態を型に乗せる、 Rust 固有の idiom です…

自分のクレート外の型にメソッドを生やす — extension trait と sealed pattern

はじめに 「String に独自メソッドを追加したい」「外部クレートの型に1メソッドだけ生やしたい」場面があります。Rust の orphan rule のせいで、外部クレートの型に外部クレートのトレイトを直接実装するのは無理です。代わりに 自分のトレイトを定義して…

`lazy_static!` はもういらない — `LazyLock` と `OnceLock` の使い分け

はじめに Rust で「グローバル変数を遅延初期化したい」となったとき、長らく lazy_static! クレートが定番でした。今 (2026年) はもう不要です。標準ライブラリの LazyLock (1.80+) と OnceLock (1.70+) で全部書けます。マクロや外部依存も要りません。 た…

`Cow<'_, T>` で「変更が必要なときだけ allocate する」

はじめに 入力をそのまま返すか、一部書き換えてから返すか、関数の中で判定する場面があります。素直に書くと「変更しない場合も無駄に String::clone() してしまう」、または「&str を返したいが、変更があった時は所有データを返したい」というジレンマに…

newtype と `PhantomData` で「混ぜたら型エラー」を作る

はじめに UserId と OrderId を取り違えてバグを生み出す経験は、String で識別子を扱っていれば誰しもあります。Rust では newtype で別の型に分けるだけで、コンパイラに止めてもらえます。さらに PhantomData を組み合わせれば、「JPY と USD を足し算す…

おい、要件を動くものにしろ

はじめに ドキュメントは、書いた瞬間から腐っていく。 読まれない。検証されない。更新されない。それでも、要件と呼ばれ続けている。 第1部では、要件を言葉にする規律について書きました。引き出し、観察し、ジョブを見極めながら、業務領域の言葉で書く…

`NonZero<T>` で「ゼロではない」を型に乗せる

はじめに ゼロ割り、ゼロサイズ確保、ゼロインデックス。「ゼロでない数値」を期待する場面はあちこちにあります。これを runtime チェックではなく 型 で保証できる仕組みが NonZero<T> です。 Rust 2024 edition で書き味がさらに素直になりました。これまで</t>…

`thiserror` と `#[non_exhaustive]` で SemVer に強いエラー型を作る

はじめに Rust で「ライブラリのエラー型をどう設計するか」は永遠のテーマです。素朴な答えは2つあります。 アプリケーションなら anyhow で済ませる ライブラリなら thiserror で型付きエラーを返す これは2026年でも変わりません。この記事は「ライブラリ…

`if let` chain — Rust 1.88 / 2024 edition で実用フェーズに入った

はじめに Rust 1.88 (2025年) で if let chain が安定化されました。2024 edition のコードでは積極的に使えます。 && で if let 条件を連結できるようになり、ネストした if let を平らに書ける構文です。短い変更ですが、効果は大きく出ます。 何を解決す…

`let-else` で早期 return を素直に書く

はじめに Rust の let-else 構文は、Rust 1.65 (2022年) で安定化された機能です。古くからある機能ですが、2024 edition のクリーンなコードベースでは多用されます。clippy の manual_let_else ルールも 2024 では使うことが推奨されます。 「Option が No…

`unwrap()` を書きそうになったときの選択肢8つ

はじめに Rust で Option や Result から値を取り出すとき、つい .unwrap() を書いてしまう場面があります。動くし短い。だから書く。だけどそのコードは、エラー時にスタックトレースなしで panic します。本番で踏むと 「どこで何の理由で死んだのか」 が…