0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【失敗5例】ハードコーディング解消の始め方5ステップ【最優先は●●●●の設定値!】

0
Posted at

目次

  1. はじめに:この記事で目指すゴール
  2. ハードコーディングって何?なぜ問題なの?
  3. 現場で遭遇する典型的なハードコーディング3パターン
  4. 解消の優先順位:どこから手をつけるべきか
  5. すぐ実践できる3つの解消テクニック
  6. チームで取り組むための具体的アプローチ
  7. よくある失敗パターンと回避策
  8. 予防と習慣化:二度と増やさないために
  9. まとめ:最初の一歩を踏み出そう

はじめに:この記事で目指すゴール

「ハードコーディングは良くない」という話は何度も聞いたことがあるでしょう。でも、実際の現場で「じゃあ明日から何をすればいいの?」と聞かれたら、答えに詰まってしまう人も多いはずです。

この記事は、技術書やQiitaの記事を読んで「理屈はわかった、でも現場でどう始めればいいかわからない」と感じている方に向けて書きました。特にWEB系ベンチャーやスタートアップのLaravel開発現場を想定し、実践的で今日から使える内容に絞っています。

この記事を読み終えた5分後には、あなたのプロジェクトで最初の一歩を踏み出せる状態になります。

私自身、技術力が突出して高いわけではありません。でも、だからこそチームで無理なく続けられる現実的な方法を大切にしています。この記事では、難しい理論ではなく「明日から使える実践知」をお伝えします。


ハードコーディングって何?なぜ問題なの?

ハードコーディングの定義

ハードコーディングとは、本来は設定ファイルや定数として管理すべき値を、プログラムコードの中に直接書き込んでしまうことです。

例えば、こんなコードです。

// ハードコーディングの例
if ($user->age >= 20) {
    // 成人向けコンテンツを表示
}

if ($order->total >= 10000) {
    // 送料無料
}

$apiUrl = 'https://api.example.com/v1/users';

一見すると問題なさそうですが、実はこれが後々大きな問題を引き起こします。

なぜ問題なのか?現場目線で考える

技術的な理由を並べても実感が湧きにくいので、現場で実際に起こる困りごとで説明します。

ケース1:仕様変更で阿鼻叫喚
「成人判定の年齢を18歳に変更してください」と言われたとき、20という数字がコード全体に散らばっていたら、grep検索で全部洗い出して修正する羽目になります。しかも「20」という数字は他の意味でも使われているので、一つひとつ確認が必要です。時間がかかる上に、修正漏れのリスクも高まります。

ケース2:環境ごとの設定変更が地獄
開発環境、ステージング環境、本番環境でAPIのURLが違う場合、コードに直接書いていると環境ごとにコードを書き換える必要が出てきます。これはデプロイミスの温床です。

ケース3:新メンバーが混乱
コードレビューで新しいメンバーから「なぜこの値が10000なんですか?」と聞かれたとき、説明できますか?ハードコーディングされた値は「なぜその値なのか」が不明瞭で、理解とメンテナンスを困難にします。

このように、ハードコーディングはチームの生産性を下げ、バグのリスクを高める原因になります。


##現場で遭遇する典型的なハードコーディング3パターン

まずは敵を知ることから始めましょう。Laravel現場で頻出するハードコーディングのパターンを3つ紹介します。

パターン1:マジックナンバー(意味不明な数値)

// よく見るハードコーディング
if ($user->status === 1) {
    // アクティブユーザーの処理
}

if ($product->category_id === 3) {
    // 食品カテゴリの処理
}

13が何を意味するのか、コードを書いた本人以外には分かりません。数ヶ月後、書いた本人すら忘れます。

パターン2:ビジネスロジックの閾値

// 送料無料の判定
if ($cart->total >= 5000) {
    $shipping = 0;
}

// ポイント付与率
$points = $purchaseAmount * 0.05;

// 在庫アラート
if ($product->stock <= 10) {
    $this->sendAlert();
}

これらの数値はビジネスルールそのものです。キャンペーンで変更したり、ABテストで調整したりする可能性が高いのに、コードに埋め込まれていると変更のたびにデプロイが必要になります。

