
目次
はじめに:一人では完璧、チームでは機能しない
半年前、驚くべきスピードでコードを書く新人エンジニアがチームに加わりました。
GitHub Copilotを使いこなし、Flutterの実装スピードは私の2倍以上。コードの品質も高い。技術的には申し分ありませんでした。
しかし、3ヶ月後、彼の書いたコードは誰もメンテナンスできない状態になっていました。
なぜか?
- コメントがほとんどない(「コード見ればわかる」という考え)
- 変数名が暗号のよう(`tmp1`、`data2`、`flg`など)
- 設計思想がドキュメント化されていない
- 他のメンバーに相談せず、勝手に仕様を変更する
彼は個人としては優秀でした。でも、チームの一員としては機能していませんでした。
ある日、彼が体調を崩して休んだとき、誰も彼のコードを理解できず、プロジェクトが止まりました。
その時、私は確信しました。
AI時代だからこそ、「個のスキル」より「共に創る力」が重要になる。
AI時代に変わるチーム開発の風景
GitHub Copilotがいる開発現場
GitHub Copilotの登場で、チーム開発のダイナミクスが変わりました。
以前:
- ベテランがコードを書く → 若手がレビューを受けて学ぶ
- 技術力の差が、開発スピードの差に直結
現在:
- 若手もAIを使って高速にコードを書ける
- 技術力の差が見えにくくなった
- でも、「コードの意図」や「設計思想」を説明できるかどうかで差が出る
実例:Flutter製アプリ開発での変化
最近、チームでFlutter製の社内SNSアプリを開発しました。
入社1年目のメンバー(Aさん)と、5年目のベテラン(Bさん)がペアで開発を進めました。
1週目の状況:
Aさんは、GitHub Copilotを駆使して、驚異的なスピードで画面を実装していきます。Bさんよりも速い。
でも、コードレビューで問題が発覚。
// Aさんのコード
Widget build(BuildContext context) {
return FutureBuilder(
future: http.get(Uri.parse('https://api.example.com/posts')),
builder: (context, snapshot) {
if (snapshot.hasData) {
var data = json.decode(snapshot.data.body);
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]['title']),
);
},
);
}
return CircularProgressIndicator();
},
);
}
問題点:
- 毎回buildのたびにAPI通信が走る(パフォーマンス問題)
- エラーハンドリングがない
- 状態管理の考慮がない
- テストが書けない構造
一方、Bさんのコードは:
// Bさんのコード
class PostListScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final postsAsync = ref.watch(postsProvider);
return postsAsync.when(
data: (posts) => ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
return PostListTile(post: posts[index]);
},
),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => ErrorView(error: error),
);
}
}
違いは何か?
Aさんは「動くコード」を書きました。
Bさんは「チームで保守できるコード」を書きました。
2週目以降:
私はAさんとBさんにペアプログラミングを提案しました。
Bさんが設計思想を説明しながら、Aさんが実装する。Aさんは「なぜそうするのか」を質問しながら学ぶ。
この経験を通じて、Aさんは気づきました。
「AIは『How(どうやって)』を教えてくれるけど、『Why(なぜ)』は人から学ぶ必要がある」
コミュニケーション設計:伝わるドキュメントの書き方
システム開発全体の管理をしていると、痛感することがあります。
良いドキュメントがあるチームは、強い。
AIがコードを書く時代だからこそ、「人間が読むドキュメント」の重要性が増しています。
ドキュメントの3つのレイヤー
私がチームで推奨しているドキュメント構造です。
レイヤー1:README(10分で理解できる)
目的: 新メンバーが、このプロジェクトの全体像を掴む
必須項目:
# プロジェクト名
## 概要
何を作っているのか、なぜ作っているのか(1-2行)
## 技術スタック
- Flutter 3.x
- State Management: Riverpod
- Backend: PHP 8.x / Laravel
- Database: MySQL 8.x
## セットアップ
1. 環境構築手順
2. 初回起動方法
3. よくあるエラーと対処法
## プロジェクト構造
主要なディレクトリの説明
## 開発ルール
- コーディング規約へのリンク
- Git運用ルール
- レビュープロセス
ポイント:
新メンバーが1日目に読むドキュメント。「何から始めればいいか」が明確になっている。
レイヤー2:設計ドキュメント(深く理解できる)
目的: なぜこの設計にしたのか、背景と意図を共有する
PHPバックエンドの例:
# API設計書
## 認証方式
JWT (JSON Web Token) を採用
### なぜJWTを選んだか
1. ステートレスな認証が可能(スケーラビリティ)
2. Flutterアプリとの相性が良い
3. リフレッシュトークンで長期ログインに対応
### 代替案として検討したもの
- セッションベース認証 → サーバー負荷の観点で不採用
- OAuth 2.0 → 過剰な仕様のため不採用
## データベース設計
### users テーブル
なぜこのカラム構成なのか、将来の拡張性をどう考えたか
### 正規化のレベル
第3正規形まで適用。パフォーマンスとメンテナンス性のバランスを考慮。
ポイント:
「何をしたか」だけでなく、**「なぜそうしたか」「他にどんな選択肢があったか」**を明記する。
レイヤー3:コード内コメント(実装レベルで理解できる)
悪いコメント例:
// データを取得
final data = await repository.getData();
// ループで処理
for (var item in data) {
// 表示
print(item);
}
これは「What(何を)」しか書いていません。コードを読めばわかることです。
良いコメント例:
// NOTE: APIのレート制限(100req/分)を考慮し、
// バッチサイズを50件に制限している
final data = await repository.getData(limit: 50);
// FIXME: この処理は O(n²) で非効率。
// 将来的にMapを使った O(n) のアルゴリズムに変更予定
// 関連Issue: #123
for (var item in data) {
// ...
}
// HACK: iOS14以下でクラッシュする問題の回避策
// 本来は不要だが、ユーザーの10%がまだiOS14を使っているため
// 2025年Q2に削除予定
if (Platform.isIOS && iOSVersion < 15) {
// 回避コード
}
ポイント:
- NOTE: 設計判断の理由
- FIXME: 技術的負債の明示
- HACK: 緊急回避策の説明と削除予定
ドキュメントが古くなる問題への対処
「ドキュメントはすぐ古くなるから、書かない方がいい」という意見を聞きます。
でも、それは間違いです。
古くなっても、ないよりはマシ。
私のチームでは、こんなルールを設けています。
ルール1:コードを変更したら、関連ドキュメントを同時に更新する
- Pull Requestのチェックリストに「ドキュメント更新」を追加
ルール2:月1回、ドキュメントレビューDay
- ドキュメントと実装が乖離していないかチェック
ルール3:「わからなかった」を記録する
- 新メンバーがつまづいた箇所を、ドキュメントに反映
レビュー文化:育てるレビュー、潰すレビュー
コードレビューは、チーム開発の要です。
でも、やり方次第で、チームを育てることも、潰すこともできます。
潰すレビューの特徴
例1:上から目線のコメント
❌ 「こんなコードも書けないの?」
❌ 「常識でしょ」
❌ 「ググればわかるよね」
例2:具体性のない指摘
❌ 「このコード、微妙」
❌ 「もっといい書き方があるはず」
❌ 「品質が低い」
例3:完璧主義の押し付け
❌ 「この命名は〇〇の方がいい」(些末な指摘の連続)
❌ 「リファクタリングしてから再提出」(常に)
❌ 「自分ならこう書く」(個人の好みの押し付け)
こうしたレビューは、メンバーの意欲を削ぎます。
育てるレビューの特徴
例1:疑問形で問いかける
✅ 「この処理、〇〇の場合はどう動きますか?」
✅ 「〇〇というアプローチも考えられますが、どう思いますか?」
✅ 「なぜこの実装を選んだのか、教えてもらえますか?」
例2:理由を添えて提案する
✅ 「この処理は毎回API通信が走りますね。
パフォーマンスを考えると、キャッシュを検討してはどうでしょうか?」
✅ 「変数名がaだと、3ヶ月後に見たとき意味がわからないかもしれません。
userAccountのような説明的な名前はどうでしょう?」
例3:良い点を先に伝える
✅ 「エラーハンドリングがしっかりしていて素晴らしいです!
ただ、この部分は〇〇の懸念があるので、△△にしてはどうでしょう?」
例4:学びを共有する
✅ 「この実装、勉強になりました!こういう書き方もあるんですね」
✅ 「この設計パターン、私も使ってみます」
私が実践している「レビューのレビュー」
品質管理の一環として、レビューコメント自体もチェックしています。
月1回、レビューコメントを振り返る会を開催:
- 良かったレビューコメントを共有
- 改善できるレビューコメントを議論
- 「このコメント、どう感じた?」と受け手の気持ちを確認
チーム全体のレビュー文化が改善され、心理的安全性が高まりました。
プロジェクトを動かす"人間力"とは
技術力だけでは、プロジェクトは成功しません。
システム開発全体の管理をしていて、強く感じることです。
ケース1:炎上プロジェクトの立て直し
1年前、納期が迫っているのに進捗が30%という炎上プロジェクトの立て直しを任されました。
状況:
- チームメンバーは優秀
- 技術スタックも適切(Swift、PHP)
- でも、全く進まない
原因を調査すると:
- メンバー間のコミュニケーションが皆無
- 「誰が何をやっているか」が不透明
- 問題が起きても、誰も声を上げない
- 責任の押し付け合いが発生
技術の問題ではなく、チームの問題でした。
私が最初にやったこと:
1. デイリースタンドアップミーティング(15分)
毎朝9時、全員が集まって:
- 昨日やったこと
- 今日やること
- 困っていること
最初は形式的でしたが、2週間続けると、自然に助け合う雰囲気が生まれました。
2. 「質問タイム」の設置
毎日15:00-16:00は「質問タイム」。
誰でも、どんな質問をしてもOK。
「こんなこと聞いたら恥ずかしい」と思っていた若手が、積極的に質問するようになりました。
3. 成功体験の共有
週1回、「今週の良かったこと」を発表。
- 「〇〇さんのアドバイスでバグが解決できました」
- 「〇〇さんのコードレビューで学びがありました」
お互いを認め合う文化が生まれました。
結果:
3ヶ月後、プロジェクトは予定通りリリース。
技術的な変更はほとんどしていません。チームのコミュニケーションを改善しただけです。
ケース2:リモート開発での孤立を防ぐ
リモートワークが増えた今、「見えない孤立」が問題になっています。
オフィスなら、「なんか困ってそうだな」と気づけた。
でも、リモートだと、誰かが苦しんでいても見えない。
私のチームでの工夫:
1. Slackの「times」チャンネル
各メンバー専用の独り言チャンネル。
- 「このエラー、なんだろう...」
- 「やっと解決した!」
- 「昼ごはん、何食べよう」
独り言を書くことで、誰が何をしているかが見える。
困っていたら、自然に「それ、こうしたらどうですか?」と声がかかる。
2. ペアプログラミングの積極活用
週2回は、誰かとペアでコーディング。
GitHub Copilotがあっても、人と一緒に考えることで、新しい発見がある。
ベテランと若手、AIが交わる現場のリアル
チームには、様々な経験年数のメンバーがいます。
AI時代、この多様性をどう活かすか。
ベテランの価値:「Why」を語れる
ベテランエンジニアの中には、焦りを感じている人もいます。
「若手がAIを使って、自分と同じスピードでコードを書いている...」
でも、ベテランにしかできないことがあります。
「なぜその設計にしたのか」を語ること。
例:PHP/Laravelでの実装
若手:「このControllerに全部書けば動きます!」
class UserController extends Controller
{
public function store(Request $request)
{
// バリデーション、DB保存、メール送信、ログ記録...
// すべてがController内に
}
}
ベテラン:「動くけど、メンテナンスが大変になるよ。こう分離してみて」
// Controller は入力の受付だけ
class UserController extends Controller
{
public function __construct(
private UserService $userService
) {}
public function store(UserCreateRequest $request)
{
$user = $this->userService->createUser($request->validated());
return new UserResource($user);
}
}
// ビジネスロジックはServiceに
class UserService
{
public function createUser(array $data): User
{
DB::transaction(function () use ($data) {
$user = User::create($data);
$this->sendWelcomeEmail($user);
$this->logUserCreation($user);
return $user;
});
}
}
「なぜ分離するのか」を説明できるのが、ベテランの強みです。
若手の価値:新しいツールへの適応力
若手エンジニアは、新しいツールへの抵抗が少ない。
GitHub Copilot、ChatGPT、最新のフレームワーク...
どんどん試して、チームに知見を共有してくれます。
ベテランが「原理」を教え、
若手が「最新のやり方」を教える。
相互に学び合う関係が、最強のチームを作ります。
AI:チーム全員の「助っ人」
AIは、誰かの脅威ではなく、チーム全員の助っ人です。
ベテラン × AI:
長年の経験から得た設計思想を、AIに説明。
AIが、それを素早くコードに落とし込む。
若手 × AI:
わからないことを、AIに質問。
AIが、教育者としてサポート。
チーム × AI:
ドキュメント生成、テストコード作成、リファクタリング提案...
チーム全体の生産性が向上。
心理的安全性:最も重要なチームの条件
Googleの研究で、「最高のチームの条件」が明らかになりました。
それは、技術力でもなく、天才の存在でもなく、「心理的安全性」でした。
心理的安全性とは
「どんな質問をしても、バカにされない」
「失敗しても、責められない」
「意見を言っても、否定されない」
そんな環境のこと。
私のチームで実践していること
1. 「失敗共有会」を月1回開催
うまくいかなかったことを、笑いながら共有。
- 「こんなバグを作ってしまいました(笑)」
- 「こんな勘違いをしていました(笑)」
失敗を責めない文化が、チャレンジを生みます。
2. 「わからない」を言いやすく
わからないことを聞くのは、恥ずかしいことじゃない。
私自身が率先して「これ、よくわからないんだけど、教えて?」と言います。
リーダーが弱みを見せることで、メンバーも安心して質問できます。
3. 感謝の言葉を惜しまない
- Pull Requestに「ありがとう」
- レビューに「勉強になりました」
- Slackで「助かりました!」
感謝の文化が、チームの雰囲気を良くします。
AI時代のチーム開発:5つの原則
これまでの内容をまとめると、AI時代のチーム開発で重要なのは:
原則1:「Why」を共有する文化
コードだけでなく、**「なぜそうしたのか」**を伝える。
ドキュメント、コメント、会話、すべてで。
原則2:育てるレビューを実践する
批判ではなく、成長を促すレビュー。
質問し、提案し、学び合う。
原則3:コミュニケーションを設計する
自然発生を待たない。
意図的にコミュニケーションの仕組みを作る。
原則4:多様性を活かす
ベテラン、若手、AI、それぞれの強みを活かす。
お互いに学び合う関係を作る。
原則5:心理的安全性を守る
失敗を責めず、質問を歓迎し、感謝を伝える。
これが、最強のチームの土台。
まとめ:一人では速く、チームでは遠くまで
アフリカのことわざに、こんな言葉があります。
「速く行きたいなら、一人で行け。
遠くまで行きたいなら、みんなで行け」
AI時代、個人の生産性は確かに上がりました。
GitHub Copilotを使えば、一人で驚くほど速くコードが書けます。
でも、システム開発は、長距離走です。
数ヶ月、数年と続くプロジェクト。
何度も仕様変更があり、技術的な壁にぶつかり、予期せぬトラブルが起きる。
そんな時、一緒に乗り越えられるチームがあるかどうか。
これが、プロジェクトの成否を分けます。
AIは強力なツールです。
でも、チームで使ってこそ、真価を発揮します。
一人で抱え込まず、チームで共有する。
一人で悩まず、チームで議論する。
一人で完璧を目指さず、チームで改善し続ける。
そんなチーム開発の力が、AI時代だからこそ、問われているのです。
次回予告
第5回では、**「AIを味方につけるためのスキルマップ」**をお届けします。
これまで、課題定義力、設計思考、チーム開発力と、「変わらない本質」について語ってきました。
次回は、具体的に「何を学ぶべきか」「どう学ぶか」を掘り下げます。
- これから必要とされるスキルセット
- PythonやSQLなど「AIと共通言語を持つ」意義
- Prompt Engineeringの実践
- 継続学習のコツ
学習意欲のあるあなたに、具体的な行動指針を提示します。
【AI時代を生き抜くシステムエンジニア論 - 連載目次】
- AI時代の到来と、SEの役割の変化
- AIに代替されないSEの基本「課題定義力」と「論理的思考」
- 変わる技術トレンド、変わらない「設計思考」
- AIと共存する時代の"チーム開発力"(今回)
- AIを味方につけるためのスキルマップ
- これからも変わらない"システムエンジニアの本質"