公開日:
更新日:
10 min read
エンジニアリングプログラミングの真髄:エンジニアリング哲学と実践

前回の記事「レガシーコードの危険な罠」では、具体的なコードの問題点とその改善方法について解説しました。 本記事では、そのような問題が発生する根本的な原因と、それを防ぐための考え方について深掘りしていきます。
エンジニアリングの基本原則
以下のようなコードが複数のファイルにコピペされているのを見かけることがあります:
$today = "2024-03-31";
$monthbefore = date("Y-m-d", strtotime("-1 month", strtotime($today)));
// 結果:2024-03-03
同じ機能は関数化して再利用化する。 それによって、ロジックが集約されるために、問題があったときは関数を修正すれば、すべての機能に反映されます。
開発現場では、ごくごく当たり前のことです。 これも一つのエンジニアリングです。
え~、関数化して共通化するの?
やだやだ~、面倒くさいよ~。
コピペでいいでしょ?
「急がば回れ」の真理
ここで一つの格言を紹介します。
急がば回れ
確かに、コピペは楽です。 すぐに終わります。 同じ機能はあちこちにコピペしまくればいいのです。 それが後々の問題を生むのです!
(1) 目先の楽を優先して、後のことは考えない。
(2) 最初は面倒だけど、のちのち効率的、つまり楽ができる。
どちらがいいでしょうか?
プロフェッショナルの姿勢
ハッキリ言います。 できるプログラマーは(2)です。 今まで見てきたプログラマーは、私生活はだらしなくて、机の上は汚くて、時間にルーズでも、できる人はプログラムだけはきれいに書きます。
現実は、(1)が多数派です。 これは人間の業です。 (1)の人は、仕事は早くても、後々の問題を生むことが多いです。 (2)の人は、仕事は遅いように思いますが、そうでもありません。 大きなプロジェクトでは共通化による作業効率の向上が、ボディーブローのようにじわじわと効いてくるのです。
実践的な考え方
「3か月前の自分は他人」という真実
プログラミングにおいて、最も重要な真理の一つが「3か月前の自分は他人である」という事実です。 私たちは日々の開発作業の中で、多くの意思決定を行っています。
- なぜこの実装方法を選んだのか
- なぜこの変数名にしたのか
- なぜこの関数の引数をこの順番にしたのか
- なぜこの処理をこの場所に書いたのか
これらの判断の背景にある文脈は、時間の経過とともに急速に失われていきます。 3か月もすれば、当時の判断の詳細な理由を思い出すことは極めて困難になります。
実践的な対策として、以下が重要です。
-
コメントの充実化
/** * 期間の開始日を計算する * * @param string $endDate 計算の基準となる終了日(YYYY-MM-DD形式) * @param int $months 遡る月数 * @return string 開始日(YYYY-MM-DD形式) * * 注意: * - 月末日の処理には特に注意が必要 * - 2024-01-31から1ヶ月前を計算する場合、2024-01-01を返す * - チケット番号:PROJ-2024-456 */ function getPeriodStart($endDate, $months) { // 実装... }
-
変数名の明確化
// 悪い例 $d = "2024-03-31"; // 良い例 $targetDate = "2024-03-31";
-
関数の単一責任の原則
// 悪い例:複数の責任が混在 function processData($data) { // データの検証 // データの変換 // データベースへの保存 // ログの出力 } // 良い例:責任の分離 function validateData($data) {} function transformData($data) {} function saveData($data) {} function logOperation($operation) {}
レガシーコードへの対応
現実的なアプローチ
レガシーコードの改善については、慎重な判断が必要です。 汚くても、読みにくくても、正常に動作しているコードには実績と信頼性があります。
私が経験した例を紹介します。 別のスタッフがテーブルにカラムを追加して、テストを行わずに放置していました。 その結果、いくつかの機能が動作しなくなっていたのです。
スタッフは「本来あるべきカラムが無いから追加した」と説明しました。 その判断自体は正しいのですが、追加後のテストを怠ったことが問題でした。
リファクタリングの判断基準
リファクタリングを行うのは、以下のような明確な理由がある場合に限るべきです:
- 新機能追加のために必要不可欠な場合
- 現在のコードでは保守が著しく困難になっている場合
- 将来の機能追加に大きな支障をきたす可能性が高い場合
現実的な対応方針
- 動作しているコードは極力触らない
- 必要最小限の改修
- 段階的なアプローチ
- 十分なテスト
技術継承の重要性
先輩から学んだ鉄則
「変数名を1文字でも変えてしまえば、コードが改変されたことになり、テストやり直しです。」
これは私が若い頃、現場の先輩方に徹底的に叩き込まれた内容です。 1文字でもコードを変えたら、テストをし直さなければならない。 この鉄則は、実際の開発現場での痛い経験から生まれた知恵なのです。
経験知の価値と次世代への継承
独学プログラマーの増加に伴う「経験知」の欠落が懸念されます。 プログラミングの技術的な知識は、書籍やオンライン学習で獲得できます。 しかし、実践的なエンジニアリング経験は、実際の開発現場での経験を通じてしか得られないものが多くあります。
先ほど紹介したカラム追加の例は、まさにその典型です。 スタッフは「本来あるべきカラムが無いから追加した」という判断自体は正しかったのですが、 その変更によってSQLが実行時エラーを起こすことになりました。 これは単なる予測の問題ではありません。 もっと本質的な問題があります。
先に述べた「1文字でもコードを変更したら、必ずテストをやり直す」という鉄則。 この基本中の基本が身についていない。 これは、プログラムを書くことへの責任感と覚悟の欠如を示しています。 技術力の問題ではなく、プロフェッショナルとしての姿勢の問題なのです。
コード変更の影響範囲の見極め、テストの必要性の判断、リスク管理の考え方。 これらは机上の学習だけでは本当の意味で理解することが難しい内容です。 些細な変更が大きな問題を引き起こした経験や、本番環境でのトラブル対応など、実際の現場での経験が、真の理解につながるのです。
まとめ
プログラミングは単なる機能実装ではありません。 それは、未来の自分や他の開発者とのコミュニケーションです。 「急がば回れ」という格言が示すように、短期的な効率を追求するのではなく、長期的な保守性を重視することが、結果として最も効率的な開発につながります。
皆さんも、「3か月前の自分は他人である」ということを常に意識して、丁寧なコーディングを心がけましょう。