はじめに
皆さんこんにちは!
今回のAKARI Tech Blogは、AI SaaS 事業部 DevのHEが担当します。
私の所属するチームでは、「品質はコストではなく、競争力」という考えを大事にして開発を行っています。
今回は、その考え方や理由を、社内向け文書をまとめ直す形でお伝えしたいと思います。
品質はコストではなく、競争力
品質を軽視する組織は、必ず速度を失います。
その代償は、障害対応・人の離脱・作り直しとして必ず返ってきます。
一方で、品質を積み上げる組織は、信頼性・採用力・開発速度という競争力のすべてを強化していくでしょう。
手戻りなく、最高速度で開発できる品質は、長期的に見れば最も安価で、最も鋭い剣となります。
なぜ品質が競争力になるのか
品質と開発速度はトレードオフ──そう考えてしまいがちですが、実は逆です。
その理由として、下記のような項目があります。
信頼性
品質を積み上げたシステムは、顧客からの信頼が高い。
バグが少なく安定して動くことで、使う側は安心できる。また、そうしたシステムは拡張性に優れるため、新しい機能や改善の要望を叶えやすい。
結果として、顧客は安心して利用・依頼できるようになる。
採用力
品質を重視するチームは、エンジニアにとって以下の点で魅力的だ。
- テストやレビューの仕組みが整っている:安全にコードをリリースできる。
- コードが読みやすい:読みにくいコードは非常にストレス。
- 無駄な調整や残業が減る:誰しも無意味な作業はしたくない。
- 学びの機会が多い:良いコードや設計に触れ、技術力が伸びる。
開発速度
品質の高いコードは、開発速度を自然に上げる。
バグや作り直しに時間を取られず、どこを直せばよいかすぐ分かり、あとから機能を追加しやすいからだ。乱雑に絡まったケーブルのようなコードでは、どこを触ると他に影響が出るか分からず、作業に時間がかかる。
整理されたケーブルのように、構造が明快で整理されたコードなら、すぐに手を入れられ、作業がスムーズに進む。
エンジニアが守る高品質コードの5原則
高品質なコードは偶然生まれるものではありません。次に、優れたチームがどのような原則に沿ってコードを書いているかを抜粋してご紹介します。
①可読性
コードを自然言語の文章のようにすらすらと読めること。誰が見ても意図がすぐ理解でき、修正や追加が迷わずできる状態を指す。
ポイントは
- 命名:変数や関数の名前で何をするか直感的に分かる。
- 構造:処理の流れが順序立てて理解できる。
- コメント:意図や理由を補足して、読み手の混乱を減らす。
可読性が高いコードは、後から触れる人の負担を大きく減らす。なお、この後から触れる人には「半年後の自分」も含まれる。半年前に書いたコードを覚えている人はほぼいないからだ。
- 当チームのAI Coding Agent用の指示ファイルにあるコメント規約
### コメント規約
#### コメントのガイドライン
- **思想**: コードを自然言語と同レベルで読めるようにする
- **簡潔で明確**: 短いコメント(例: `// 搭載データを準備する`, `テストAPI呼び出し`)
- **処理ブロック単位**: 論理的なまとまりごとにコメントを付ける
- **コードを意訳**: 動作そのものより動作の意味を書く
- **日本語推奨**: 日本語でコメント
// ✅ 良い例(下記の例で←で始まる括弧内は注釈なのでコメントに含めない) /**(←関数ドキュメントにはJSDoc) * ABC変更に伴い、ユーザーに返すデータを返す(←何をする関数かが簡潔で明瞭) */ const handleChangeABC = async () => { // 文字列バリデーション(←簡潔で明瞭なコメント) isCorrect = isTextValid(); if (isCorrect && !isInputting) { // バリデーションが通り、ユーザーが入力中でないなら(←if句の直下に条件説明をつける) // 初期化する(←動作を意訳) setLoading(false); // ユーザーに返すデータを準備する(←一連のロジックをまとめている) const rawData = get(); const data = setup(rawData); buildUserPayload(data); } else { // ユーザーに警告を出す(←JSDocから取得して掲載する) abcdefWarning(); } // 処理が未完了なら再開する(←短い処理ブロックならif句でも上にまとめて良い) if (!isCompleted) { Restart(); } }; // ❌ 悪い例 // ABC変更イベントハンドラー(←JSDocじゃない、イベントハンドラーという関数の種類を書くのは無駄) const handleChangeABC = async () => { // バリデーション(←簡潔すぎて不明瞭) isCorrect = isTextValid(); // バリデーションが通り、ユーザーが入力中でないなら(←if句の外に条件説明) if (isCorrect && !isInputting) { // ローディング状態をfalseに(←動作を直訳しただけの無意味なコメント) setLoading(false); const rawData = get(); // 生データ取得(←下のコメントとまとめられていない) const data = setup(rawData); // 生データを加工 (←細かすぎるコメント) // ユーザーペイロードデータを準備する(←変数を直訳したので分かりにくい) buildPayload(data); } else { abcdefWarning();(←コメントなしで何をしているか不明) } if (!isCompleted) { // 処理が未完了なら再開する(←短い処理ブロックなのにif句の中) Restart(); } };
②再利用性
DRY原則(Don’t Repeat Yourself)に準拠。使い回せるコードは使い回す。
ポイントは
- 共通化:同じ処理は関数やモジュールにまとめる。
- 汎用的設計:特定の状況に縛られず、柔軟に使える。
- モジュール化:部品として切り出せるので、他箇所に安全に導入できる。
同じコードが複数ある場合、その処理で変更点が生じるとすべての箇所に同じ変更を加える必要が出てくる。
③拡張性
既存のコードを壊さずに増築や変更ができること。変更や追加が容易であれば、手戻りやバグのリスクを最小限にできる。
ポイントは
- 責務の分離:一つの部品や関数が担う役割を明確にする。
- インターフェースの明確化:外部と接続する部分を安定させる。
- 柔軟な構造:将来的な変更や機能追加を想定した設計にする。
④保守性
コードが動いているときに挙動が明白で、ブラックボックスにならないこと。中でどう動いているかがわからないと、問題が起きた時に対処が難しい。
ポイントは
- 観測可能:ログやメトリクスで何が起きたか分かる。
- テストが容易:単体・統合テストが書きやすい構造。
- デバッグが容易:異常時に原因を追いやすい設計。
- 構造が透明:制御フローや依存関係が追いやすい。
⑤完全性
コードやシステムが意図した機能を漏れなく安全に実現すること。想定外の状況や入力でも正しく動作し、副作用を最小限に抑えることが重要だ。
ポイントは
- 境界値・例外処理の考慮:想定外の入力や状況でも安全に動作する。
- 入力検証:不正なデータや形式が入った場合も安全に対応できる。
- 副作用の管理:他の機能やデータに影響を及ぼさないように設計する。
完全性が高いコードは、ユーザーや他のシステムに対して予期せぬ振る舞いを避け、信頼性を確保できる。
プログラマの三大美徳
上記を達成するために、優れたエンジニアは、次の三大美徳を行動の指針として持っています。
憤怒(短気)
先に起こりうる問題を今から潰す短気さ。
→ 早期に問題を発見・修正することで手戻りやバグを減らし、開発をスムーズに進められる。
傲慢
他者に文句を言わせないような質の高い成果物を作ろうとする傲慢さ。
→ 設計やコメント、他の全てにおいて、初心者からベテランまで誰もが認めてくれるものを。
あとがき
最後までお読みいただき、ありがとうございます。
品質を意識した開発は、一朝一夕で身につくものではありません。しかし、今回ご紹介した高品質コードの原則やエンジニアの美徳を意識することで、チーム全体の速度・信頼性・採用力を着実に高めることができます。
当社でも、この考え方を少しずつ取り入れ、品質を競争力として活かす文化を育てています。皆さんのチームでも、同じように取り組んでいただければと思います。
今後も、開発現場で役立つ知見を共有してまいりますので、どうぞご期待ください。
We’re Hiring!
私たちは共に学び、共に強くなれるエンジニア仲間を募集しています!
- 挑戦したい人
- ルーチンワークを嫌う人
にとっては特に面白い環境だと思います。
燈では、あらゆる分野のITエンジニアを募集しています。
興味がある方は、ぜひ採用ページをご覧いただき、カジュアル面談でお話しましょう!🔥
akariinc.co.jp