パターン3:環境依存の設定値

// API接続先
$client = new Client([
    'base_uri' => 'https://api.production.example.com'
]);

// メール送信元
Mail::to($user)->send(new WelcomeMail('support@example.com'));

// ファイル保存先
$path = '/var/www/html/storage/uploads/';

開発環境と本番環境で値が変わるものがコードに直書きされていると、環境切り替えのたびに修正が必要になり、非常に危険です。


##解消の優先順位:どこから手をつけるべきか

「全部のハードコーディングを今すぐ直そう!」と意気込むのは危険です。焦って進めると、かえって混乱を招きます。

ここでは現実的に進められる優先順位を提案します。

【最優先】環境依存の設定値(パターン3)

まず最初に手をつけるべきは、環境によって値が変わる設定です。理由は明確で、デプロイ事故のリスクが最も高いからです。

  • APIエンドポイント
  • データベース接続情報
  • 外部サービスのキー・トークン
  • メール送信元アドレス
  • ファイル保存パス

これらは.envファイルとconfigディレクトリで管理するだけで、すぐに効果が出ます。

【次点】頻繁に変更されるビジネスロジックの閾値(パターン2の一部)

次に狙うべきは、変更頻度が高い値です。

  • キャンペーンで変わる送料無料の金額
  • ポイント付与率
  • 会員ランクの境界値

これらを設定ファイルや定数に移すだけで、デプロイなしで変更できる可能性が広がります。

【段階的に】マジックナンバー(パターン1、パターン2の一部)

最後に取り組むのが、マジックナンバーです。これは影響範囲が広く、一気に変更すると混乱するため、新しく書くコードから徐々に改善していくのが現実的です。

  • ステータスコード
  • カテゴリID
  • その他の固定値

すぐ実践できる3つの解消テクニック

それでは、具体的な解消方法を見ていきましょう。難しいことは一切ありません。

テクニック1:環境設定は.envconfigに集約

Before(ハードコーディング)

$client = new GuzzleHttp\Client([
    'base_uri' => 'https://api.production.example.com',
    'timeout' => 30,
]);

After(改善版)

まず.envファイルに追加します。

API_BASE_URL=https://api.production.example.com
API_TIMEOUT=30

次にconfig/services.php(または新規作成)に設定を定義します。

// config/services.php
return [
    'external_api' => [
        'base_url' => env('API_BASE_URL'),
        'timeout' => env('API_TIMEOUT', 30),
    ],
];

コード内ではconfig()ヘルパーで取得します。

$client = new GuzzleHttp\Client([
    'base_uri' => config('services.external_api.base_url'),
    'timeout' => config('services.external_api.timeout'),
]);

なぜこれで解決するのか?

.envファイルは環境ごとに内容を変えられるので、コードを一切変更せずに開発・本番で異なる設定を使えます。さらに、.env.exampleにサンプルを残しておけば、新メンバーも設定を理解しやすくなります。

テクニック2:定数クラスでマジックナンバーを撲滅

Before(ハードコーディング)

if ($user->status === 1) {
    // アクティブユーザー
}

if ($order->payment_status === 2) {
    // 支払い完了
}

After(改善版)

app/Constantsディレクトリを作成し、定数クラスを配置します。

// app/Constants/UserStatus.php
namespace App\Constants;

class UserStatus
{
    public const INACTIVE = 0;
    public const ACTIVE = 1;
    public const SUSPENDED = 2;
    public const DELETED = 3;
}
// app/Constants/PaymentStatus.php
namespace App\Constants;

class PaymentStatus
{
    public const PENDING = 1;
    public const COMPLETED = 2;
    public const FAILED = 3;
    public const REFUNDED = 4;
}

コードでは定数を使います。

use App\Constants\UserStatus;
use App\Constants\PaymentStatus;

if ($user->status === UserStatus::ACTIVE) {
    // アクティブユーザー
}

if ($order->payment_status === PaymentStatus::COMPLETED) {
    // 支払い完了
}

