この記事は、保守性を高くするための記事ではなく、保守性が悪いプログラムについて説明した記事です。
私は、業務整理・要件定義などの上流工程から、設計、開発、テスト、運用保守まで、ソフトウェア開発の上流から下流まで一貫して経験してきました。今は、コーディングをする機会はほとんどなくなりましたが、ときどき、他の人が書いたコードを見ることがあります。
プログラムを見たときに、「あぁ・・残念なプログラムだな」と感じることがあります。
そんな、残念で保守性の悪いプログラム、こういうコーディングをすると保守が大変になる例を5つご紹介します。これをしないだけでも、確実にプログラムの保守がしやすくなります。ぜひ、参考にしてください。
ハードコーディングしている
プログラミングでは「ハードコーディングは良くない」と、よく言われます。
なぜ、ハードコーディングが良くないのでしょうか?理由は、プログラムを修正するコストがとても高くつくからです。
例えば、成年か未成年かを判別するために、次のようなコードが書かれているとします。以前は、20歳以上が成年でしたので、次のようなコードになります。
if ( $age >= 20 ) then {
// 成年だった場合の処理
} else {
// 未成年だった場合の処理
}
2022年4月から、成年は18歳以上に変更されました。そのため、次のようにコードを修正します。
if ( $age >= 18 ) then {
// 成年だった場合の処理
} else {
// 未成年だった場合の処理
}
修正する場所が1つだけであれば、ハードコーディングしても問題はありません。
けれど、同じ処理が複数個所にあるとしたら?
その分、ソースコードを修正しなければなりません。修正する箇所が多いほど、時間もかかるし、間違えて修正してしまい新たな「バグ」を生み出すこともあります。
これを避けるためには、定数を定義して使います。例えば、PHPであればこんな感じです。
define("ADULT_AGE", 18); // 定数を定義
if ( $age >= ADULT_AGE ) then {
// 成年
} else {
// 未成年
}
このように定数を定義しておけば、成年の年数が変更になった場合、定数を変更するだけですみます。定数を定義するファイルをまとめておくとより便利です。
ハードコーディングはせずに、定数として定義する癖をつけましょう。
共通処理をまとめていない
共通で使われている処理が、まとめられていないケースも良く目にします。
共通で使われる処理は、オブジェクト指向言語であればクラスに、C言語などであれば関数化すると保守性が良くなります。
こんなプログラムを見たことがあります。
それは、外部システムへ提供するAPIのプログラムでした。
APIなので、リクエストパラメータのチェックをしているのですが、10個のAPIそれぞれでパラメータをチェックしています。中には、まったく同じパラメータもあります。
- データの長さ
- データが空やNULLでないか
- 無効なデータが指定されていないか
こういったパラメータのチェックは、共通化することができます。
共通化しておけば、プログラムの修正は1か所ですみます。あちこちにコードが埋め込まれている場合、その数だけプログラムの修正が必要になり、修正に時間もかかるし、新たなバグを生み出す可能性もあります。理由は、ハードコーディングと同じですね。
複数個所で使われる処理は、共通化できないか検討してみましょう。
命名規則(ネーミングルール)がない
変数や関数など、名前の付け方のルールがないと保守性は悪くなります。
例えば、営業所コードの名前を考えてみましょう。
鈴木さんは、営業所コードを扱う場合、salesCD と書きます。田中さんは、Sales_code。山田さんは、eigyosyo_code。同じ営業所コードですが、大文字・小文字、日本語・英語、キャメルケール・スネークケース・・入り乱れています。
システムをリリースして1年後、組織変更が行われることになりました。営業所コードで判別していた処理の一部が、変更になります。プログラムを改修しなければなりません。
プログラムで営業所コードが使われている箇所を、調査することになりました。
salesCD、Sales_code、eigyosyo_codeで調べて、必要な修正をしましたが、うまく動作しないところがあります。調べてみると、なんと上記3つ以外に、eigyosyo_cd と書かれていた箇所があったのです。
コーディングをする前に、営業所コードの変数の命名規則を決めておくことで、こういったことは回避できます。
例えば、営業所コードは、sales_cd と決めておけば、鈴木さんも、田中さんも、山田さんも sales_cd を使います。sales_cdで統一しておけば調査は簡単だし、何よりプログラムが見やすくなります。
変数や関数の命名規則をつくりましょう。
ログを残さない
ログを残すことも大切です。特にエラーログは、運用・保守のために必ず残してください。
エラーログがないと、システムトラブルが発生したときに、何が原因なのか特定することが難しくなります。
SQLエラーなのか、そもそもRDBに接続できないのか。
認証エラーなのか、データ不整合が発生しているのか。
何が原因でトラブルが発生したのか、調査をする手がかりになるのがログです。
例えば、顧客からシステムが動かないと連絡が入リました。
ログを確認すると、SQLエラーが発生しています。UPDATE分に渡されたデータが、どうやらおかしいようです。データを調べると、そのデータは外部システムから連携されたデータで、データ不整合が発生していました。
ここまで調査ができれば、原因は外部システムにあると切り分けをすることができます。
逆に、ログがなかったら?
調査に時間がかかることは、あきらかですよね。
適切なログを出力しましょう。特にエラーログは大切です。
エラーハンドリングしない
中国とベトナムのオフショア開発に携わったことがあります。どちらもコーディングが早く優秀なのですが、なぜか、エラーハンドリングを面倒くさがる傾向がありました。
エラーハンドリングを適当にすると、どうなると思いますか?
以前、こんなことがありました。
当時、他システム用に認証用APIを提供していました。
そのAPIを利用しているベンダーから、ある日、問い合わせが入りました。
「お客様が正しいID/パスワードを入力しているのに、ログイン認証できない。APIに問題がないか調査をしてほしい」
APIのログを確認すると、そのお客様のアカウントは、パスワードを一定回数以上間違えたためアカウントがロックされていました。ベンダーにアカウントロックがかかっていること、APIでアカウントロックのエラーを返していることを伝えると、驚くべき回答が返ってきました。
そのシステムは、アカウントロックのエラーハンドリングをしていなかったのです。そのため、なぜログイン認証ができないのか、わからなかったようです。
全てのエラーをハンドリングすることは不可能ですが、あらかじめ想定できるエラーは、プログラムで処理をすると、後々こういった目に合わずにすみます。
エラーハンドリングは、面倒くさがらずにやりましょう。
まとめ
保守性が悪くなる、プログラムのポイントを5つご紹介しました。
- ハードコーディングしている
- 共通処理をまとめていない
- 命名規則(ネーミングルール)がない
- ログを残さない
- エラーハンドリングしない
どれも、決して難しいことではありません。それなのに、上記ができていないシステムを見かけることがあります。
その気持ちも、わかります。
1つ1つは難しくはありませんが、どちらかというと面倒くさい作業です。時間がない時などは、ついつい、後回しにしてしまうこともあります。
けれど、この5つのポイントの手を抜くと・・システム運用が始まってからが大変です。
プログラム修正に時間がかかったうえに、新たなバグが発生してしまった。
エラーが発生したけれど、プログラムのどこで、何が原因なのかわからない。
私自身が身をもって、経験してきました。
良いアルゴリズムを考えること、パフォーマンスを上げることもとても大切なことですが、ぜひ、運用・保守も考慮したシステム開発をして頂ければと思います。あなた自身のためにも。
最後までお読み頂き、ありがとうございます。