コードの匂いは古典的です。 においがするのは、編集または改善できる場合が多いためです。 これらの臭いのほとんどは、何かが間違っている可能性があることを示しているだけです。それらはそれ自体を修正する必要はありません…(ただし、調べておく必要があります。) 前 コードの匂い パートI パート II パート III パート IV パート V パート VI パートVII パートVIII パート IX パート X パートXI パート XII パート XIII 第14部 パート XV パート XVI パート XVII パート XVIII パート XIX パートXX 第21部 続けましょう... Code Smell 106 - 生産依存コード 運用環境をチェックする IF を追加しないでください。 TL;DR: 本番環境に関連する条件を追加しないでください 問題 フェイル ファスト原則違反 テスト容易性の欠如 ソリューション 完全に必要な場合は、環境をモデル化し、それら をテストします。 すべて 環境 場合によっては、開発と本番で異なる動作を作成する必要があります。 たとえば、パスワードの強度。 この場合、環境自体ではなく、強度戦略を使用して環境を構成し、戦略をテストする必要があります。 サンプルコード 違う def send_welcome_email(email_address, environment): if ENVIRONMENT_NAME == "production": print(f"Sending welcome email to {email_address} from Bob Builder <bob@builder.com>") else: print("Emails are sent only on production") send_welcome_email("john@doe.com", "development") # Emails are sent only on production send_welcome_email("john@doe.com", "production") # Sending welcome email to john@doe.com from Bob Builder <bob@builder.com> 右 class ProductionEnvironment: FROM_EMAIL = "Bob Builder <bob@builder.com>" class DevelopmentEnvironment: FROM_EMAIL = "Bob Builder Development <bob@builder.com>" # We can unit test environments # and even implement different sending mechanisms def send_welcome_email(email_address, environment): print(f"Sending welcome email to {email_address} from {environment.FROM_EMAIL}") # We can delegate into a fake sender (and possible logger) # and unit test it send_welcome_email("john@doe.com", DevelopmentEnvironment()) # Sending welcome email to john@doe.com from Bob Builder Development <bob@builder.com> send_welcome_email("john@doe.com", ProductionEnvironment()) # Sending welcome email to john@doe.com from Bob Builder <bob@builder.com> 検出 マニュアル [×] これはデザインの匂いです。 空の開発/運用構成を作成し、カスタマイズ可能なポリモーフィック オブジェクトで委任する必要があります。 タグ カップリング 結論 テスト不可能な条件を追加することは避けてください。 ビジネス ルールを委任する構成を作成します。 抽象化、プロトコル、およびインターフェイスを使用し、ハードな階層を避けます。 関係 Code Smell 56 - プリプロセッサ より詳しい情報 煩わしいifを回避する方法 クレジット による写真 Unsplashの Birmingham Museums Trust このツイートは @ にインスパイアされたものです。 Jan Giacomelli ツイッター 複雑さは、技術的な未熟さの表れです。 ATM であろうとパトリオット ミサイルであろうと、使いやすさは優れた設計の製品の真の兆候です。 ダニエル・T・リン ソフトウェアエンジニアリングの名言 Code Smell 107 - 変数の再利用 変数を再利用すると、スコープと境界をたどるのが難しくなります TL;DR: 異なる目的で同じ変数を読み書きしないでください 問題 可読性 隠れた問題 ソリューション 変数を再利用しない スコープを分離する Extract メソッド 環境 スクリプトをプログラミングするときは、変数を再利用するのが一般的です。 これは混乱を招き、デバッグを困難にします。 可能な限り範囲を狭める必要があります。 サンプルコード 違う // print line total double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); // print amount total total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); // variable is reused 右 function printLineTotal() { double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); } function printAmountTotal() { double total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); } 検出 自動 [ ] リンターは解析ツリーを使用して、変数の定義と使用法を見つけることができます。 タグ 可読性 結論 変数名の再利用は避けてください。より具体的で異なる名前を使用してください。 関係 Code Smell 03 - 関数が長すぎる より詳しい情報 リファクタリング 002 - Extract メソッド クレジット による写真 Unsplashの Sigmund 汎用性の前にシンプルさ、再利用の前に使用。 ケブリン・ヘニー ソフトウェアエンジニアリングの名言 Code Smell 108 - 浮動アサーション 2 つの浮動小数点数が同じであると主張するのは非常に難しい問題です TL;DR: float を比較しないでください 問題 間違ったテスト結果 壊れやすいテスト フェイル ファスト原則違反 ソリューション 実際のパフォーマンスの問題がない限り、フロートは避けてください 任意精度の数値を使用する フロートを比較する必要がある場合は、許容範囲と比較してください。 環境 浮動小数点数の比較は、古いコンピューター サイエンスの問題です。 通常の解決策は、しきい値の比較を使用することです。 float をまったく使用せず、無限精度の数値を使用することをお勧めします。 サンプルコード 違う Assert.assertEquals(0.0012f, 0.0012f); // Deprecated Assert.assertTrue(0.0012f == 0.0012f); // Not JUnit - Smell 右 Assert.assertEquals(0.0012f, 0.0014f, 0.0002); // true Assert.assertEquals(0.0012f, 0.0014f, 0.0001); // false // last parameter is the delta threshold Assert.assertEquals(12 / 10000, 12 / 10000); // true Assert.assertEquals(12 / 10000, 14 / 10000); // false 検出 自動 [ ] float のチェックを避けるために、テスト フレームワークに check con を追加できます。 assertEquals() タグ においのテスト 結論 float の比較は常に避けるべきです。 関係 Code Smell 71 - 小数点を装った魔法の浮動小数点数 より詳しい情報 早く失敗する クレジット による写真 Unsplashの Mika Baumeister 神は自然数を作った。他のすべては人間の仕事です。 レオポルド・クロネッカー ソフトウェアエンジニアリングの名言 Code Smell 109 - 自動プロパティ コードの匂いを4つ組み合わせるとどうなる? TL;DR: ゲッターを避け、セッターを避け、メタプログラミングを避ける。行動について考えます。 問題 情報隠蔽違反 可変性 違反 フェイル ファスト原則 プロパティ設定時のコードの重複 ソリューション 自動セッターとゲッターを削除する 環境 セッターとゲッターは、業界の悪い習慣です。 多くの IDE は、このコードの匂いを好みます。 一部の言語では、貧血モデルと DTO を構築するための明示的なサポートが提供されています。 サンプルコード 違う class Person { public string name { get; set; } } 右 class Person { private string name public Person(string personName) { name = personName; //imutable //no getters, no setters } //... more protocol, probably accessing private variable name } 検出 自動 [ ] これは言語機能です。 未熟な言語を避けるか、最悪の慣行を禁止する必要があります。 タグ カプセル化 結論 プロパティを公開する前に、慎重に検討する必要があります。 最初のステップは、プロパティについて考えるのをやめ、行動だけに集中することです。 関係 Code Smell 28 - セッター Code Smell 68 - ゲッター Code Smell 70 - 貧血モデルジェネレーター Code Smell 40 - DTO Code Smell 01 - 貧血モデル より詳しい情報 W3 学校 怠惰 I - メタプログラミング 怠惰 II - コード ウィザード リファクタリング 001 - セッターの削除 ミュータントの邪悪な力 フェイルファスト クレジット による写真 Unsplashの コニー 厳しい締め切りの中で働きながら、片付けに時間をかけることほど難しいことはありません。 ケント・ベック ソフトウェアエンジニアリングの名言 Code Smell 110 - デフォルトのスイッチ デフォルトとは、「まだわかっていないすべて」を意味します。私たちは未来を予見することはできません。 TL;DR: ケースにデフォルト句を追加しないでください。例外に変更します。明示的であること。 問題 カップリング フェイルファスト原則違反 オープンクローズ原則違反 ソリューション if と case をポリモーフィズムに置き換える デフォルト コードを例外に変更する 環境 ケースを使用するときは、通常、失敗しないようにデフォルトのケースを追加します。 失敗は、証拠なしに決定を下すよりも常に優れています。 類も臭いですから避けられます。 ケースやスイッチ サンプルコード 違う switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; default: // if value does not presently match the above values // or future values // the following will be executed doSomethingSpecial(); break; } 右 switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; case value3: case value4: // We currently know these options exist doSomethingSpecial(); break; default: // if value does not match the above values we need to take a decision throw new Exception('Unexpected case ' + value + ' we need to consider it'); break; } 検出 半自動 [x] 例外がない限り、デフォルトの使用について警告するようリンターに指示できます。 タグ フェイルファスト 結論 堅牢なコードを書くことは、証拠なしに決定を下す必要があるという意味ではありません。 関係 Code Smell 36 - Switch/case/elseif/else/if ステートメント より詳しい情報 フェイルファスト クレジット の による写真 Unsplash Joshua Woroniecki 機能を追加するコストは、コーディングにかかる時間だけではありません。コストには、将来の拡張に対する障害の追加も含まれます。コツは、互いに競合しない機能を選択することです。 ジョン・カーマック ソフトウェアエンジニアリングの名言 そして、それは今のところすべてです… 次の記事では、さらに5つのコードの匂いについて説明します!