Dart 基本構文 — プログラム構造・コメント・コード
構文はコードの骨格である — 標準化された構文の習慣が、コードの可読性と保守性を決める。
1. 学べること
main()エントリ関数とプログラムの実行モデル- セミコロン、波括弧、インデントの規約(dart format ルール)
- 3 種類のコメント:行コメント / ブロックコメント / ドキュメントコメント(
///) - キーワードと予約語の概要
- 文(文)と式(式)の違い
2. 開発者のリアルな物語
(1) 課題:コメント不足で保守不能なコードに
Charlie は前任者から受け継いだデータ処理スクリプトにコメントが一切なかった。マジックナンバーと略語だらけの 500 行のコードの中で、p が product を、t が taxRate を表していることを理解するのに 3 日かかった。さらに悪いことに、重要な税計算ロジックにはドキュメントコメントがなく、新しい同僚がそれをバグだと勘違いして修正してしまった。結果として 2,000 件の注文で税計算が誤りになり、5 万ドルの直接的な損失が出た。
(2) 標準化された構文による解決
Dart は 3 種類のコメントを提供する。dart format による自動フォーマットと dart analyze による静的チェックを組み合わせれば、構造が明確でよくコメントされたコードを書ける。
/// Calculates the tax amount for an order.
///
/// Uses the regional tax rate and applies exemptions
/// for orders below the minimum threshold.
double calculateTax(double amount, double taxRate, {double exemptThreshold = 0}) {
// Apply exemption threshold
if (amount <= exemptThreshold) return 0;
/* Complex tax calculation logic
that may span multiple lines */
final taxableAmount = amount - exemptThreshold;
return taxableAmount * taxRate;
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(3) 効果
- ドキュメントコメントは
dart docで API ドキュメントとして自動生成できる dart formatがチームのコードスタイルを統一し、フォーマット論争を撲滅する- 標準化された命名とコメントにより、コードの保守性が 3 倍向上
3. プログラム構造と main エントリポイント
(1) プログラム実行モデル
すべての Dart プログラムは main() 関数から実行を開始する。Dart はシングルスレッドのイベントループモデルを採用しているが、Isolate によって並列処理を実現できる。
graph TD
A[OS が Dart VM をロード] --> B[main 関数を検出]
B --> C[main 本体を実行]
C --> D{非同期操作があるか?}
D -->|いいえ| E[プログラム終了]
D -->|はい| F[イベントループが動作]
F --> G[マイクロタスクを処理]
G --> H[イベントを処理]
H --> I{まだイベントがある?}
I -->|はい| G
I -->|いいえ| E
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
▶ サンプル:main 関数の基本形
// 最もシンプルな main 関数
void main() {
print('DataPipeline starting...');
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
▶ サンプル:引数付き main 関数
// コマンドライン引数付きの main
void main(List<String> arguments) {
// arguments[0] は最初の引数(プログラム名ではない)
print('Arguments received: $arguments');
print('Argument count: ${arguments.length}');
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| main の形式 | シグネチャ | 用途 |
|---|---|---|
| 引数なし | void main() |
シンプルなスクリプト |
| 引数あり | void main(List<String> args) |
CLI ツール |
| 戻り値あり | Future<void> main() |
非同期エントリポイント |
4. セミコロン、波括弧、インデント
(1) 基本的な構文ルール
Dart は文の終わりにセミコロン ; を、コードブロックの囲みに波括弧 {} を使用する。インデントは 2 スペース(dart format で強制される)。
▶ サンプル:セミコロンと波括弧
void main() {
// 各文の終わりにセミコロン
int orderCount = 1000;
double totalAmount = 50000.0;
// ブロック本体には波括弧が必須
if (orderCount > 0) {
print('Processing $orderCount orders');
} else {
print('No orders to process');
}
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| ルール | 説明 | dart format の挙動 |
|---|---|---|
| 末尾のセミコロン | すべての文の終わりに ; |
自動では付与しない |
| 波括弧 | if/for/while は {} 必須 |
自動フォーマット |
| インデント | 2 スペースインデント | 自動修正 |
| 行幅 | 80 文字以内を推奨 | 強制ではない |
5. 3 種類のコメント
(1) 行コメント //
単一行の説明に使われ、もっとも一般的である。
▶ サンプル:行コメント
void main() {
// データパイプラインを初期化
final maxRecords = 1000000; // 処理する最大レコード数
// TODO: 設定ファイルのサポートを追加
print('Max capacity: $maxRecords records');
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(2) ブロックコメント /* */
複数行の説明やコードの一時的な無効化に使う。
▶ サンプル:ブロックコメント
void main() {
/* このセクションは DataPipeline 設定の
初期セットアップを扱う。
環境変数から読み込む。 */
final config = 'production';
/*
// デバッグ用に一時的に無効化
if (config == 'production') {
enableLogging();
}
*/
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
(3) ドキュメントコメント ///
API ドキュメントの生成に使われ、Markdown 形式に対応する。
▶ サンプル:ドキュメントコメント
/// Represents an e-commerce order with tax calculation.
///
/// This class models a single order from the DataPipeline
/// system, including amount, tax rate, and status.
///
/// Example:
/// ```dart
/// final order = Order(id: 'ORD-001', amount: 1500.0);
/// print(order.totalWithTax);
/// ```
class Order {
final String id;
final double amount;
Order({required this.id, required this.amount});
double get totalWithTax => amount * 1.08;
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| コメントの種類 | 構文 | 用途 | ドキュメント生成 |
|---|---|---|---|
| 行コメント | // |
コード説明、TODO | なし |
| ブロックコメント | /* */ |
複数行説明、コード無効化 | なし |
| ドキュメントコメント | /// |
API ドキュメント | あり(dart doc) |
6. キーワードと予約語
(1) Dart キーワードの分類
| カテゴリ | キーワード | 説明 |
|---|---|---|
| 宣言 | class enum mixin extension typedef |
型宣言 |
| 修飾子 | abstract sealed final const late static |
修飾子 |
| 制御 | if else for while do switch return |
フロー制御 |
| 例外 | try catch finally throw rethrow |
例外処理 |
| 非同期 | async await sync yield |
非同期プログラミング |
| 型 | int double String bool dynamic void |
組み込み型 |
| Null 安全性 | null late required |
Null 安全性 |
▶ サンプル:予約語の識別子使用を避ける
// 正しい - 意味のある名前を使う
int orderCount = 100;
String customerName = 'Alice';
double taxRate = 0.08;
// 間違い - 予約語の識別子使用を避ける
// int class = 5; // 構文エラー!
// String function = 'test'; // 構文エラー!
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
7. 文と式
(1) コアな違い
式は戻り値を持つが、文は持たない。これは Dart の構文を理解するうえで基礎となる。
graph TD A[コード単位] --> B[式<br/>値を持つ] A --> C[文<br/>値を持たない] B --> B1[リテラル: 42] B --> B2[変数: count] B --> B3[演算: a + b] B --> B4[関数呼び出し: max(1, 2)] C --> C1[if-else] C --> C2[for ループ] C --> C3[return 文] C --> C4[変数宣言]
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
▶ サンプル:式と文
void main() {
// 式 - 値を生成する
int count = 100; // 100 は式
double price = 29.99; // 29.99 は式
double total = price * count; // price * count は式
bool isExpensive = total > 1000; // total > 1000 は式
// 文 - 値を生成しない
if (isExpensive) { // if 文
print('High value order'); // print 呼び出し文
}
// Dart 3: switch 式(式である!)
String label = switch (count) {
0 => 'empty',
<= 10 => 'small',
<= 100 => 'medium',
_ => 'large',
};
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
| 観点 | 式 | 文 |
|---|---|---|
| 戻り値 | あり | なし |
| 入れ子 | 他の式の中にネスト可能 | 独立して実行される |
| 例 | a + b、x > 0 |
if、for、return |
| Dart 3 新機能 | switch 式 | — |
8. 完全なサンプル:DataPipeline コードスタイルテンプレート
// ============================================
// DataPipeline - コードスタイルテンプレート
// 正しい構文、コメント、構造を示す
// ============================================
/// Configuration for the DataPipeline processing engine.
///
/// Holds settings like maximum batch size, output format,
/// and whether to enable verbose logging.
class PipelineConfig {
/// Maximum number of records per processing batch.
final int batchSize;
/// Output format for generated reports.
final String outputFormat;
/// Enable detailed processing logs.
final bool verbose;
/// Creates a new pipeline configuration.
///
/// Default batch size is 10,000 records.
/// Default output format is 'json'.
PipelineConfig({
this.batchSize = 10000,
this.outputFormat = 'json',
this.verbose = false,
});
/// Returns a human-readable summary of the config.
String get summary =>
'Batch: $batchSize records, Format: $outputFormat, Verbose: $verbose';
}
/// Entry point for DataPipeline CLI tool.
void main(List<String> arguments) {
// Step 1: Load configuration
final config = PipelineConfig(
batchSize: 50000,
outputFormat: 'csv',
verbose: true,
);
// Step 2: Display configuration
print('=== DataPipeline Configuration ===');
print(config.summary);
// Step 3: Process based on arguments
/* TODO: Implement actual data processing
- Read input source
- Transform records
- Write output report
*/
final recordCount = arguments.isNotEmpty ? int.tryParse(arguments[0]) ?? 0 : 0;
if (recordCount > 0) {
print('Processing $recordCount records...');
} else {
print('No records specified. Use: dart run bin/main.dart <record_count>');
}
}
> 出力: ローカルの DartPad または `dart run` で実行してください。この Dart コースの全例は Dart 3.x / Flutter 3.x ベースです。SDK バージョンにより結果が多少異なる場合があります。
出力(
dart run bin/main.dart 100000):
=== DataPipeline Configuration ===
Batch: 50000 records, Format: csv, Verbose: true
Processing 100000 records...
❓ よくある質問
Q: Dart ではセミコロンは必須ですか? A: はい、Dart ではすべての文の終わりにセミコロンが必要です。Python/Go のように省略はできません。これは Dart 初心者がもっともよく犯すミスです。
Q: 行コメントとドキュメントコメントはいつ使い分けますか? A: 公開 API(クラス、公開メソッド、公開プロパティ)には
///ドキュメントコメントを使います。内部実装の詳細には//行コメントを使います。dart docはドキュメントコメントのみを処理します。
Q:
dart formatはコードロジックを変更しますか? A: いいえ。dart formatは空白と改行を調整するだけで、コードの意味は変更しません。CI で--set-exit-if-changedを安心して使えます。
Q: Dart の
if文は波括弧を省略できますか? A: 文法上、続く文が 1 つだけなら波括弧を省略できます。ただしdart formatは自動的に波括弧を追加します。常に波括弧を使うことを強く推奨します。
Q: switch 式と switch 文の違いは何ですか? A: switch 式(Dart 3)は戻り値を持ち、
=>で分岐します。switch 文は戻り値が無く、case:で分岐します。前者の方が簡潔、後者の方が柔軟です。
Q: ドキュメントコメントには
///と/ */のどちらを使いますか? A: Dart は公式に///を推奨しています。/ */も有効ですが、///が Dart コミュニティの主流スタイルであり、dart formatも///を使うようにフォーマットします。
Q:
main関数はintを返せますか? A: Dart のmainの戻り型はvoidまたはFuture<void>です。プロセスの終了コードはdart:ioのexit()関数で設定できます。
📖 まとめ
- Dart プログラムは
main()から実行を開始し、同期と非同期の両方のエントリポイントに対応する。 - セミコロン、波括弧、2 スペースインデントが Dart の基本構文ルールで、
dart formatで自動強制される。 - 3 種類のコメントはそれぞれ役割を持つ:
//行コメント、/* */ブロックコメント、///ドキュメントコメント(API ドキュメント生成用)。 - キーワードは 7 つの大きなカテゴリに分類される:宣言、修飾子、制御フロー、例外、非同期、型、Null 安全性。
- 式は戻り値を持ち、文は持たない — Dart 3 の switch 式がこのギャップを埋める。
📝 練習問題
- 基礎(難易度 ⭐):3 種類のコメントをすべて使った
main関数を書きましょう。dart doc .を実行して生成されたドキュメントの効果を確認してください。 - 中級(難易度 ⭐⭐):意図的に整形が悪い Dart コード(インデントの混在、波括弧の欠落)を数か所書いた後、
dart formatで自動修正してください。修正前後の違いを比較しましょう。 - 挑戦(難易度 ⭐⭐⭐):3 つのメソッドを含むクラスの完全なドキュメントコメント(説明、パラメータ説明、サンプルコードを含む)を書き、
dart docで HTML ドキュメントを生成して結果を確認してください。