汚いコードとは、低品質なソースコードを指すスラングです。読みにくく、構造が悪く、保守が困難です。Stripeのレポート(2022)によると、開発者は作業時間の最大40%を、質の悪いコードの読み解きに費やしています。ロシア語圏のコミュニティでは、この用語が非常に広く使われており、govnokod.ruという特化サイトまで存在し、開発者が特に顕著な事例を公開しています。
主なポイント
汚いコードとは、最低限の品質基準を満たしていないコードに対する主観的ではあるが一般的に受け入れられている特徴づけです。Robert Martinは彼の著書『Clean Code』(2008年)の中で、質の悪いコードを「何をするのかの理解を妨げるコード」と定義しています。汚いコードは文法的に正しく、動作することさえありますが、その保守はチームにとって悪夢となります。
汚いコードという用語は、特にロシア語圏のコミュニティで広く使われています。英語では、スパゲッティコード、ダーティコード、技術的負債コードなど、よりフォーマルな用語が使われます。しかし、「汚いコード」という言葉の感情的なニュアンスは、開発者のこうしたコードに対する態度—苛立ち、嫌悪、そして職業上の侮辱の混ざり合い—をより正確に伝えます。
McKinseyの調査(2023年)によると、技術的負債の高い企業—汚いコードはその主な構成要素です—は、新機能の開発に20~40%多くのリソースを費やしています。コードの品質はビジネス指標に直接影響を与えます。これは比喩ではなく、確認された事実です。
客観的な指標は存在しませんが、実用的な基準はあります。開発者が20行の関数を理解するのに5分以上かかるなら、それは汚いコードです。1行の変更が無関係な3つのモジュールを壊すなら、それは汚いコードです。完全な書き換えなしではテストでカバーできないコードも、汚いコードです。
コピペ(コピーアンドペーストプログラミング)は、最も明白で検出が容易な兆候の1つです。同じコードブロックが最小限の変更で複数箇所に繰り返されている場合、それは単なる汚いコードではなく、将来のバグの原因です。一箇所を修正しても別の箇所を直し忘れるのは、典型的なケースです。
意味のない変数名は古典的です。`a`、`b`、`x`、`data`、`temp`、`tmp`、`result`、`list`、`obj`のような名前の変数は、その目的に関する情報を一切提供しません。コードを読む人は、変数が何を保持しているかを理解するために関数全体を分析する必要があります。Robert Martinはこれを「名前に嘘がある」と呼んでいます。名前は情報を約束するが、それを提供しないのです。
深いネスト—条件分岐、ループ、エラーハンドリングが5段階以上のインデントを持つ構造を作り出す場合です。このようなコードは、横スクロールや全階層の頭の中での追跡なしには読むことが不可能です。これはエラーへの直接の道です。論理演算子を簡単に間違えたり、閉じ括弧を見逃したりします。
| 兆候 | 汚いコードの例 | クリーンなコード |
|---|---|---|
| コピペ | 同じブロックを5回コピー | 関数として抽出 |
| 名前 | `var a = getData()` | `var userList = getData()` |
| ネスト | if/forが6段階 | 早期リターンで2~3段階 |
| 関数 | 300行の関数 | 3~5のメソッドに分割 |
| コメント | `i++ // iをインクリメント` | コメント不要の自己説明的なコード |
デッドコード—どこでも使われていない関数、変数、クラス。これらはコード量を増やし、開発者の注意を散らし、システムの能力について誤った印象を与えます。マジックナンバー—文脈のない数値。Godクラス—単一責任の原則(SOLIDのS)に違反して、すべてを一度に行うクラス。
時間の不足が最も一般的な理由です。締め切りが迫っていると、開発者は速度のために品質を犠牲にします。戦術的には正当化できるかもしれませんが、戦略的には技術的負債を蓄積しています。問題は、「一時的な」汚いコードが後で修正されることはめったにないということです。
コードレビューの欠如が2番目に重要な理由です。コードがピアレビューなしで一人で書かれると、悪いパターンが定着し増殖します。コードレビューは単なる品質管理ではなく、チーム内の知識伝達でもあります。レビューのないプロジェクトは必然的に汚いコードへと堕落します。
開発者のスキル不足やメンターシップの欠如。監督なしで放置されたジュニア開発者は、自然に汚いコードを書きます—それは学習プロセスの一部です。問題は、このコードがレビューやリファクタリングなしで本番環境にリリースされるときに発生します。
「動けばいい」をモットーとするチームでは、汚いコードがはびこります。コーディング標準、テスト要件、レビュープロセスの欠如は、コードの品質が誰の関心事でもない環境を作り出します。そのようなプロジェクトはすぐに「レガシー」—誰も触れたがらないコード—になります。
汚いコードの主な結果は、開発の遅延です。質の悪いコードのパラドックスは、最初のバージョンを素早く書けるが、その後の修正ごとにますます時間がかかることです。コードの品質に対する開発速度のグラフは指数関数的です—ある閾値を超えると、新機能の追加は実質的に不可能になります。
スタッフの離職率は間接的ではありますが深刻な影響です。開発者、特に経験豊富な開発者は、汚いコードで働きたがりません。Stack Overflow Developer Survey 2024によると、開発者の47%が職場を選ぶ際の重要な要素の1つとしてコードベースの品質を挙げています。コードの質が悪いプロジェクトは、優秀な従業員を失います。
セキュリティも汚いコードの犠牲者です。質の悪いコードには、未処理の例外、SQLインジェクション、XSS、メモリリークなど、より多くの脆弱性が含まれています。ユニットテストとコードレビューを伴う品質の高いコードは、本番稼働前にこれらの問題のほとんどを捕捉します。
SonarQubeや同様のツールは、技術的負債を人時または日数で見積もることができます。例えば、コピペに関する500件の警告、マジックナンバーに関する200件、深いネストに関する50件は、30日分の技術的負債の見積もりを示します。これらの数値は、リファクタリングを正当化するために経営陣に示すことができ、また示すべきです。
DRY(Don’t Repeat Yourself)の原則は、最初に実装すべきことです。ロジックの断片はすべて、単一の場所に存在する必要があります。コピペの代わりに—繰り返しコードを別の関数、クラス、またはモジュールに抽出します。マジックナンバーの代わりに—名前付き定数を使います。長い関数の代わりに—いくつかの小さな関数に分割します。
KISS(Keep It Simple, Stupid)の原則は、過度な複雑さから守ります。タスクが10行で解決できるなら、50行書く必要はありません。ループがストリームよりシンプルなら、ループを使います。普通の関数がデコレータより明確なら、関数を書きましょう。シンプルさは、保守しやすいコードの主要な品質です。
ボーイスカウトルール—「コードを見つけた時よりもきれいにしておく」。編集のたびに小さな改善を積み重ねることで、汚いコードは徐々にまともなコードに変わります。変数名を変更する、大きな関数を分割する、テストを追加する—どんな改善も重要です。
// 悪いコード — コピペ、マジックナンバー、貧弱な名前
function calc(a, b, c) {
let x = a * 0.85;
if (b > 1000) { x = x * 0.9; }
let y = c * 0.85;
if (b > 1000) { y = y * 0.9; }
return x + y;
}
// クリーンなコード — 明確な名前、DRY、定数
const DISCOUNT_RATE = 0.85;
const BULK_THRESHOLD = 1000;
const BULK_DISCOUNT = 0.9;
function applyDiscount(amount, quantity) {
let price = amount * DISCOUNT_RATE;
if (quantity > BULK_THRESHOLD) {
price = price * BULK_DISCOUNT;
}
return price;
}
function calculateTotal(items, quantity) {
return items.reduce((sum, item) => {
return sum + applyDiscount(item, quantity);
}, 0);
}
Pythonの典型的な例を見てみましょう。この関数は注文を処理しますが、その方法は悪質です:80行、深いネスト、マジックナンバー、重複。リファクタリング後、コードは読みやすく、テスト可能で、保守しやすくなります。
# 悪いコード — 単一の関数がすべてを行う
def process_order(order):
if order.get("type") == "premium":
if order["amount"] > 100:
discount = 0.8
else:
discount = 0.9
else:
discount = 1.0
total = order["amount"] * discount
return total
# クリーンなコード — 抽出された関数と定数
class OrderProcessor:
PREMIUM_DISCOUNT_HIGH = 0.8
PREMIUM_DISCOUNT_LOW = 0.9
PREMIUM_THRESHOLD = 100
def get_discount(self, order):
if order.type == "premium" and order.amount > self.PREMIUM_THRESHOLD:
return self.PREMIUM_DISCOUNT_HIGH
return self.PREMIUM_DISCOUNT_LOW
def calculate_total(self, order):
return order.amount * self.get_discount(order)
良い関数は一つのことを行い、それを適切に実行します。関数が3つの異なることを行うなら、分割しましょう。関数が20行を超えるなら、おそらく分割できます。関数に2段階以上のインデントがあるなら、リファクタリングが必要です。
静的コード解析ツールは、汚いコードに対する防御の第一線です。ESLint(JavaScript)、Pylint(Python)、SonarQube(多言語対応)、Checkstyle(Java)は、コピペ、マジックナンバー、空のcatchブロック、過度に長い関数、その他何百ものアンチパターンを自動的に検出します。
コードスタイルとフォーマッタは、第二レベルの防御です。Prettier、Black、gofmtはコードを自動的にフォーマットし、スペース、インデント、括弧の問題を排除します。チーム全体で一貫したスタイルを保つことで、誰が書いたかにかかわらずコードが読みやすくなります。フォーマットに関する議論は自動化されるべきです。
コードレビューは3番目で最も重要な防御レベルです。ソリューションのアーキテクチャが間違っている、または開発者が誤ったアプローチを選択したことに気づく人間の代わりに、解析ツールは使えません。効果的なレビューには時間がかかりますが、汚いコードの量を大幅に減らすことでその価値を発揮します。
よくある質問
極めて稀です。プロトタイピングやハッカソンでは、品質よりもスピードが重要ですが、そのようなコードは一時的なものとしてマークし、リファクタリングなしで本番環境に投入すべきではありません。本番環境では、汚いコードの言い訳はありません—今節約した時間は、将来の何倍もの損失となって跳ね返ります。
初心者のコードは経験不足ではあっても、しばしば誠実で、スキルの向上とともに改善されます。汚いコードは、品質に対する意識的または無関心な軽視です。初心者は最適ではないが読みやすいコードを書くことがあります。一方、汚いコードは根本的に読みにくい—作者は他人が理解できるかどうかを気にしていません。
書き直しは最後の手段です。段階的なリファクタリングの方が安全です:モジュールを分離し、テストでカバーし、少しずつ書き換えます。完全な書き直しはリスクが伴います—誰も文書化していないエッジケースの処理を含む、古いコードに蓄積されたビジネスロジックを失う可能性があります。
メトリクスを使いましょう:SonarQubeは技術的負債を時間単位で表示します。古いコードのバグにどれだけの時間が費やされているかを示します。プロジェクトの「クリーン」な部分と「汚い」部分での新機能開発の速度を比較します。ビジネスの言葉に翻訳しましょう:時間はお金であり、汚いコードはお金がかかります。
『Clean Code』(Robert Martin、2008年)は、高品質なプログラミングのバイブルです。命名原則、フォーマット、エラーハンドリング、テスティングをカバーしています。さらに:Steve McConnell著『Code Complete』、Martin Fowler著『Refactoring』、GoF著『デザインパターン』。すべての開発者がこれらの本を読むべきです。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。