なぜこれで解決するのか?

数値の意味が一目瞭然になり、typoも防げます。IDEの補完も効くので、開発効率も上がります。さらに、定数を変更するときは一箇所を修正するだけで済みます。

テクニック3:ビジネスルールは設定ファイルに切り出す

Before(ハードコーディング)

// 送料無料判定
if ($cart->total >= 5000) {
    $shipping = 0;
}

// ポイント付与
$points = $purchaseAmount * 0.05;

After(改善版)

config/business.phpを作成します。

// config/business.php
return [
    'shipping' => [
        'free_threshold' => env('SHIPPING_FREE_THRESHOLD', 5000),
    ],
    'points' => [
        'rate' => env('POINTS_RATE', 0.05),
    ],
];

コードでは設定を参照します。

// 送料無料判定
if ($cart->total >= config('business.shipping.free_threshold')) {
    $shipping = 0;
}

// ポイント付与
$points = $purchaseAmount * config('business.points.rate');

なぜこれで解決するのか?

ビジネスルールの変更が設定ファイルの編集だけで済むようになります。将来的にはデータベースや管理画面から変更できるようにも拡張できます。また、値の意味がキー名で明示されるため、可読性も向上します。


チームで取り組むための具体的アプローチ

一人で黙々と改善するだけでは、チーム全体の習慣は変わりません。ここでは、チームで無理なく進めるための現実的なアプローチを紹介します。

ステップ1:小さく始めて成功体験を作る

いきなり大規模リファクタリングに着手するのは危険です。まずは影響範囲の小さい部分で成功体験を積むことが大切です。

おすすめの最初の一歩

  1. 自分が今開発中の機能で、新しく書くコードから実践する
  2. 一つのファイルだけ、一つの機能だけで試してみる
  3. 動作確認をしっかり行い、問題がないことを確認する

例えば、今まさに実装している新機能があるなら、そこで.envconfigを使ってみる。たったこれだけです。

ステップ2:ドキュメント化して共有する

自分が実践したアプローチをチームに共有しましょう。ただし、いきなり「全員これに従ってください」と押し付けるのは逆効果です。

効果的な共有方法

  • プロジェクトのREADMEやWikiに「コーディングガイドライン」として軽く記載する
  • 実際に改善したコードのBefore/AfterをSlackで共有し、「こうすると便利でした」と伝える
  • チームミーティングで5分だけ時間をもらい、簡単に説明する

重要なのは、「これが正解だから従え」ではなく「こうしたら楽だったので共有します」というスタンスです。

ステップ3:コードレビューで優しく指摘する

PRレビューの際、ハードコーディングを見つけたら優しく指摘しましょう。

NGな指摘の仕方

❌「ハードコーディングしないでください」
❌「これは設定ファイルに書くべきです」

OKな指摘の仕方

✅「この値、将来変更する可能性ありますよね?configに移しておくと後で楽かもしれません」
✅「例えばconfig/business.phpにこんな感じで書いておくと、他の人も理解しやすそうです(サンプルコード添付)」

指摘するときは、理由と具体的な代替案をセットで伝えると、相手も納得しやすくなります。

ステップ4:定期的にリファクタリングの時間を確保する

新機能開発ばかりに追われていると、既存コードの改善は後回しになります。理想を言えば、スプリントごとに「リファクタリングタスク」を少しずつ入れることです。

現実的な時間確保の方法

  • 新機能を実装する際、関連する既存コードのハードコーディングを一緒に直す
  • バグ修正のついでに、その周辺のコードも改善する
  • 月に1回「クリーンアップデー」を設けて、チーム全員で小規模リファクタリングをする

無理のない範囲で、少しずつ積み重ねていくことが大切です。

ステップ5:新メンバーのオンボーディングで伝える

新しいメンバーが入ってきたときは、最高の教育機会です。オンボーディング資料に「ハードコーディングを避ける理由とやり方」を入れておきましょう。

オンボーディング資料に含めるべき内容

  • プロジェクトで使っている定数クラスの場所と命名規則
  • .envconfigの使い分け
  • 実際のコード例(Good/Bad両方)

