【kintoneカスタマイズで抱えてた問題点】
kintoneカスタマイズ、便利ですよね。JavaScriptを使って、アプリ内にボタンを出現させたり、フィールドを非表示にしたり...標準機能ではできないことを実現してくれます。
ただ、多くの記事では下記のようなコード例が紹介されています。(引用元)
// index.js
// レコード追加画面の保存成功後イベント
kintone.events.on('app.record.create.submit.success', (event) => {
const record = event.record;
const appId = event.appId;
const recordId = event.recordId;
const createDate = luxon.DateTime.fromISO(record.作成日時.value).toFormat('yyyyMMdd');
// レコードの更新API
const body = {
app: appId,
id: recordId,
record: {
submit_No: {
value: `交通${createDate}-${recordId}`
}
}
};
return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body).then(resp => {
alert(`申請No: 交通${createDate}-${recordId}を登録しました`);
return event;
}).catch(error => {
alert(error.message);
return event;
});
});
})();
indexファイルにすべてを書き込む形です。この例では自動採番を行ってるだけなのでまだ読みやすいですが、もしここに、
- フィールドの非活性化
- 保存時のバリデーションチェック
- 一覧ページでのボタン表示とあれとこれと...
と、モリモリとカスタマイズを加えていったら、どうなるでしょうか?
機能が増えれば増えるほどindexファイルが巨大化し、数百行にも及ぶ手が付けられないコードへと変わっていきます。
AI開発が加わると、事態はさらにカオスになります。機能そのものは瞬く間に完成しますが、その反面、
- 無秩序なコード変更により可読性が急激に低下する
- 容赦ない大量のコード変更によって予期せぬバグが混入する
- どこにどの処理が書かれているか人間が追えなくなり、保守不能に陥る
といった深刻な問題も浮き彫りになってきました。
【課題へのアプローチ】
だからといって、今後の開発において「AIを使わない」という選択肢はありません。
そこで、
「コーディングガイドラインを制定し、AIにはそれに厳格に従って実装してもらう」
という解決策が、チームの中で提案されました。これなら、人間にとっての可読性を維持しつつ、AIの実装スピードという恩恵も享受できるはずです。
【具体的なアクション】
コーディングガイドラインを作成するために、チームメンバーで次のようなアクションを取りました。
✏チーム内での認識合わせ
コーディングガイドラインを作成するにあたり、まずはチーム内で「正しいコードの書き方」に対する認識を揃える必要がありました。そこで、メンバーそれぞれが技術書を読みアウトプットする、定期勉強会を開催しました。扱った教材の一例です。
✏ガイドラインの策定と環境整備
勉強会のたびにコーディングガイドラインを更新し、AIもチームメンバーも同じルール下でコーディングできるよう整備を進めました。
✏ガイドライン完成
完成したガイドラインの要約を載せておきます。これをリポジトリに置き、GeminiCodeAssistには「このガイドラインを読んで実装してね」と伝えることにしました。
本ガイドラインは、AIと人間が協調して保守性の高いシステム(インテリジェント・オフィスビル)を構築するための指針です。
**1. ディレクトリ構成とファイル分割(高い凝集度)**
機能的凝集度を高めるため、アプリごとにディレクトリを作成し、内部を「関心事の分離」に基づき`api`(外部通信)、`logic`(ビジネスロジック)、`view`(DOM操作)の3層に分割します。ファイル名は`{domain}.{layer}.ts`形式で統一し、各ファイルが単一の役割のみを持つように徹底します。
```text
src/
├── app01/ # アプリ単位で分割
│ ├── index.ts # イベントハンドラ(総合受付)
│ ├── api/ # 通信担当 (例: customer.api.ts)
│ ├── logic/ # 頭脳担当 (例: customer.logic.ts)
│ └── view/ # 画面担当 (例: customer.view.ts)
└── common/ # 汎用モジュール
```
**2. マジックストリングやマジックナンバーの排除**
コードの意味不明な数値や文字列は、メンテナンス性を損なうため直接記述を禁止します。アプリIDは全プロジェクト共通の定数ファイルで、フィールドコードや閾値は各アプリ固有の定数ファイルで一元管理します。
```typescript
// src/common/constants/appIds.ts (アプリIDの一元管理)
export const APP_IDS = { PROJECTS: 1, INVOICES: 2 } as const;
// src/app01/constants.ts (アプリ固有の定数)
export const FIELD_CODES = { CUSTOMER_RANK: '顧客ランク' } as const;
export const TAX_RATE = 0.1;
```
**3. JSDocによる契約の文書化**
`export`される全ての関数にはJSDocを記述します。これはAIや他開発者に対する「契約(Contract)」として機能します。実装コードが「What」を語るのに対し、コメントには「Why(意図や背景)」と入出力の定義を明記します。
```typescript
/**
* 取引総額に基づき顧客ランクを判定します。
* @param totalAmount - 取引総額(正の整数)
* @returns ランク ('A' | 'B' | 'C')
*/
export const determineRank = (totalAmount: number): string => { /*...*/ };
```
**4. エラーハンドリング戦略**
エラーは「もみ消し」を行わず、階層的に処理します。`api`層で技術的エラーを検知して報告し、`logic`層で業務的な意味(ユースケースエラー)を与えてログ出力し、最終的に`view`層でユーザーへ通知を表示します。
```typescript
// 1. Api層: エラーを検知し、原因を含めて投げる
} catch (e) { throw new ApiError('登録失敗', { cause: e }); }
// 2. Logic層: コンテキスト情報を付与してログ出力し、再スロー
} catch (e) { console.error(orderId, e); throw new UsecaseError('作成失敗'); }
// 3. View層: ユーザーにメッセージを表示
} catch (e) { kintone.portal.showNotifier({ text: e.message }); }
```
【結果と振り返り】
コーディングガイドライン × AI駆動開発をチームで本格的に導入して約2カ月が経過し、良かった点と悪かった点の両方が見えてきました。
✏良かった点
-
コードの構造化による可読性向上
旧:index.tsに全ての処理が集中し、解読困難が不可能な状態でした。
新:役割ごとにファイル分割されたスッキリとした構成に生まれ変わりました。これにより、開発中や保守時にどこを修正すればよいかが明確になりました。 -
AIとの協業効率化
リポジトリ内にAI参照用のガイドラインを配置したことで、AIが自律的にガイドラインに沿ったコーディングを行ってくれるようになりました。人間側としても「なぜその実装になったのか」「なぜその変更が必要だったのか」が追いやすくなり、綺麗なコードを圧倒的な速度で書けるようになったと実感しています。
✏悪かった点(苦労した点)
-
プロンプトエンジニアリングの工数増
AIに実装を任せる分、どうしてもプロンプトを練る時間は長くなります。AIが出力するコードはまだ完璧とは言えません。そのため、現在は以下のフローを踏んでいます。- 要件をAIに詳細に伝える(この作成にまず時間がかかる)
- 実装上の疑問点や懸念点がないかAIに壁打ちする
- AIからの疑問・懸念に回答する(ここが特に長い!)
- 詳細設計を出してもらい、それをブラッシュアップする
- ようやくAIによる実装
- 静的エラーの解消・kintone上での動作確認&エラー解消
-
コミュニケーションの「事故」
上記のフローを踏んでいるのでチャットが長くなりすぎて過去の文脈(コンテキスト)が忘れ去られることが良くあります。
また、明らかに質問をしている段階なのに「それではコーディングに入りますね❗❗」とAIが勝手に実装を始めてしまったりすることも...。
とはいえ、多少の苦労はありつつも、このクオリティとスピード感で機能を実装できている点、そして何より保守が楽になっている点を考慮すれば、AI開発を前提としたコーディングガイドラインの制定は、圧倒的にメリットの方が大きかったと結論づけて良さそうです。
今後の展望
AI開発ならではの「時間がかかる部分」については、まだ改善の余地があります。今後は以下の対策を考えています。
-
チケットや実装機能の粒度調整
機能を一度に実装しようとせず、モジュール単位などで細かく分割して実装を進めるのが良さそうです。 -
生成AIの使い分け
「要件整理・疑問点の洗い出し・詳細設計」といった上流工程は、Gemini Code Assistのようなエディタ統合型ではなく、より多くのコンテキストを保持できるチャット特化型の生成AI(ChatGPTやGeminiのWeb版など)で行うなど、ツールの使い分けも有効そうです。
また、本筋とは少し逸れますが、kintoneカスタマイズにおける「自動テスト」についても今後深掘りしたいと考えています。
コードの影響範囲が掴みやすくなったとはいえ、変更によって予期せぬ障害が起きるリスクはゼロではありません(実際、先日も発生しました)。しかし、kintoneのデータ操作(CRUD)は本番環境のアプリでしか行えず、一般的なWebアプリ開発のように「仮想のテスト環境(DB)を用意して、そこで破棄前提のテストを行う」といった手法をとるのが難しいのが現状です。
このあたりは引き続き、調査・検討を進めていきたいと思います。