Dartコードの書き方の順番

目次

Dartファイルの構造 – 家を建てる順番!

比喩で言うと: コードは家を建てるようなもの。土台→柱→壁→屋根の順番が決まっています! 🏠

順番(テンプレート)

// ========================================
// 1. import 文(外部から材料を持ってくる)
// ========================================
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:io';

// 自作ファイルのimportは最後
import 'models/student.dart';
import 'utils/helpers.dart';

// ========================================
// 2. クラス定義
// ========================================
class StudentPage extends StatefulWidget {
  // ========================================
  // 2-1. 定数(const)
  // ========================================
  static const String routeName = '/student';
  
  // ========================================
  // 2-2. final 変数(コンストラクタで初期化)
  // ========================================
  final String studentId;
  final String studentName;
  
  // ========================================
  // 2-3. コンストラクタ
  // ========================================
  const StudentPage({
    Key? key,
    required this.studentId,
    required this.studentName,
  }) : super(key: key);
  
  // ========================================
  // 2-4. createState (StatefulWidgetの場合)
  // ========================================
  @override
  State<StudentPage> createState() => _StudentPageState();
}

// ========================================
// 3. State クラス
// ========================================
class _StudentPageState extends State<StudentPage> {
  // ========================================
  // 3-1. 通常の変数(状態)
  // ========================================
  int _counter = 0;
  String _message = '';
  List<String> _items = [];
  
  // ========================================
  // 3-2. late 変数
  // ========================================
  late TextEditingController _controller;
  
  // ========================================
  // 3-3. ライフサイクルメソッド(決まった順番!)
  // ========================================
  
  // 初期化(一番最初に呼ばれる)
  @override
  void initState() {
    super.initState();
    _controller = TextEditingController();
    _loadData();
  }
  
  // 依存関係が変わったとき
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 必要なら処理
  }
  
  // Widget が更新されたとき
  @override
  void didUpdateWidget(StudentPage oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 必要なら処理
  }
  
  // 破棄される前(最後に呼ばれる)
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  // ========================================
  // 3-4. build メソッド(UI を作る)
  // ========================================
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.studentName),
      ),
      body: Center(
        child: Column(
          children: [
            Text('$_counter'),
            ElevatedButton(
              onPressed: _incrementCounter,
              child: Text('増やす'),
            ),
          ],
        ),
      ),
    );
  }
  
  // ========================================
  // 3-5. プライベートメソッド(内部で使う関数)
  // ========================================
  
  // データ読み込み
  Future<void> _loadData() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = prefs.getInt('counter') ?? 0;
    });
  }
  
  // カウンター増加
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  
  // データ保存
  Future<void> _saveData() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt('counter', _counter);
  }
  
  // 計算処理
  int _calculateTotal() {
    return _counter * 2;
  }
}

📚 各セクションの詳細説明

1、import 文の順番

// (1) Dart標準ライブラリ
import 'dart:io';
import 'dart:async';

// (2) Flutterライブラリ
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

// (3) 外部パッケージ
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

// (4) 自分のファイル(相対パス)
import 'models/student.dart';
import 'screens/home_page.dart';
import 'utils/constants.dart';

順番の理由:

  • 標準 → Flutter → パッケージ → 自作の順
  • 関連性の高いものをグループ化
  • 読みやすさのため

2、クラス内の変数の順番

class MyWidget extends StatefulWidget {
  // (1) 定数(static const)
  static const String title = 'マイアプリ';
  
  // (2) final 変数(外部から受け取る)
  final String studentId;
  final int age;
  
  // (3) コンストラクタ
  const MyWidget({
    required this.studentId,
    required this.age,
  });
  
  // (4) createState
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

順番の理由:

  • 変わらないもの(定数)が先
  • 外部から受け取るもの(final)が次
  • 初期化処理(コンストラクタ)
  • 最後に createState

3、State クラス内の順番

class _MyWidgetState extends State<MyWidget> {
  // (1) 変数(状態)
  int _counter = 0;
  String _name = '';
  
  // (2) late 変数
  late TextEditingController _controller;
  
  // (3) ライフサイクルメソッド
  @override
  void initState() { ... }
  
  @override
  void dispose() { ... }
  
  // (4) build メソッド
  @override
  Widget build(BuildContext context) { ... }
  
  // (5) プライベートメソッド
  void _myMethod() { ... }
  Future<void> _loadData() async { ... }
}

順番の理由:

  • データ(変数)を最初に定義
  • ライフサイクル(初期化・破棄)
  • UI構築(build)
  • ヘルパー関数(メソッド)

🔄 ライフサイクルメソッドの順番

これは決まった順番があります!

class _MyPageState extends State<MyPage> {
  // ========================================
  // 呼ばれる順番:
  // 1. initState (最初の1回だけ)
  // 2. didChangeDependencies (初回 + 依存変更時)
  // 3. build (何度も呼ばれる)
  // 4. didUpdateWidget (親から更新された時)
  // 5. dispose (最後、破棄される時)
  // ========================================
  