新メンバーは「このチームのやり方を早く覚えたい」と思っているので、素直に吸収してくれます。そして、新メンバーの方が最新のルールを守りやすいという好循環が生まれます。


よくある失敗パターンと回避策

ハードコーディング解消に取り組む際、よく陥りがちな失敗パターンを紹介します。これを知っておくだけで、無駄な回り道を避けられます。

失敗パターン1:過剰な抽象化で逆に複雑化する

よくある失敗例

// やりすぎた例
config('business.rules.cart.shipping.conditions.free.threshold.amount.minimum')

ハードコーディングを恐れるあまり、設定ファイルの階層を深くしすぎて、かえって分かりにくくなるパターンです。

回避策

シンプルに保つことを優先しましょう。

// これで十分
config('business.shipping.free_threshold')

判断基準:「他の人が見て3秒で理解できるか?」

設定のキー名は長すぎても短すぎてもダメです。「意味が分かる最小限の長さ」を心がけましょう。

失敗パターン2:一気に全部変えようとして破綻する

よくある失敗例

「来週までに全ファイルのハードコーディングを撲滅する!」と意気込んで着手したものの、影響範囲が大きすぎてテストが追いつかず、バグを大量に生み出してしまう。

回避策

段階的に進めることが鉄則です。

  1. まずは新規開発コードだけ適用
  2. 次に、触る機会の多いコアな機能から改善
  3. 古くて誰も触らないコードは最後(または放置)

完璧主義は禁物です。「8割改善できればOK」くらいの気持ちで進めましょう。

失敗パターン3:定数や設定の命名がバラバラ

よくある失敗例

// 命名がバラバラ
UserStatus::ACTIVE
ORDER_STATUS_COMPLETED
config('payment_method')
config('PaymentMethods')

命名規則が統一されていないと、どこに何があるのか分からなくなります。

回避策

チームで命名規則を決めておくことが重要です。

