やあ。Dartの世界へようこそ。
FlutterやDart VMの深淵に触れていると、「Null」という存在がどれほどエンジニアを悩ませ、そして実行時のクラッシュを生むトリガーになるかを痛感させられます。
今日は、Dartの「Sound Null Safety(健全なNull安全)」を正しく守りつつ、さらに一歩進んだ「例外を投げない堅牢なアーキテクチャ」について話をしよう。
「Nullチェック地獄」から抜け出し、関数型プログラミングのエッセンスを取り入れた設計手法を、一緒にマスターしていこう。
—
1. なぜ「Nullを返す」ことが危ういのか?
DartのNull安全は、コンパイル時に「ここにはNullが入り得るぞ」と厳格に教えてくれる素晴らしい仕組みです。しかし、API設計で「失敗した時にnullを返す」というアプローチを多用すると、呼び出し側は常に `if (result == null)` というチェックを強いられることになります。
// ありがちな「Nullで失敗を表現する」設計
User? fetchUser(String id) {
if (database.isOffline) return null; // 失敗がNull
return User(id: id);
}
// 呼び出し側:Nullチェック地獄の始まり
final user = fetchUser(‘123’);
if (user != null) {
print(user.name);
} else {
// ここでエラーハンドリングが必要だが、なぜ失敗したか分からない
}
このコードの問題点は、「失敗の理由(原因)」が捨てられていることと、「Nullの確認を忘れるリスク」が常に残ることです。
2. 救世主『Result型』の概念
ここで、関数型プログラミングの知見を借りよう。成功(Success)と失敗(Failure)を明示的に保持する「Result型」というコンテナを使うんだ。
Dartの強力な `sealed class` を使えば、型安全かつ網羅的に状態をハンドリングできる。
// Result型の定義(成功と失敗を型で分ける)
sealed class Result
const Result();
}
class Success
final T value;
const Success(this.value);
}
class Failure
final Exception error;
const Failure(this.error);
}
なぜこれが強力なのか?
この `sealed` クラスを使うと、Dartのコンパイラは `switch` 文で「全パターン(成功か失敗か)」を処理しているかを強制的にチェックしてくれる。これぞ、Dart VMが誇る型システムの真骨頂です。
3. 実践:Nullチェックから解放されるコード
では、先ほどの `fetchUser` を `Result` 型を使って書き換えてみよう。
Result
try {
// 成功時はSuccessに包む
return Success(User(id: id));
} catch (e) {
// 失敗時は理由と共にFailureに包む
return Failure(Exception(‘ユーザーが見つかりません: $e’));
}
}
void main() {
final result = fetchUser(‘123’);
// switch式(Dart 3.0以降の強力な武器)
final message = switch (result) {
Success(value: final user) => ‘ようこそ、${user.name}さん!’,
Failure(error: final e) => ‘失敗しました: ${e.toString()}’,
};
print(message);
}
ここで何が起きているのか?
1. 網羅性チェック: もし `Failure` の処理を書き忘れたら、Dartはコンパイルエラーを出して教えてくれる。
2. 情報の保持: `Failure` には例外情報が含まれているため、デバッグが極めて容易になる。
3. Nullの消滅: このコードの中に `null` は一文字も登場しない。すべてが型によって管理されているんだ。
4. 初学者が陥りやすい罠
多くの人がやりがちなミスとして、「Result型の中にさらにNullを許可してしまう」ことがあります。
// 悪い例:中身がNullかも知れないResult
Result
`Result
結びに:Dartを掌握するということ
Null安全は単なる「エラーを防ぐための足かせ」ではなく、「コンパイラに設計の意図を正しく伝えるための対話」です。
Result型のような設計パターンを取り入れることで、君の書くコードは「Nullチェックというノイズ」から解放され、ビジネスロジックそのものを語り始めるはずです。
もし現場で「Nullが怖い」と感じたら、まずは `sealed class` で状態を切り出すことから始めてみて。Dart VMが君の設計を完璧に守ってくれることを実感できるはずだよ。
さあ、次はどんな深いコードの海へ潜りに行こうか? またいつでも相談してくれ。