【入門編】DartのNull安全と『Record型』の相性:多値返却におけるNull許容の最適解 – Dart コア文法・オブジェクト指向・Null安全解析バイブル

Dartの多値返却とNull安全:Record型で「安全な戻り値」を設計する極意

Dartの世界へようこそ。言語の深淵に触れる準備はいいですか?

今日は、Dart 3で導入された強力な機能である「Record型」と、Dartの心臓部である「Sound Null Safety(健全なNull安全)」がどう交差するのか、そのベストプラクティスを紐解いていきましょう。

多くの開発者が、関数から「成功した時の値」と「エラー情報」を同時に返したいとき、どう型を定義すべきか迷います。ここでNull安全の考え方を誤ると、ランタイムエラーの温床になります。しかし、Record型を正しく使えば、その悩みは魔法のように消え去ります。

—

1. なぜ「Record型」なのか?

かつて、複数の値を返すには`List`を使うか、専用の`class`を定義していました。しかし、`List`は型安全ではありませんし、わざわざクラスを作るのはコードの肥大化を招きます。

Record型は、「コンパイル時に構造が確定する、一時的なデータ構造」です。

// ユーザー名と年齢を返すシンプルな例
(String, int) getUserInfo() {
return (‘Alice’, 30);
}

この`(String, int)`という記述。これは単なるデータ構造ではなく、DartのVMが「この関数は必ずこの型のペアを返す」と厳密に解釈する「型としての実体」です。

—

2. Null安全と「どこをNullにするか」の最適解

さて、ここからが本題です。検索エンジンで見かけるコードは、しばしば「全てをNull許容にする」という安易な実装をしがちです。しかし、それではDartが提供する「Null安全の恩恵」をドブに捨てることになります。

NG:すべてNull許容にしてしまう例

// 失敗した時に何を返せばいいかわからず、とりあえず全部Nullに…
(String?, int?) fetchData() {
return (null, null); // これでは呼び出し側が毎回 null チェック地獄に陥ります
}

ベストプラクティス:型で「状態」を表現する

「成功したのか、失敗したのか」という状態自体をRecordの構造に組み込むのが、Dart流のスマートな解法です。

// 成功した場合は値を返し、失敗した場合はエラーメッセージを返す
// どちらか一方が必ず存在するように定義する
({String? data, String? error}) fetchData() {
bool success = false; // 仮のロジック

if (success) {
return (data: ‘Success!’, error: null);
} else {
return (data: null, error: ‘Connection Failed’);
}
}

void main() {
final result = fetchData();

// 分解(Destructuring)を使ってスマートに処理
final (data: data, error: error) = result;

if (error != null) {
print(‘エラー発生: $error’);
} else {
print(‘データ取得成功: $data’);
}
}

なぜこの書き方が「最強」なのか?

1. 名前付きフィールドを使用: `(String?, int?)`のような位置ベースのRecordではなく、`(data: …, error: …)`と名前を付けることで、呼び出し側で「何がエラーなのか」が明確になります。
2. Nullチェックの強制: `data`がNullかもしれないとコンパイラが認識しているため、不用意なアクセスを未然に防げます。
3. 可読性の向上: 呼び出し側で `result.$1` などと書く必要がなく、直感的に値にアクセスできます。

—

3. 陥りやすい罠:Null許容の伝播

初心者がよくやる間違いは、「とりあえず全部 `?` をつければエラーは消える」と勘違いすることです。

例えば、`({String? name, int? age})` を受け取ったとき、`name` が Null なのか、そもそもデータが存在しないのかの区別がつかなくなります。

解決策:
もし「データがない状態」を明確に表現したいなら、Recordを返すのではなく、Dartの強力な`sealed class`と組み合わせた「Resultパターン」を検討してください。Recordはあくまで「複数の値をまとめて返すための手段」であり、複雑な状態遷移を記述するためのものではない、と理解することが重要です。

—

4. 最後に:Dartを掌握するということ

DartのNull安全は、単なる「エラーを防ぐ機能」ではありません。「コードの意図をコンパイラに正しく伝えるための言語仕様」です。

Record型で多値を返す際、`?` をどこに置くべきか迷ったら、こう自問自答してみてください。
「この値がNullであるとき、呼び出し側は安全に処理を分岐できるか?」

その問いへの答えが、あなたのコードの品質を決めます。

ここをクリアすれば、あなたはもうDartの基本をマスターしたと言っても過言ではありません。次はぜひ、`pattern matching`と組み合わせて、より宣言的で美しいコードを書いてみてください。

Dartの旅はまだ始まったばかりです。一緒に最高峰のコードを書き続けましょう!

タイトルとURLをコピーしました