【入門編】Dart 3の「論理演算パターン(& / |)」を駆使した複雑なバリデーションロジックの簡略化 – Dart コア文法・オブジェクト指向・Null安全解析バイブル

こんにちは!FlutterやDartのコードを日々書き進める中で、「あ、また条件分岐の `if` が深くなっちゃったな……」と頭を抱えた経験はありませんか?

他のプログラミング言語からDartにやってきた開発者からよく聞くのが、「Dart 3のパターンマッチングってすごそうだけど、実際の現場でどう使えばいいの?」という疑問です。

実は、Dart 3で導入された論理演算パターン(`&` と `|`)を使いこなせるようになると、これまで複雑にネストしていたバリデーション(入力値検証)ロジックが、驚くほど美しくフラットになります。

ここをクリアすれば、あなたのDartコードの表現力は一段とプロフェッショナルなものになりますよ。一緒にしっかりとマスターしていきましょう!

—

1. 従来の「深い if 文」が抱えるストレス

まずは、よくあるフォームの入力値やユーザー権限のバリデーションを考えてみましょう。
例えば、「管理者(Admin)である、またはプレミアム会員であり、かつ年齢が20歳以上である」という条件を、従来の `if` 文で書くとどうなるでしょうか。

// 従来のネストしたバリデーション
void checkAccessOld(String role, bool isPremium, int age) {
if (role == ‘Admin’) {
print(‘アクセス許可:管理者権限’);
} else {
if (isPremium) {
if (age >= 20) {
print(‘アクセス許可:プレミアム成人会員’);
} else {
print(‘アクセス拒否:20歳未満のプレミアム会員は不可’);
}
} else {
print(‘アクセス拒否:権限がありません’);
}
}
}

うーん、これだと条件が増えるたびに右側にどんどんコードが逃げていき(いわゆる「右肩上がりのコード」)、どこで何をチェックしているのかパッと見で追いづらくなってしまいますよね。

—

2. Dart 3の論理演算パターン(`&` と `|`)とは?

Dart 3の `switch` 式や `if-case` では、パターン同士を論理演算子で結ぶことができます。ここで使われるのは、おなじみの `&&` や `||` ではなく、単一の `&`(AND)と `|`(OR)です。

  • `|`(パターンOR): 「パターンのどれか一方が一致すればOK」
  • `&`(パターンAND): 「パターンの両方に一致していればOK」

これらを組み合わせることで、「変数そのものの値」を評価するのではなく、「構造や条件の組み合わせ」を一撃でマッチングさせることができるようになります。

脳内イメージ図

従来の `if` 文が「ドアを一つずつ開けて奥へ進む迷路」だとすれば、Dart 3の論理演算パターンは「条件が書かれた巨大な型抜きクッキーを、データにガチャンと一回押し当てる」ような感覚です。

[データ (role, isPremium, age)]
↓
┌──────────────────────────────┐
│ 論理演算パターンによる一括判定 │
└──────────────────────────────┘
│
┌──────┴──────┐
▼ ▼
【マッチ成功】 【マッチ失敗】

—

3. 実践!複雑なバリデーションをフラットにする

先ほどの複雑なアクセス権限の判定を、Dart 3の `switch` 式と論理演算パターンを使って書き直してみましょう。

void checkAccessSmart(String role, bool isPremium, int age) {
// レコード(複数の値のグループ)にしてパターンマッチにかける
switch ((role, isPremium, age)) {
// パターン1: 管理者であれば、年齢やプレミアム状態に関わらず許可
case (‘Admin’, _, _):
print(‘アクセス許可:管理者権限’);

// パターン2: プレミアム会員であり、かつ年齢が20歳以上 (ANDパターン & を使用)
case (_, true, >= 20):
print(‘アクセス許可:プレミアム成人会員’);

// それ以外の場合(デフォルト)
default:
print(‘アクセス拒否:条件を満たしていません’);
}
}

どうでしょう?あんなに深かったネストが綺麗に消え、上から下に流れるような読みやすいコードになりましたよね。

ここでさらに、「OR(`|`)」を使ったより実践的なバリデーションの例を見てみましょう。例えば、「ユーザーのステータスが `active` または `pending` で、かつ、権限が `editor` または `admin` の場合」という複合条件です。

String validateUserStatus({
required String status,
required String role,
}) {
return switch ((status, role)) {
// statusが ‘active’ または ‘pending’ かつ roleが ‘editor’ または ‘admin’
case (==’active’ | ==’pending’, ==’editor’ | ==’admin’) =>
‘VALID: 操作を許可します’,

// それ以外
_ =>
‘INVALID: アクセス権限がありません’,
};
}

void main() {
print(validateUserStatus(status: ‘active’, role: ‘admin’));
// 出力: VALID: 操作を許可します

print(validateUserStatus(status: ‘banned’, role: ‘editor’));
// 出力: INVALID: アクセス権限がありません
}

このように、`==’active’ | ==’pending’` のように関係演算子(`==` や `>=`)を伴うリレーショナルパターンと `|` を組み合わせることで、数学の論理式のようにスマートに条件を記述できます。

—

4. 陥りやすい文法エラーと注意点

非常に強力な論理演算パターンですが、Dartを学び始めた開発者が必ずといっていいほどハマる「罠」がいくつかあります。コンパイルエラーを防ぐために、以下のポイントを頭に置いておきましょう。

罠1: 論理演算子を間違える(`&&` や `||` を使ってしまう)

  • 誤り: `case (== ‘active’ && == ‘pending’):`
  • 正解: `case (== ‘active’ & == ‘pending’):`(※実際のコードではリレーショナルパターンでANDを使うケースは稀ですが、基本は単一の記号を使います)

パターンマッチングの世界では、通常のブール演算子(`&&`, `||`)ではなく、単一の `&` と `|` がパターン結合子として定義されています。ここを間違えると、「Operator ‘&&’ isn’t defined for the class…」といったコンパイルエラーになります。

罠2: ワイルドカード(`_`)や変数バインディングのスコープ

論理演算子で結ばれたパターンの両側で、同じ変数名をバインド(取得)することはできません。

// エラーになる例:両方で同じ名前の変数を使おうとするとコンパイルエラー
// case (var name, _) | (var name, _):

複雑な条件分岐で変数を再利用したい場合は、無理に一つのケースにまとめず、個別のケースに分けるか、ガード節(`when` 句)の利用を検討しましょう。

—

5. まとめ

今回は、Dart 3の論理演算パターン(`&` / `|`)を活用した、複雑なバリデーションロジックの簡略化について解説しました。

  • ネストが深くなった `if-else` の山は、レコードと `switch` 式(または `if-case`)でフラットにできる。
  • `|`(OR)や `&`(AND)をパターン間に使うことで、複雑な組み合わせ条件を一刀両断できる。
  • 通常の条件分岐(`&&`, `||`)と、パターンマッチングの論理演算(`&`, `|`)の記号の違いに気をつける。

ここをクリアすれば、あなたの書くDartコードの保守性と美しさは劇的に向上します。ぜひ、明日の開発現場のコードレビューやリファクタリングで使ってみてくださいね。

それでは、快適なDartライフを!

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