Dart: Dart 言語入門 — 起源からエコシステムまで
Dart — マルチプラットフォームのために生まれた言語。Flutter から CLI、Web からサーバーまで、単一のコードベースであらゆる場所で動作する。
1. 学べること
- Dart の誕生背景と Google の戦略的位置づけ
- Dart と JavaScript / TypeScript / Kotlin のコアな違い
- Dart 3 の三大柱:null 安全性 / パターンマッチング / シールクラス
- Dart エコシステムの全体像:pub.dev / Flutter / サーバーサイド / CLI
- Bob の DataPipeline プロジェクトの俯瞰と学習ロードマップ
2. 開発者のリアルな物語
(1) 課題:マルチプラットフォーム開発の断片化という悪夢
Bob は EC サイト向けデータ分析 SaaS プロダクトを担当するフルスタック開発者である。彼は Web フロントエンド(JavaScript)、モバイルアプリ(Kotlin + Swift)、バックエンドサービス(Go)、CLI ツール(Python)を同時に保守しなければならない。4 つの言語、4 つのツールチェーン、4 つのコードベース — たった 1 つのバグ修正でも 4 か所変更が必要となる。プロダクトマネージャーが「リアルタイムダッシュボード」を求めたとき、Bob は Flutter とネイティブ開発のどちらを選ぶか何度も迷い、チーム内のコミュニケーションコストは週 20 時間にまで膨らんだ。
(2) Dart による解決
Dart は統一された技術スタックを提供する。1 つの言語でフロントエンド(Flutter Web)、モバイル(Flutter Mobile)、バックエンド(shelf)、CLI(dart:io)をカバーできる。Bob はプロジェクト全体を Dart で書き直し、コアのビジネスロジックを 1 度だけ書けば済むようにした。
// 共有されるビジネスロジック - CLI、Web、モバイル、サーバーで動作
class DataPipeline {
final String name;
final int maxRecords;
const DataPipeline({
required this.name,
this.maxRecords = 1000000,
});
String get summary => '$name: capacity ${maxRecords} records';
}
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(3) 効果
- コードの再利用率が 30% から 85% に向上
- チームが 1 つの言語だけを習得すればよくなり、コミュニケーションコストが 60% 削減
- Dart 3 の null 安全性により、実行時の NullPointerException が 95% 削減
3. Dart の誕生と進化
(1) 誕生の背景
Dart は 2011 年に Google の Lars Bak と Kasper Lund によって公開された。当初は Web の主要言語として JavaScript を置き換える目的だったが、2015 年に Flutter が生まれたことで Dart の運命は変わる。「Web 向け言語」から「マルチプラットフォーム言語」へと進化したのである。
graph LR A[Dart 1.0<br/>2011] --> B[Dart 2.0<br/>2018<br/>強い型付け] B --> C[Dart 2.12<br/>2021<br/>Null 安全性] C --> D[Dart 3.0<br/>2023<br/>Records/Pattern/Sealed] D --> E[Dart 3.x<br/>2024+<br/>Wasm GC]
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| バージョン | 年 | 主要機能 | 意義 |
|---|---|---|---|
| Dart 1.0 | 2011 | 任意の型付け | Web 代替 |
| Dart 2.0 | 2018 | 強い型付け + 静的型付け | 型安全性の基盤 |
| Dart 2.12 | 2021 | null 安全性 | NullPointerException を撲滅 |
| Dart 3.0 | 2023 | Records / パターンマッチング / シールクラス | モダン言語機能 |
| Dart 3.x | 2024+ | Wasm GC 対応 | Web パフォーマンスの飛躍 |
(2) Google の戦略的位置づけ
Dart は Flutter の唯一の公式言語であり、Google 内部の Fuchsia OS のアプリケーション層言語でもある。Google の Dart への投資は実験的プロジェクトではなく長期的な戦略である。
| 戦略領域 | 位置づけ |
|---|---|
| モバイル | Flutter のコア言語 |
| Web | JS / Wasm にコンパイルして動作 |
| デスクトップ | Flutter Desktop |
| サーバーサイド | shelf / dart:io |
| 組み込み | Fuchsia OS のアプリケーション層 |
4. Dart と他言語の比較
(1) コアな違いの比較
graph LR A[Dart] --> B[null 安全性] A --> C[パターンマッチング] A --> D[シールクラス] A --> E[AOT + JIT] A --> F[Isolate 並行処理] G[JavaScript] --> H[動的型付け] G --> I[シングルスレッド] J[TypeScript] --> K[型消去] J --> L[実行時型情報なし] M[Kotlin] --> N[JVM 依存] M --> O[コルーチン]
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| 観点 | Dart | JavaScript | TypeScript | Kotlin |
|---|---|---|---|---|
| 型システム | 堅牢な静的型付け | 動的型付け | 静的型付け(型消去あり) | 静的型付け |
| null 安全性 | 堅牢(コンパイル時) | なし | 必須ではない | 必須ではない |
| AOT コンパイル | 対応 | 非対応 | 非対応 | 対応(Native) |
| 並行処理モデル | Isolate(共有メモリなし) | シングルスレッド | シングルスレッド | コルーチン |
| パターンマッチング | Dart 3 がネイティブ対応 | なし | なし | 限定的に対応 |
| シールクラス | Dart 3 がネイティブ対応 | なし | なし | 対応 |
| Flutter サポート | 唯一の公式言語 | なし | なし | 間接的(KMP) |
| 学習コスト | 中程度 | 低 | 中程度 | 中程度 |
(2) Dart ならではの優位性
- 堅牢な null 安全性:コンパイラが非 nullable 型が決して null にならないことを保証する。TypeScript のようにコンパイル時チェックだけではない。
- Isolate:共有メモリなしの真の並列実行により、競合状態を回避する。
- AOT + JIT デュアルモード:開発中は JIT のホットリロード、リリース時は AOT の高性能を活用できる。
- Dart 3 の三矢:Records / パターンマッチング / シールクラスが一斉に導入された。
5. Dart 3 の三大柱
(1) null 安全性
Dart の null 安全性では型を nullable な T? と non-nullable な T に分ける。コンパイラはコンパイル時に non-nullable 型が決して null にならないことを保証する。
// non-nullable - コンパイラが non-null を保証
String name = 'Bob';
// nullable - 使用前に必ず null チェックが必要
String? nickname = null;
// 安全なアクセス
int length = nickname?.length ?? 0;
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(2) パターンマッチング
Dart 3 は完全なパターンマッチングシステムを導入し、分割代入、if-case、switch 式、網羅性チェックに対応する。
// パターンマッチングを使った switch 式
String describe(Object value) => switch (value) {
int i => 'Integer: $i',
double d => 'Double: $d',
String s => 'String: $s',
_ => 'Unknown type',
};
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(3) シールクラス
シールクラスはサブクラスを同一ライブラリ内に制限し、コンパイラに switch の網羅性を保証させる。
sealed class DataSource {}
class ApiSource extends DataSource { final String endpoint; ApiSource(this.endpoint); }
class FileSource extends DataSource { final String path; FileSource(this.path); }
class DatabaseSource extends DataSource { final String connectionString; DatabaseSource(this.connectionString); }
// 網羅的な switch - コンパイラが全ケースをチェック
String describe(DataSource source) => switch (source) {
ApiSource(:final endpoint) => 'API: $endpoint',
FileSource(:final path) => 'File: $path',
DatabaseSource(:final connectionString) => 'DB: $connectionString',
};
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| 機能 | 解決する問題 | 適用シナリオ |
|---|---|---|
| null 安全性 | 実行時の NullPointerException | 任意のコンフィグ項目、null 許容の API 戻り値 |
| パターンマッチング | if-else チェーンの冗長さ | 型チェック、データの分解 |
| シールクラス | 分岐処理の漏れ | データソースの種類、状態遷移マシン |
6. Dart エコシステムの全体像
(1) エコシステムのコア構成要素
graph LR A[Dart Ecosystem] --> B[Flutter<br/>Mobile/Desktop/Web] A --> C[pub.dev<br/>Package Registry] A --> D[Server-side<br/>shelf/dart:io] A --> E[CLI Tools<br/>args/dart:io] A --> F[Web<br/>dart2js/dart2wasm] A --> G[Testing<br/>test package] A --> H[Code Generation<br/>build_runner]
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| エコシステム構成要素 | 目的 | 代表パッケージ |
|---|---|---|
| Flutter | UI フレームワーク | flutter, cupertino |
| pub.dev | パッケージマネージャー | 40,000+ パッケージ |
| サーバーサイド | HTTP サービス | shelf, dart_frog |
| CLI | コマンドラインツール | args, cli_util |
| Web | フロントエンドコンパイル | dart2js, dart2wasm |
| テスト | テストフレームワーク | test, mockito |
| コード生成 | コードジェネレーション | build_runner, json_serializable |
▶ サンプル:pub.dev でパッケージを検索する
Bob はデータ処理関連のパッケージを pub.dev で検索する:
// pubspec.yaml の DataPipeline 用依存関係
// dependencies:
// args: ^2.4.2 # CLI 引数解析
// http: ^1.2.0 # HTTP クライアント
// csv: ^6.0.0 # CSV 解析
// sqlite3: ^2.4.0 # SQLite データベース
// path: ^1.9.0 # パス操作
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
7. Bob の DataPipeline プロジェクトの俯瞰
(1) プロジェクトの定義
DataPipeline は Bob が開発する EC 向けデータ分析 CLI ツールである。100 万件の注文レコードを処理し、SaaS ダッシュボードで利用できるレポートを出力する。
▶ サンプル:プロジェクトビジョン
// DataPipeline プロジェクト概要
// 入力: 120 万件の EC 注文(CSV / API / DB)
// 処理: フィルタリング、集約、変換を並列実行
// 出力: ダッシュボード向けレポート(JSON / CSV / HTML)
void main() {
print('DataPipeline v1.0.0');
print('Processing capacity: 1,000,000+ orders');
print('Output formats: JSON, CSV, HTML');
}
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(2) 学習ロードマップ
graph TD
subgraph Phase1[Phase 1: 基礎]
L1[Lesson 1: 入門]
L2[Lesson 2: インストール]
L3[Lesson 3: 基本構文]
L4[Lesson 4: 変数と型]
L5[Lesson 5: 演算子]
L6[Lesson 6: 制御フロー]
end
subgraph Phase2[Phase 2: 中核機能]
L7[Lesson 7: 関数]
L8[Lesson 8: クラスとオブジェクト]
L9[Lesson 9: コレクション]
L10[Lesson 10: 例外処理]
L11[Lesson 11: ジェネリック]
L12[Lesson 12: 列挙型と拡張]
end
subgraph Phase3[Phase 3: 発展]
L13[Lesson 13: null 安全性]
L14[Lesson 14: Future / async-await]
L15[Lesson 15: Stream]
L16[Lesson 16: Dart 3 の新機能]
L17[Lesson 17: Isolate]
L18[Lesson 18: メタプログラミング]
end
subgraph Phase4[Phase 4: 運用]
L19[Lesson 19: パッケージ管理]
L20[Lesson 20: テスト]
L21[Lesson 21: コード生成]
L22[Lesson 22: Dart と Flutter]
end
subgraph Phase5[Phase 5: プロジェクト]
L23[Lesson 23: プロジェクト設計]
L24[Lesson 24: 最適化とリリース]
end
Phase1 --> Phase2 --> Phase3 --> Phase4 --> Phase5
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| フェーズ | レッスン | 目標 | 主な成果 |
|---|---|---|---|
| Phase 1 | L1-L6 | 基礎 | Hello World → 制御フロー |
| Phase 2 | L7-L12 | 中核機能 | 関数/クラス/コレクション/例外/ジェネリック/列挙型 |
| Phase 3 | L13-L18 | 発展機能 | null 安全性/非同期/Stream/Dart 3/Isolate |
| Phase 4 | L19-L22 | 管理と運用 | パッケージ管理/テスト/コード生成/Flutter |
| Phase 5 | L23-L24 | 総合演習 | DataPipeline プロジェクト完成 |
▶ サンプル:DataPipeline プレビューコード
// DataPipeline プレビュー - これから作るもの
void main() {
// ステップ 1: データソースを定義
final source = ApiSource('https://api.example.com/orders');
// ステップ 2: パイプラインを作成
final pipeline = DataPipeline(
name: 'E-Commerce Analytics',
maxRecords: 1200000,
);
// ステップ 3: 処理して出力
print(pipeline.summary);
// 出力: E-Commerce Analytics: capacity 1200000 records
}
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
8. 完全なサンプル:DataPipeline プロジェクトスケルトン
// ============================================
// DataPipeline プロジェクトスケルトン
// EC データ分析向け CLI ツール
// ============================================
// データソース型(網羅的マッチングのためのシールクラス)
sealed class DataSource {}
class ApiSource extends DataSource {
final String endpoint;
ApiSource(this.endpoint);
}
class FileSource extends DataSource {
final String path;
FileSource(this.path);
}
// コアなパイプラインクラス
class DataPipeline {
final String name;
final int maxRecords;
DataSource? source; // nullable - まだ設定されていない可能性がある
DataPipeline({
required this.name,
this.maxRecords = 1000000,
});
String get summary => '$name: capacity ${maxRecords} records';
String describeSource() {
if (source == null) return 'No source configured';
return switch (source!) {
ApiSource(:final endpoint) => 'API source: $endpoint',
FileSource(:final path) => 'File source: $path',
};
}
}
// エントリーポイント
void main() {
final pipeline = DataPipeline(
name: 'E-Commerce Analytics',
maxRecords: 1200000,
);
pipeline.source = ApiSource('https://api.example.com/orders');
print('=== DataPipeline ===');
print(pipeline.summary);
print(pipeline.describeSource());
}
> **出力:** ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
出力:
=== DataPipeline ===
E-Commerce Analytics: capacity 1200000 records
API source: https://api.example.com/orders
❓ よくある質問
Q: Dart と Flutter の関係は? A: Dart は Flutter の唯一の公式プログラミング言語であり、Flutter は Dart で構築された UI フレームワークです。Dart を学ぶことは Flutter を学ぶための前提条件です。
Q: Dart はフロントエンド開発で JavaScript を置き換えられますか? A: Dart は dart2js で JavaScript に、または dart2wasm で WebAssembly にコンパイルできます。ただし、Web のエコシステムは依然として JavaScript が支配的です。Dart の強みは Flutter for Web にあります。
Q: Dart 3 の null 安全性は強制ですか? A: はい、Dart 3 ではデフォルトで堅牢な null 安全性が有効です。レガシーコードは移行が必要ですが、Dart 2.12 以降では段階的な移行がサポートされています。
Q: Dart はバックエンド開発に適していますか? A: はい。Dart には shelf や dart_frog といったバックエンドフレームワークがあり、Isolate による並行処理モデルで高並行シナリオに対応できます。ただし、エコシステムの成熟度は Go/Java には及びません。
Q: TypeScript の経験がある場合、Dart の学習は大変ですか? A: それほど難しくありません。Dart と TypeScript は型システムが似ていますが、Dart の堅牢な null 安全性と Isolate は新しい概念であり、重点的に学習する必要があります。
Q: Dart のパフォーマンスはどうですか? A: AOT コンパイル後は Go/Java に近い性能を発揮します。JIT モードではホットリロード開発がサポートされます。Wasm GC 対応により Web でのパフォーマンスが大きく向上します。
📖 まとめ
- Dart は Google が 2018 年に公開した。Dart 2.0 で強い型付けが確立し、Dart 3 で 2023 年に三大柱が導入された。
- Dart 3 の三大柱:null 安全性(NullPointerException を撲滅)、パターンマッチング(型の分解)、シールクラス(網羅的チェック)。
- Dart と JS/TS/Kotlin のコアな違い:堅牢な型システム、Isolate 並行処理、AOT+JIT デュアルモード。
- Dart エコシステムは Flutter、pub.dev、サーバーサイド、CLI、Web の 5 つの主要領域をカバーする。
- Bob の DataPipeline プロジェクトは 24 レッスンにわたり、Hello World から完成した CLI ツールまでを扱う。
- 学習ロードマップ:入門から実践応用までの 5 フェーズで段階的に進む。
📝 練習問題
- 基礎(難易度 ⭐):pub.dev にアクセスし、
httpパッケージを検索して pub points の評価を確認し、対応プラットフォームのリストを記録してください。 - 中級(難易度 ⭐⭐):Dart と自分が最も得意なプログラミング言語(JS/Python/Java など)を比較し、Dart の利点 3 つと欠点 3 つの表を作成してください。
- 挑戦(難易度 ⭐⭐⭐):DataPipeline プロジェクトのモジュール分割図をスケッチしてください。データ入力、処理、出力の 3 段階でどのようなコンポーネントが必要かを考えてみましょう。