はじめに
当たり前のことですが、Webサービス開発は「作って終わり」ではありません。
むしろ運用開始後に、追加開発・不具合修正・仕様変更が繰り返し発生します。
そのときに 「コードが読みにくい」「修正したら別の機能が壊れた」 といった問題が多発すると、チームの工数は一気に膨らみます。
つまり、 保守性・可読性を意識した設計・実装 ができるかどうかが、現場で大きな差を生みます。
この記事は、自分自身の学習メモとして「保守性・可読性を意識した開発」を整理したものです。
特に現場でもありがちな Controllerにロジック直書き問題 を題材に、改善の手順をまとめます。
Controller直書きはなぜ危険か?
Laravelを例に考えます。
つい便利だからと、Controllerにそのままビジネスロジックを書いてしまうことがあります。
class OrderController extends Controller {
public function store(Request $request) {
// バリデーション
$validated = $request->validate([
'user_id' => 'required',
'item_id' => 'required',
]);
// 在庫チェック & 注文登録(ビジネスロジック直書き)
$item = Item::find($validated['item_id']);
if ($item->stock <= 0) {
throw new Exception('在庫切れ');
}
$item->stock--;
$item->save();
Order::create($validated);
return response()->json(['message' => 'success']);
}
}
一見すると動きますが、問題は以下です:
- コード量が増え、処理の意図がつかみにくい(可読性低下)
- 他の機能でも在庫チェックが必要になるとコピペが増える(再利用性なし)
- テストしにくく、変更時の影響範囲が広い(保守性低下)
改善ステップ:Service層への切り出し
そこで、ビジネスロジックを Serviceクラス に切り出します。
// App/Services/OrderService.php
namespace App\Services;
use App\Models\Item;
use App\Models\Order;
use Exception;
class OrderService {
public function createOrder(array $data) {
$item = Item::find($data['item_id']);
if ($item->stock <= 0) {
throw new Exception('在庫切れ');
}
$item->decrement('stock');
return Order::create($data);
}
}
Controller側は「依頼」と「返却」に集中できます。
class OrderController extends Controller {
protected $orderService;
public function __construct(OrderService $orderService) {
$this->orderService = $orderService;
}
public function store(Request $request) {
$validated = $request->validate([
'user_id' => 'required',
'item_id' => 'required',
]);
$this->orderService->createOrder($validated);
return response()->json(['message' => 'success']);
}
}
結果として:
- Controllerはリクエスト処理に専念 → 読みやすい
- 在庫チェック処理は共通化 → 再利用可能
- Service単位でテスト可能 → 変更に強い
可読性・保守性を高めるポイント3つ
実務や学習で意識しているポイントを3つ紹介します。
1. 共通処理は一元化する
似たような処理はServiceやヘルパーに集約し、重複をなくす。
- 修正時に1箇所だけ直せばよい
- デグレ(副作用バグ)が起きにくい
2. コメントは“補足”として残す
コードだけで伝わらない部分に、意図や理由をコメントで残す。
// 在庫ゼロでも注文を許可する特別仕様(キャンペーン対応)
if ($item->stock <= 0 && $campaignActive) {
...
}
→ 数ヶ月後の自分や、別の開発者が理解しやすくなる。
3. 冗長な処理をリファクタリング
- ネストが深い
if文を「ガード節」で早期returnする - 無駄な
forループを削減する
// 改善前
if ($user) {
if ($user->isActive()) {
return true;
}
}
return false;
// 改善後(ガード節)
if (!$user || !$user->isActive()) {
return false;
}
return true;
読みやすさが段違いになり、レビューもしやすくなる。
まとめ
- Controller直書きは現場あるあるだが、保守性・可読性を損なう
- Service層に切り出すことで、コードが読みやすく、変更にも強くなる
- 共通化・コメント・リファクタリングで長期運用に耐えるコードに近づく
今後も学んだ改善を記事に残し、「任せても安心なエンジニア」 を目指していきます。