🧑‍✈️

エディタにFlutter/Dart AI Rulesを読み込ませてコード生成の質を高める

に公開

はじめに

突然ですが、AIの生成したコードで以下のようなサジェスト・生成コードを見たことはないでしょうか。


(それぐらい説明されなくてもわかる…)

上記のように、しばしばコード生成を使用すると、時折「メソッド名の直訳」や、「役割が自明なコードの説明」といった、意味のないコメントが生成されてしまったりします。

また、実装においても、「実装方針に沿わない実装をどんどん提案してきて、逆にコード補完が煩わしい」というような問題に陥った方も多いのではないでしょうか。

ルールを追加してコード生成の質を上げる

開発が進み参照できるコードが増えていくと、期待通りの出力をしてくれる可能性は高くなっていきますが、開発の初期段階ではそうはいきません。

今回は VSCode で copilot-instructions.mdを作成し、プロジェクト全体で使用するルールをcopilot に読み込ませます。

copilot-instructions.md を作成する

AI rules for Flutter and Dartを参考にcopilot-instructions.mdを作成します。

プロジェクトルート/
└── .github/
    └── copilot-instructions.md

ルールを記述する

ルールの形式はマークダウンのため、人間用のドキュメントをそのまま兼用することもできそうです。

ここでは、公式が公開している Flutter/Dart のためのAIルールのテンプレートを日本語に翻訳して使用します。

ルールを記述したら、VSCodeを再起動してください。

確認

ルール適用前と適用後のプロジェクトでそれぞれ以下のプロンプトを使用して、コード生成を行います。

各部に適切なコメントを追加して下さい

適用前

import 'package:flutter/material.dart';

/// アプリケーションのエントリーポイント
void main() {
  runApp(const MyApp());
}

/// アプリケーションのルートウィジェット
/// Material Designのテーマとホーム画面を設定
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

/// ホーム画面のStatefulWidget
/// カウンターの状態を管理する画面
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  /// アプリバーに表示されるタイトル
  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

/// MyHomePageの状態を管理するクラス
class _MyHomePageState extends State<MyHomePage> {
  /// ボタンが押された回数を保持するカウンター
  int _counter = 0;

  /// カウンターをインクリメントする
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      // 画面中央にカウンター表示を配置
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('You have pushed the button this many times:'),
            // カウンターの値を大きなフォントで表示
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      // カウンターをインクリメントするフローティングアクションボタン
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

適用後

import 'package:flutter/material.dart';

/// アプリケーションのエントリポイント
///
/// Flutter アプリケーションを起動し、[MyApp] ウィジェットをルートとして実行します。
void main() {
  runApp(const MyApp());
}

/// アプリケーションのルートウィジェット
///
/// MaterialApp を構成し、テーマやホーム画面を設定します。
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

/// ホーム画面を表示するウィジェット
///
/// カウンター機能を持つシンプルなデモ画面です。
/// ボタンをタップするとカウンターが増加します。
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  /// AppBar に表示されるタイトル
  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  /// ボタンがタップされた回数を保持するカウンター
  int _counter = 0;

  /// カウンターを1増加させる
  ///
  /// FloatingActionButton がタップされたときに呼び出され、
  /// setState を使用して UI を更新します。
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

どうでしょうか。
適用後の方がコメントが丁寧になり、無駄なコメントが削られた印象をうけるのではないでしょうか。

効果的なルールの運用

実際のプロジェクトで意識しているルールの運用方法を記載します。
基本的にAIのルールも人間用のルールと同じように運用するのが良いと思われます。

これには、副次的にチームメンバー用のドキュメントをAIルールに転用することができるメリットもあります。

✔ コード例を多く入れる

AI は “例” を学習しやすい傾向があるため、
良いコード例と悪いコード例をセットで入れると効果が高い です。

✔ チーム内で共通化する

ルールはGitで管理し、同じプロジェクトで働く開発者全員に適用するようにします。

✔ プロジェクト変更時に更新する

設計変更・規約追加があれば随時ルールファイルも更新します。

✔ 出力結果に応じて絶えず改善する

AIが質の悪いもの出してきたなと感じた時に、今後同様の生成を防ぐために、ルールファイルを絶えずに改善するようにします。


最後に

プロジェクトに新規参入したとき、プロジェクトルールに沿わない実装をしてしまったような経験は誰しもあると思います。

AIも同じように、ルールが明示されていなければ、プロジェクトの方針にそぐわないコード生成行ってしまいます。

そのため、AI コード生成を積極的に利用するプロジェクトにとっては、効率的にAIを活用するためにルールの明示してあげることが必須と言えます。

PR

アンドエーアイでは事業拡大のため、即戦力エンジニアを募集中!Flutterだけでなく、インフラ、Web、ネイティブ開発などの知識を持つ方も歓迎します。最新技術を追い、チームに積極的に貢献できる方をお待ちしています!

採用ページ
https://iwantyou.andai.net/

エンジニア採用ページ
https://iwantyou.andai.net/engineer

アンドエーアイTechBlog

Discussion