推奨の命名規則(一例)

  • 定数クラス:PascalCase(例:UserStatusPaymentStatus
  • 定数名:UPPER_SNAKE_CASE(例:ACTIVECOMPLETED
  • 設定ファイル:snake_case(例:business.phppayment.php
  • 設定キー:snake_case(例:free_thresholdtax_rate

プロジェクトのドキュメントに明記しておくと、新メンバーも迷いません。

失敗パターン4:.envに値を書いてもconfigを経由しない

よくある失敗例

// 直接envを参照してしまう
if ($cart->total >= env('SHIPPING_FREE_THRESHOLD')) {
    $shipping = 0;
}

これは一見問題なさそうですが、キャッシュの問題があります。本番環境でphp artisan config:cacheを実行すると、env()ヘルパーが正しく動作しなくなります。

回避策

必ずconfigファイルを経由させましょう。

// config/business.php
return [
    'shipping' => [
        'free_threshold' => env('SHIPPING_FREE_THRESHOLD', 5000),
    ],
];

// コード内
if ($cart->total >= config('business.shipping.free_threshold')) {
    $shipping = 0;
}

鉄則:コード内ではenv()を使わず、必ずconfig()を使う

失敗パターン5:定数クラスが乱立して管理不能になる

よくある失敗例

app/Constants/UserStatus.php
app/Constants/UserType.php
app/Constants/UserRole.php
app/Constants/UserPermission.php
app/Enums/Status.php
app/Enums/StatusType.php
...

良かれと思って定数クラスを作りすぎて、逆にどこに何があるか分からなくなるパターンです。

回避策

関連する定数はなるべくまとめることを意識しましょう。

// app/Constants/User.php
namespace App\Constants;

class User
{
    // ステータス
    public const STATUS_INACTIVE = 0;
    public const STATUS_ACTIVE = 1;
    public const STATUS_SUSPENDED = 2;

    // タイプ
    public const TYPE_FREE = 1;
    public const TYPE_PREMIUM = 2;
    
    // ロール
    public const ROLE_USER = 'user';
    public const ROLE_ADMIN = 'admin';
}

使うときはUser::STATUS_ACTIVEのように呼び出せば、意味も明確です。


予防と習慣化:二度と増やさないために

ハードコーディングを減らすのも大事ですが、これ以上増やさない仕組みを作ることが最も重要です。

習慣1:コードを書く前に「この値、変わる可能性は?」と自問する

新しくコードを書くとき、数値や文字列を書く前に一瞬立ち止まりましょう。

自問すべき質問

  • この値、将来変更される可能性はあるか?
  • 環境によって値が変わる可能性はあるか?
  • 他の人がこの値の意味を理解できるか?

これを習慣にするだけで、ハードコーディングは激減します。

習慣2:PRテンプレートにチェック項目を追加する

GitHubやGitLabのPRテンプレートに、チェック項目を追加しましょう。

## チェックリスト
- [ ] ハードコーディングしていない(数値、URL、固定文字列など)
- [ ] 環境依存の設定は`.env``config`に記載した
- [ ] マジックナンバーは定数化した

これがあるだけで、PR作成者もレビュアーも意識するようになります。

習慣3:定期的にgrepで洗い出す

月に1回、簡単なgrepコマンドでハードコーディングの兆候をチェックしましょう。

# 疑わしい数値リテラルを探す
grep -r "=== [0-9]" app/

# 疑わしいURL
grep -r "http://" app/
grep -r "https://" app/

# メールアドレスの直書き
grep -r "@" app/ | grep -v "param" | grep -v "return"

完璧なチェックはできませんが、目視で怪しい箇所を拾い上げるきっかけになります。

習慣4:静的解析ツールを導入する

余裕があれば、静的解析ツールを導入すると、自動でハードコーディングを検出できます。

Laravel向けのツール例

  • PHPStan / Larastan:型チェックとコード品質チェック
  • PHP_CodeSniffer:コーディング規約チェック
  • Rector:自動リファクタリング

特にPHPStanは導入が簡単で、マジックナンバーや型の問題を検出してくれます。

composer require --dev phpstan/phpstan
./vendor/bin/phpstan analyse app

最初はエラーが大量に出るかもしれませんが、少しずつレベルを上げていけばOKです。

習慣5:新メンバーからのフィードバックを歓迎する

新しく入ったメンバーほど、「これ、なんでこうなってるんですか?」と素朴な疑問を持ちます。その質問こそ、ハードコーディングや分かりにくいコードの兆候です。

「その疑問、すごくいい視点ですね!一緒に改善しましょう」

このスタンスを持つことで、チーム全体の品質意識が高まります。


まとめ:最初の一歩を踏み出そう

ここまで、Laravel現場でのハードコーディング解消について、実践的な内容を解説してきました。最後に、重要なポイントをおさらいしましょう。

今日から実践できること

1. 新しく書くコードから意識する
いきなり既存コードを全部直そうとせず、まずは今日から書くコードで実践しましょう。

2. 環境設定を.envconfigに移す
最も効果が高く、今すぐできる改善です。APIのURLや外部サービスのキーから始めましょう。

3. マジックナンバーを定数クラスに置き換える
app/Constantsディレクトリを作って、意味のある定数名で管理しましょう。

4. ビジネスルールを設定ファイルに切り出す
頻繁に変わる閾値や係数は、config/business.phpにまとめましょう。

チームで進めるときの心構え

  • 小さく始めて成功体験を積む:一気にやろうとしない
  • 優しく共有する:押し付けではなく、提案として伝える
  • 完璧を目指さない:8割改善できればOK
  • 習慣化する:PRテンプレートやレビューで自然と意識できる仕組みを作る

最後に

ハードコーディングの解消は、技術力の高さを誇示するためのものではありません。チーム全体の開発体験を向上させ、保守性を高め、バグを減らすための現実的な取り組みです。

完璧なコードを目指す必要はありません。今日より少しだけマシな状態にする。その積み重ねが、半年後、1年後に大きな差を生み出します。

あなたがこの記事を読んだ後、最初の一歩を踏み出せることを願っています。

さあ、明日から始めましょう。まずは.envファイルを開くところから。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?