  @override
  void initState() {
    super.initState();
    print('1. initState');
    // 初期化処理(1回だけ)
  }
  
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('2. didChangeDependencies');
  }
  
  @override
  Widget build(BuildContext context) {
    print('3. build');
    return Scaffold(...);
  }
  
  @override
  void didUpdateWidget(MyPage oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('4. didUpdateWidget');
  }
  
  @override
  void dispose() {
    print('5. dispose');
    super.dispose();
  }
}

ポイント:

  • initState → super.initState() を最初に
  • dispose → super.dispose() を最後に

📐 build メソッド内の順番

@override
Widget build(BuildContext context) {
  return Scaffold(
    // (1) AppBar(上部)
    appBar: AppBar(
      title: Text('タイトル'),
    ),
    
    // (2) body(メインコンテンツ)
    body: Center(
      child: Column(
        children: [
          Text('Hello'),
          ElevatedButton(
            onPressed: () {},
            child: Text('ボタン'),
          ),
        ],
      ),
    ),
    
    // (3) FloatingActionButton(右下のボタン)
    floatingActionButton: FloatingActionButton(
      onPressed: () {},
      child: Icon(Icons.add),
    ),
    
    // (4) bottomNavigationBar(下部ナビ)
    bottomNavigationBar: BottomNavigationBar(
      items: [
        BottomNavigationBarItem(icon: Icon(Icons.home), label: 'ホーム'),
        BottomNavigationBarItem(icon: Icon(Icons.search), label: '検索'),
      ],
    ),
    
    // (5) drawer(サイドメニュー)
    drawer: Drawer(
      child: ListView(...),
    ),
  );
}

Scaffoldの順番:

  • appBar → body → floatingActionButton → bottomNavigationBar → drawer
  • 上から下、メインから補助の順

メソッド名の付け方ルール

プライベートメソッド(内部で使う):

// アンダースコア(_)で始める
void _incrementCounter() { ... }
Future<void> _loadData() async { ... }
int _calculateTotal() { ... }

パブリックメソッド(外部から呼ぶ):

// アンダースコアなし
void incrementCounter() { ... }
Future<void> loadData() async { ... }

99%の場合、State内のメソッドは _ 付き(プライベート)

コツを調べてみた!

コメントでセクション分け

class MyPage extends StatefulWidget {
  // ========================================
  // Variables
  // ========================================
  final String title;
  
  // ========================================
  // Constructor
  // ========================================
  const MyPage({required this.title});
  
  // ========================================
  // Create State
  // ========================================
  @override
  State<MyPage> createState() => _MyPageState();
}

見やすくなる! ✨

関連メソッドをまとめる

// ========================================
// データ関連
// ========================================
Future<void> _loadData() async { ... }
Future<void> _saveData() async { ... }
void _clearData() { ... }

// ========================================
// UI関連
// ========================================
Widget _buildHeader() { ... }
Widget _buildBody() { ... }
Widget _buildFooter() { ... }

// ========================================
// イベントハンドラ
// ========================================
void _onButtonPressed() { ... }
void _onTextChanged(String text) { ... }

分かりやすい! ✨

メソッドは短く

// ❌ 長すぎる
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      children: [
        Container(
          // 100行のコード...
        ),
        ListView(
          // 100行のコード...
        ),
        // ...
      ],
    ),
  );
}

// ✅ メソッドに分ける
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      children: [
        _buildHeader(),
        _buildList(),
        _buildFooter(),
      ],
    ),
  );
}

Widget _buildHeader() { ... }
Widget _buildList() { ... }
Widget _buildFooter() { ... }

1メソッド = 20-30行まで が目安!

async/await の順番

// Future<void> は非同期
Future<void> _loadData() async {
  // await を使う
  final data = await fetchFromDatabase();
  setState(() {
    _data = data;
  });
}

// void は同期
void _updateCounter() {
  setState(() {
    _counter++;
  });
}

まとめ: 順番の全体像

// 1. import (材料を集める)
import 'package:flutter/material.dart';

// 2. StatefulWidget (設計図)
class MyPage extends StatefulWidget {
  // 2-1. 定数
  // 2-2. final変数
  // 2-3. コンストラクタ
  // 2-4. createState
}

// 3. State (実際の家)
class _MyPageState extends State<MyPage> {
  // 3-1. 変数(状態)
  // 3-2. late変数
  
  // 3-3. ライフサイクル(決まった順番!)
  @override void initState() { super.initState(); }
  @override void dispose() { super.dispose(); }
  
  // 3-4. build(UI)
  @override Widget build(BuildContext context) {
    return Scaffold(...);
  }
  
  // 3-5. メソッド(機能)
  Future<void> _loadData() async { ... }
  void _updateUI() { ... }
}

一言まとめ:
コードの順番は家を建てる順番と同じ!
import(材料) → クラス定義(設計図) → 変数(部品) → ライフサイクル(組み立て) → build(完成) → メソッド(機能)。この順番を守ると、読みやすく、メンテしやすい!

目次