# 開発におけるコーディングルール・規約
チーム開発でも個人開発でも、保守性の高いコードを書くことは重要です。この記事では、実践的なコーディングルールと規約について、基本原則から本番環境での運用まで、包括的に解説します。
# コーディングルールの重要性
コーディングルールは、単なる「お作法」ではありません。適切なルールを設定し、遵守することで以下のメリットが得られます:
- 可読性の向上: 統一されたスタイルにより、コードの理解が容易になる
- 保守性の向上: 一貫性のあるコードは修正や拡張が容易
- バグの削減: 明確なルールにより、よくある間違いを防げる
- チーム開発の効率化: コードレビューがスムーズになり、知識共有が促進される
- 技術的負債の削減: 長期的なメンテナンスコストを削減
# 基本的なコーディング原則
すべての開発において、ソースコードがスパゲッティ化にならないように気をつけるべき基本原則:
- 変数宣言は関数の最初に行う: 変数のスコープを明確にし、可読性を向上
- 関数の上にコメントで説明を入れる: 関数の目的、引数、戻り値を明記
- グローバル変数はできるだけ作らない: 副作用を減らし、テストしやすくする
- 単一責任の原則: 1つの変数・関数は1つの目的のみを持つ
- 関数の肥大化を防ぐ: 長すぎる関数は分割し、再利用可能な単位に
- 入れ子の階層は2階層まで: 深いネストは可読性を下げる
プロフェッショナルな開発者の心得: コーディングの速さ、メンテナンスのしやすさ、後継者のことを考えながらコーディングするのがプロである
# 開発環境の基本設定
# エディターとツール
- VSCode を使用: チームで統一されたエディターを使用することで、設定の共有が容易
- コードフォーマッター: Prettier - Code formatter (opens new window) を使用して自動フォーマット
- Linter: ESLint (opens new window) や PHP_CodeSniffer でコード品質をチェック
# コード品質の基本原則
- マジックナンバーを避ける: 数値や文字列は定数として定義し、意味を明確化
- 型のキャストは小文字を使用:
(int),(string),(array)など - 文末の空白を除去: 不要な空白は削除し、git の差分をクリーンに保つ
- クォートの使い分け: シングルクォートとダブルクォートを適切に使い分ける
- シングルクォート: 文字列リテラル(変数展開なし)
- ダブルクォート: 変数展開が必要な場合
// 悪い例:マジックナンバー
if ($user->age > 18) {
// ...
}
// 良い例:定数を使用
define('ADULT_AGE', 18);
if ($user->age > ADULT_AGE) {
// ...
}
// 悪い例:不適切なクォート使用
$message = "Hello, $name"; // 変数展開が必要な場合のみダブルクォート
// 良い例:適切な使い分け
$message = 'Hello, ' . $name; // シングルクォートで十分
$message = "Hello, {$name}"; // 変数展開が必要な場合
# チーム開発における共有・連絡事項
チーム開発において、以下の変更は必ず事前に共有・連絡する必要があります。適切なコミュニケーションにより、予期しない問題を防ぎ、スムーズな開発を実現できます。
# 必須共有項目
# データベース関連
- マイグレーション: migration 追加・変更・削除
- テーブル構造変更: テーブル構造の変更、インデックスの追加・削除
- データ移行: 大量データの移行が必要な場合
# 設定・環境関連
- 設定変更: 設定ファイルの変更、追加する必要がある env config など
- 環境変数: 新しい環境変数の追加、既存環境変数の変更
- コマンド実行: デプロイ時やセットアップ時にコマンド実行する必要がある場合
# API・インターフェース関連
- API 変更: 既存 API の仕様変更、削除
- 破壊的変更: 既存の機能に影響を与える変更
# 依存関係・ライブラリ
- 依存関係: 新しいライブラリの追加、既存ライブラリのバージョンアップ
- 互換性: バージョンアップによる互換性の問題
# セキュリティ・パフォーマンス
- セキュリティ関連: 認証・認可ロジックの変更、セキュリティ設定の変更
- パフォーマンス関連: キャッシュ戦略の変更、クエリの最適化
# その他
- その他: 他のメンバーに影響する箇所がある場合
# 共有方法
プルリクエストの説明欄に変更内容を明記
- 変更の目的と背景
- 影響範囲
- テスト方法
- デプロイ時の注意事項
大きな変更は事前にチームチャットで共有
- 実装前に設計を共有
- フィードバックを求める
破壊的変更は特に注意喚起
- 変更内容を明確に記載
- 移行手順を提供
デプロイ手順や注意事項をドキュメント化
- README や Wiki に記録
- 後から参照できるようにする
# コードの可読性
コードの可読性は、長期的な保守性に直結します。以下の原則を守りましょう:
- コードの読みやすさは賢さや短さより重要: 複雑なコードは理解に時間がかかり、バグの温床になる
- 複雑なロジックにはコメントを追加: アルゴリズムやビジネスロジックの説明を追加
- 自己説明的な変数名・関数名を使用: 名前から意図が分かるコードを書く
- マジックナンバーやマジックストリングは避ける: 定数として定義し、意味を明確化
// 悪い例:意図が分からない
if ($u->a > 18 && $u->s === 'A') {
// ...
}
// 良い例:自己説明的
if ($user->age > ADULT_AGE && $user->status === UserStatus::ACTIVE) {
// ...
}
# PHP コーディング規約
# 基本スタイル
- インデント: スペース 4 つ(タブは使用しない)
- ブレース(波かっこ): すべてのブロックに対して使用(if, for, while など)
elseifを使用:else ifは禁止(PHP の標準に合わせる)- PHP ショートタグ禁止:
<?=や<?は使用せず、<?phpを使用 - 変数名: 小文字でスネークケースを使用(
$user_name,$order_idなど)
# アーキテクチャパターン
- Repository パターン: Controller から Model を直接参照せず、Repository に集約管理
- データアクセスロジックを一元管理
- テストしやすい構造
- ビジネスロジックとデータアクセスを分離
// 悪い例:Controller から Model を直接参照
class UserController {
public function show($id) {
$user = User::find($id); // Model を直接参照
return view('user.show', compact('user'));
}
}
// 良い例:Repository を使用
class UserController {
private $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function show($id) {
$user = $this->userRepository->findById($id);
return view('user.show', compact('user'));
}
}
# 定数の命名
- 定数はすべて大文字で、アンダースコア区切り:
MAX_RETRY_COUNT,DEFAULT_TIMEOUT
// 良い例
define('MAX_LOGIN_ATTEMPTS', 5);
define('SESSION_TIMEOUT', 3600);
const API_BASE_URL = 'https://api.example.com';
# 悪い例と良い例
プレース(波かっこ)を使わない悪い例:
// 悪い例:プレースを使わない、不適切なインデント
$i = 0;
$k = 1;
if( $i === 0 ):
/*
* 長い処理....
*/
if( $k > $i ){
echo $k;
}
endif;
良い例:
// 良い例:プレースを使用、適切なインデント
$counter = 0;
$threshold = 1;
if ($counter === 0) {
/*
* 長い処理....
*/
if ($threshold > $counter) {
echo $threshold;
}
}
# 命名規則
# データベース命名規則
- テーブル名: 小文字スネークケース(複数形推奨)
- 例:
users,order_items,user_profiles
- 例:
- カラム名: 小文字スネークケース
- 例:
user_id,created_at,is_active
- 例:
- インデックス名:
idx_プレフィックス + テーブル名 + カラム名- 例:
idx_users_email,idx_orders_user_id
- 例:
# 変数・定数・パラメータの命名規則
- テーブルカラム名に合わせる: データベースとアプリケーション間の一貫性を保つ
- 意味のある名前を使用: 一時変数除いて3文字以内は非推奨
- 悪い例:
$i,$tmp,$data - 良い例:
$index,$temporary_file,$user_data
- 悪い例:
- クラス名: パスカルケース(
UserController,OrderRepository) - PHP 変数名: スネークケース(
$user_name,$order_id) - JavaScript 変数名: キャメルケース(
userName,orderId) - 定数: 全て大文字のスネークケース(
MAX_RETRY_COUNT,API_BASE_URL) - 関数・メソッド名:
- PHP: スネークケース(
get_user_by_id(),calculate_total()) - JavaScript: キャメルケース(
getUserById(),calculateTotal())
- PHP: スネークケース(
# 命名規則の実践例
// データベース
// テーブル: users
// カラム: id, name, email, created_at
// PHP コード
class UserController {
const MAX_LOGIN_ATTEMPTS = 5;
public function get_user_by_email($user_email) {
$user_data = $this->userRepository->findByEmail($user_email);
return $user_data;
}
}
// JavaScript コード
const MAX_LOGIN_ATTEMPTS = 5;
function getUserByEmail(userEmail) {
const userData = userRepository.findByEmail(userEmail);
return userData;
}
# 命名規則の種類(ケーススタイル)
開発では様々な命名規則(ケーススタイル)が使われます。プロジェクトや言語に応じて適切なスタイルを選択しましょう。
| ケース名 | 例 | 説明 | よく使うパターン |
|---|---|---|---|
| キャメルケース | camelCase | 先頭小文字、接続要素語先頭大文字にする命名規則 | PHP JS などの関数名 |
| パスカルケース | PascalCase | 先頭大文字、接続要素語先頭大文字にする命名規則 | PHP JS などのクラス名 |
| スネークケース | snake_case | アンダーバーで要素語をつなぐ命名規則 | DB カラム名、PHP 変数名 |
| ケバブケース | kebab-case | ハイフンで要素語をつなぐ命名規則 | ファイル名、HTML の class 名 |
- キャメルケースはローワーキャメルケースともいいます
- パスカルケースはアッパーキャメルケースともいいます
# 言語・フレームワーク別の命名規則リファレンス
各言語やフレームワークには公式のコーディング規約があります。参考にしましょう:
- Airbnb JavaScript Style Guide (opens new window)
- Facebook React Style Guide (opens new window)
- HashiCorp Go Style Guide (opens new window)
- Kubernetes Go Style Guide (opens new window)
- Flask Python Style Guide (opens new window)
- Laravel PHP Style Guide (opens new window)
# インデントとフォーマット
# 言語別インデント規則
- PHP: スペース 4 つ
- JavaScript / JSON: スペース 2 つ
- CSS: スペース 2 つ
- HTML: スペース 2 つ
# エディター設定
- ESLint: Microsoft ESLint (opens new window) を使用して JavaScript のコード品質をチェック
- EditorConfig: プロジェクト全体で一貫したフォーマット設定を適用(後述の「エディター設定」セクションを参照)
# インデントの重要性
一貫したインデントは、コードの可読性に大きく影響します。チーム全体で統一されたルールを設定し、自動フォーマッターで強制することが重要です。
# DB マイグレーション
データベースの変更はすべてマイグレーションファイルで管理します。
# 基本原則
- テーブル構造はすべてマイグレーション化する
- マイグレーションファイルは一度実行したら変更しない(新しいマイグレーションで修正)
- 本番環境で実行する前に必ずステージング環境でテスト
# マイグレーションのベストプラクティス
破壊的変更は慎重に
- カラム削除前にデータ移行を実施
- 外部キー制約がある場合は順序を考慮
- ダウンタイムが必要な場合は事前に計画
ロールバック可能なマイグレーション
up()とdown()メソッドを適切に実装- データ損失を伴う変更は特に注意
パフォーマンスを考慮
- 大量データの変更はバッチ処理で実施
- インデックス追加は非同期で実行(可能な場合)
- マイグレーション実行時間を監視
不要なテーブル・カラムの削除
- 不要なテーブルは名前の末尾にアンダーバーつけて時間置いて削除
- 削除前に使用箇所がないか確認
- 削除後はバックアップを保持
# マイグレーション実行時の注意
- 本番環境では必ずバックアップを取得してから実行
- マイグレーション実行中はアプリケーションのデプロイを控える
- 実行ログを確認し、エラーがないかチェック
# コメントを大事にする
適切なコメントは、コードの理解を助け、保守性を大幅に向上させます。ただし、コメントは「なぜ(Why)」を説明するものであり、「何を(What)」を説明するものではありません。
# コメントの基本原則
- 関数毎にコメントで説明する
- 関数の目的、引数、戻り値を明記
- PHPDoc や JSDoc などの標準フォーマットを使用
/**
* ユーザー認証を実行する
*
* @param string $email ユーザーのメールアドレス
* @param string $password パスワード(平文)
* @return array|null 認証成功時はユーザー情報、失敗時は null
* @throws AuthenticationException 認証に失敗した場合
*/
function authenticateUser($email, $password) {
// 実装...
}
- 重要箇所はコメント
- ビジネスロジックの重要な部分
- パフォーマンス最適化を行った箇所
- セキュリティ対策を実装した箇所
- 非自明な実装の理由
// パフォーマンス最適化: 大量データを処理するため、バッチサイズを制限
// 一度に1000件ずつ処理することで、メモリ使用量を抑制
$batchSize = 1000;
for ($i = 0; $i < count($items); $i += $batchSize) {
$batch = array_slice($items, $i, $batchSize);
processBatch($batch);
}
- 不安定箇所や今後変更される予定のある箇所は
TODOをつけるTODO: 今後実装予定の機能FIXME: 修正が必要な箇所HACK: 一時的な回避策NOTE: 重要な注意事項XXX: 危険なコードや注意が必要な箇所
// TODO: キャッシュ機能を追加してパフォーマンスを改善
function getExpensiveData() {
// 実装...
}
// FIXME: タイムゾーンの処理が正しくない可能性がある
function formatDate($timestamp) {
// 実装...
}
// HACK: ライブラリのバグを回避するための一時的な対応
function workaroundLibraryBug() {
// 実装...
}
# コメントのベストプラクティス
- なぜ(Why)を説明する: 何をしているか(What)だけでなく、なぜそうしているかを記述
- 古いコメントを削除: コードと一致しないコメントは削除または更新
- 自明なコメントは避ける: コードから明らかなことはコメント不要
// 悪い例:自明なコメント
$user = getUser(); // ユーザーを取得
// 良い例:なぜそうしているかを説明
// セッションからユーザーIDを取得できない場合、デフォルトユーザーを使用
// これにより、未認証ユーザーでも一部機能を利用可能にする
$user = getUser() ?: getDefaultUser();
- 複雑なロジックには説明を追加: アルゴリズムや複雑な条件分岐には説明を付ける
// 複雑な条件分岐の例
if ($user->isPremium() && $order->total > 10000 && !$user->hasUsedDiscount()) {
// プレミアムユーザーで、注文額が10,000円以上、
// かつ割引未使用の場合のみ、特別割引を適用
$discount = calculateSpecialDiscount($order);
}
# ドキュメント管理
プロジェクトの規模にもよりますが、できればドキュメントをまとめてドキュメントサイトに管理した方がいいです。適切なドキュメント管理により、知識の共有と継承が容易になります。
# ドキュメント管理のメリット
- 検索機能: 必要な情報を素早く見つけられる
- Git 管理で変更履歴確認: ドキュメントの変更履歴を追跡できる
- シンタックスハイライト: コード例が読みやすくなる
- 見出しによる構造化: 情報が整理され、ナビゲーションが容易
# ドキュメント化すべき内容
- API 仕様書: エンドポイント、リクエスト/レスポンス形式
- アーキテクチャ図: システム構成、データフロー
- セットアップ手順: 開発環境の構築方法
- デプロイ手順: 本番環境へのデプロイ方法
- トラブルシューティング: よくある問題と解決方法
- 意思決定の記録(ADR): 技術選定の理由と背景
# エディター設定
.editorconfig
## EditorConfig is awesome: https://EditorConfig.org
## top-most EditorConfig file
root = true
## Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
## Matches multiple files with brace expansion notation
## Set default charset
[*.{js,php}]
charset = utf-8
## 4 space indentation
[*.php]
indent_style = space
indent_size = 4
## Tab indentation (no size specified)
[Makefile]
indent_style = tab
## Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2
## Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
# Git ブランチ管理
# ブランチ戦略
- 開発環境:
develop- 開発中の機能を統合 - 検証環境:
staging- 本番前の最終確認 - 本番環境:
main(またはmaster) - 本番環境にデプロイされるコード
# 機能ブランチ
- 課題があれば課題番号でブランチ切る
- 例:
feature/TICKET-123-user-authentication - 例:
bugfix/TICKET-456-login-error - 例:
hotfix/TICKET-789-security-patch
- 例:
# ブランチ命名規則
feature/: 新機能開発bugfix/: バグ修正hotfix/: 本番環境の緊急修正refactor/: リファクタリングdocs/: ドキュメント更新
# コミットメッセージ
- 明確で説明的なメッセージを書く
- 変更の理由と内容を簡潔に記述
- 関連するチケット番号を含める
良い例:
feat: ユーザー認証機能を追加 [TICKET-123]
fix: ログイン時のエラーハンドリングを修正 [TICKET-456]
refactor: UserRepository のクエリを最適化
悪い例:
update
fix bug
changes
# プルリクエスト
- 小さな単位でプルリクエストを作成(1つの PR で1つの機能/修正)
- 説明欄に変更内容、テスト方法、影響範囲を明記
- レビューが完了してからマージ
- マージ後はブランチを削除(不要になった場合)
# .env ファイル
- 環境変数追加した場合、
.env.exampleに Key を追加 - Key 追加後情報共有
- 本番環境にリリースする前に開発環境、ローカル環境の
.env差分確認 - 機密情報(API キー、パスワード、トークン)は絶対にコミットしない
.envファイルは.gitignoreに必ず含める- 本番環境の
.envは別途安全な方法で管理(シークレット管理ツール推奨)
# セキュリティベストプラクティス
# 入力バリデーション
- すべてのユーザー入力は検証する
- SQL インジェクション対策:プリペアドステートメントを使用
- XSS 対策:出力時にエスケープ処理を実施
- CSRF 対策:トークン検証を実装
- ファイルアップロード:ファイルタイプ、サイズ、拡張子を厳格にチェック
// 悪い例:直接 SQL に埋め込む
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
// 良い例:プリペアドステートメントを使用
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
# 認証・認可
- パスワードはハッシュ化して保存(bcrypt、Argon2 推奨)
- セッション管理は安全に実装(セッションハイジャック対策)
- 権限チェックは各エンドポイントで実施
- ログイン試行回数制限を実装(ブルートフォース攻撃対策)
# 機密情報の取り扱い
- エラーメッセージに機密情報を含めない
- 本番環境ではデバッグモードを無効化
- ログにパスワードやトークンを含めない
- API キーは環境変数で管理
# セキュリティヘッダー
本番環境では以下のセキュリティヘッダーを設定:
X-Frame-Options: DENY- クリックジャッキング対策X-Content-Type-Options: nosniff- MIME タイプスニッフィング対策X-XSS-Protection: 1; mode=block- XSS 対策Strict-Transport-Security- HTTPS 強制Content-Security-Policy- CSP 設定
# エラーハンドリングとログ管理
# エラーハンドリング
- すべてのエラーを適切に処理する
- ユーザーには分かりやすいエラーメッセージを表示
- 開発者向けの詳細情報はログに記録
- 本番環境ではエラー詳細を画面に表示しない
// 悪い例:エラーを無視
$result = file_get_contents($url);
// 良い例:エラーハンドリングを実装
try {
$result = file_get_contents($url);
if ($result === false) {
throw new Exception("Failed to fetch URL");
}
} catch (Exception $e) {
error_log("Error fetching URL: " . $e->getMessage());
// ユーザー向けの適切なエラーメッセージを表示
}
# ログ管理
- 重要な操作は必ずログに記録
- ログレベルを適切に使い分け(DEBUG, INFO, WARNING, ERROR, CRITICAL)
- ログにはタイムスタンプ、ユーザーID、IP アドレスを含める
- ログローテーションを設定(ディスク容量を考慮)
- 本番環境のログは外部サービス(CloudWatch、Datadog など)に送信を検討
// ログ記録の例
error_log(sprintf(
"[%s] [%s] User: %s, Action: %s, IP: %s",
date('Y-m-d H:i:s'),
'INFO',
$userId,
'login_success',
$_SERVER['REMOTE_ADDR']
));
# パフォーマンス最適化
# データベース
- N+1 クエリ問題を回避(Eager Loading を使用)
- 適切なインデックスを設定
- 不要なデータを取得しない(SELECT * を避ける)
- クエリキャッシュを活用
- 大量データの処理はバッチ処理やキューを使用
// 悪い例:N+1 クエリ
foreach ($users as $user) {
$posts = Post::where('user_id', $user->id)->get(); // ループ内でクエリ実行
}
// 良い例:Eager Loading
$users = User::with('posts')->get();
# キャッシュ戦略
- 頻繁にアクセスされるデータはキャッシュする
- キャッシュの有効期限を適切に設定
- キャッシュキーは一意で分かりやすい名前にする
- キャッシュ無効化のタイミングを考慮
# リソース最適化
- 画像は適切なサイズにリサイズ、圧縮
- CSS/JavaScript は minify、結合
- CDN の活用を検討
- 不要なライブラリは削除
# テスト戦略
# テストの種類
- 単体テスト: 個々の関数・メソッドの動作確認
- 統合テスト: 複数のコンポーネントの連携確認
- E2E テスト: ユーザーシナリオに沿った動作確認
# テストのベストプラクティス
- 本番環境にデプロイする前に必ずテストを実行
- カバレッジ目標を設定(80% 以上推奨)
- テストは自動化し、CI/CD パイプラインに組み込む
- テストデータは本番データを使用しない
# テスト環境
- 開発環境、ステージング環境、本番環境を分離
- ステージング環境は本番環境に可能な限り近い構成にする
- データベースのマイグレーションはテスト環境で事前確認
# デプロイメント手順
# デプロイ前チェックリスト
- [ ] すべてのテストが通過している
- [ ] コードレビューが完了している
- [ ] マイグレーションファイルが正しく作成されている
- [ ] 環境変数の追加・変更が適切に反映されている
- [ ] 依存関係の更新が適切に反映されている(composer.json, package.json)
- [ ] ログ出力が適切に設定されている
- [ ] セキュリティチェックが完了している
# デプロイ手順
ブランチ管理
- 機能ブランチ → develop → staging → main の順でマージ
- 各環境で動作確認を実施
マイグレーション実行
- 本番環境にデプロイする前にマイグレーションの内容を確認
- 破壊的変更がある場合はダウンタイムを考慮
- ロールバック手順を事前に準備
デプロイ実行
- デプロイは低トラフィック時間帯を選ぶ(可能な場合)
- デプロイ後は即座に動作確認を実施
- ログを監視してエラーがないか確認
ロールバック準備
- デプロイ前の状態に戻せるよう、バックアップやタグを準備
- ロールバック手順を文書化
# ゼロダウンタイムデプロイ
- ブルー・グリーンデプロイメントを検討
- データベースマイグレーションは後方互換性を保つ
- 新機能はフィーチャーフラグで段階的に有効化
# モニタリングとアラート
# 監視すべき指標
アプリケーション
- レスポンスタイム
- エラー率
- スループット(リクエスト数/秒)
インフラストラクチャ
- CPU 使用率
- メモリ使用率
- ディスク使用率
- ネットワークトラフィック
データベース
- クエリ実行時間
- 接続数
- スロークエリ
# アラート設定
- エラー率が閾値を超えた場合
- レスポンスタイムが異常に遅い場合
- リソース使用率が高い場合
- 異常なトラフィックパターンを検出した場合
# ログ監視
- エラーログをリアルタイムで監視
- 異常なアクセスパターンを検出
- セキュリティイベントを記録・通知
# バックアップと災害復旧
# バックアップ戦略
- データベース: 毎日自動バックアップ、最低 7 日分保持
- ファイル: ユーザーアップロードファイルは定期的にバックアップ
- 設定ファイル: バージョン管理システムで管理
# 災害復旧計画
- 復旧時間目標(RTO)と復旧ポイント目標(RPO)を定義
- 定期的にバックアップからの復元テストを実施
- 災害復旧手順を文書化し、チームで共有
# コードレビュー
コードレビューは品質向上と知識共有の重要なプロセスです。
# レビューの観点
- 機能性: 仕様通りに実装されているか
- コード品質: 可読性、保守性、パフォーマンス
- セキュリティ: 脆弱性がないか
- テスト: 適切なテストが書かれているか
- ドキュメント: 必要なコメントやドキュメントがあるか
# レビュー時の注意点
- コードと人を分けて評価する
- 建設的なフィードバックを提供する
- 良い点も認める
- チームのコーディング規約に従っているか確認
詳細は コードレビューガイドライン を参照
# 本番環境特有の注意事項
# デバッグ情報
- 本番環境ではデバッグモードを無効化
- エラーメッセージにスタックトレースを含めない
- 開発用のコメントや
var_dump()を削除
# パフォーマンス
- 本番環境では OPcache を有効化(PHP の場合)
- 静的アセットは CDN から配信
- データベースクエリの最適化を実施
# スケーラビリティ
- 将来的な負荷増加を考慮した設計
- 水平スケーリングが可能なアーキテクチャを検討
- ステートレスな設計を心がける
# 本番環境で重要な原則
本番環境で動作するコードは、開発環境とは異なる責任と要件を持ちます。以下の原則を常に意識して開発を行いましょう。
- 可用性(Availability): システムは常に動作可能であるべき
- 信頼性(Reliability): エラーが発生しても適切に処理されるべき
- セキュリティ(Security): 脆弱性を最小限に抑えるべき
- パフォーマンス(Performance): ユーザー体験を損なわない速度で動作すべき
- 監視可能性(Observability): 問題が発生した際に迅速に特定できるべき
これらの原則は、コードレビューやデプロイ前チェックリストで確認すべき重要な項目です。
# チームコラボレーション
# コミュニケーション
- 大きな変更は事前にチームで共有: 影響範囲が大きい変更は、実装前にチームで相談
- ブロッカーやリスクは早期に報告: 問題を隠さず、早期に共有することで対処時間を確保
- 知識共有のためのドキュメントを積極的に作成: ナレッジベースを構築し、チーム全体のスキル向上を図る
# ドキュメント管理
- API 仕様書を最新に保つ: OpenAPI/Swagger などのツールを活用
- アーキテクチャ図を定期的に更新: システムの変更に合わせて図も更新
- 意思決定の記録(ADR: Architecture Decision Records)を残す: なぜその技術を選んだかを記録し、後から参照できるようにする
# 継続的改善
- 定期的にレトロスペクティブを実施: 改善点を洗い出し、アクションアイテムを設定
- 技術的負債を記録し、計画的に解消: 技術的負債を無視せず、計画的に対処
- チームのコーディング規約を定期的に見直し: プロジェクトの成長に合わせてルールも更新
# よくある間違いと対処法
# 1. マジックナンバーの使用
// 悪い例
if ($user->age > 18) {
// ...
}
// 良い例
define('ADULT_AGE', 18);
if ($user->age > ADULT_AGE) {
// ...
}
# 2. 深いネスト
// 悪い例:3階層以上のネスト
if ($user) {
if ($user->isActive()) {
if ($user->hasPermission()) {
// 処理
}
}
}
// 良い例:早期リターンを使用
if (!$user) {
return;
}
if (!$user->isActive()) {
return;
}
if (!$user->hasPermission()) {
return;
}
// 処理
# 3. グローバル変数の乱用
// 悪い例
$global_config = [];
function setConfig($key, $value) {
global $global_config;
$global_config[$key] = $value;
}
// 良い例:依存性注入を使用
class Config {
private $config = [];
public function set($key, $value) {
$this->config[$key] = $value;
}
}
# 4. エラーハンドリングの不備
// 悪い例:エラーを無視
$result = file_get_contents($url);
// 良い例:適切なエラーハンドリング
try {
$result = file_get_contents($url);
if ($result === false) {
throw new Exception("Failed to fetch URL");
}
} catch (Exception $e) {
error_log("Error fetching URL: " . $e->getMessage());
// ユーザー向けの適切なエラーメッセージを表示
}
# 実装時の注意点
開発におけるコーディングルールと規約について、以下のポイントを押さえる。
# 重要なポイント
- 基本原則の遵守: 変数宣言の位置、関数のコメント、グローバル変数の回避など、基本的な原則を守る
- 命名規則の統一: データベース、変数、関数、クラスなど、一貫した命名規則を適用
- コードの可読性: 適切なインデント、コメント、関数の分割により、読みやすいコードを書く
- セキュリティ: 入力バリデーション、認証・認可、機密情報の取り扱いに注意
- パフォーマンス: N+1 クエリの回避、キャッシュ戦略、リソース最適化
- チーム開発: コミュニケーション、ドキュメント管理、継続的改善
# 次のステップ
- プロジェクトに適したコーディング規約を策定
- 自動フォーマッターと Linter を設定
- コードレビューのプロセスを整備
- 定期的に規約を見直し、改善を続ける
コーディングルールは一度設定して終わりではない。プロジェクトの成長とともに、チームの経験を積み重ねながら、継続的に改善していくことが重要。
# 関連記事
- コードレビューガイドライン - コードレビューの進め方
- Prettier フォーマット設定 - コードフォーマッターの設定方法