ソース内の無意味なコード


34

私は上級コーダーからこの話を聞いたことがあり、自分でその一部を見てきました。無意味なコードを書いているプログラマーのインスタンスがいくつかあるようです。次のようなものが表示されます。

  • 価値のないメソッドまたは関数呼び出し。
  • 個別のクラスファイル、オブジェクト、またはメソッドで行われる冗長チェック。
  • if 常に真と評価されるステートメント。
  • スピンオフし、注目に値しないスレッド。

ほんの数例を挙げます。これは、プログラマーが意図的にコードを混乱させて組織に自分の価値を高めたい、または契約や外部委託の作業の場合に繰り返しビジネスをしたいからだと言われました。

私の質問は。他の誰かがこのようなコードを見ましたか?そのコードが存在した理由は何でしたか?

誰かがこのようなコードを書いた場合、その理由を共有できますか?


4
if (false) {...}ブロックはコードをコメントアウトするのに最適です!</
sarcasm

18
特に一時的なクイックハックがほとんど一時的ではないソフトウェア開発では、愚かさによって十分に説明されている悪意に起因することはありません
ワイルドピーク

1
@ dlras2プロットツイスト:#DEFINE false true :)
Silviu Burcea 14

回答:


17

コーディングの成果を実際よりも複雑に聞こえさせようとする開発者の話を聞きました。誰もこれを認めるのを聞いたことがありませんが、私はあなたの基準を満たすコードが、妨害行為ではなく、急いでまたは悪いやり方で意図的に作成されたのを見ました。不正なコードを囲むコードは、特定の機能が役に立たなくなるポイントに変更されている可能性があります。

実際には、この開発者だけが複雑さを管理できるという結論に達する前に、誰かが実際にこのコードを実際に見る必要があります。ほとんどのマネージャーや他のビジネスマンは、どんな種類のコードも理解しておらず、ポジションを補充したくないため、この結論に至ります。


2
この場合、私はあなたに正しい答えを与えたいと思っています 他にも役に立たないコードの関連する理由があると思いますが、私が見るコードは少数の人々が取り組んでいるプロジェクトにあり、私は元の開発チームの外で最初に取り組んでいます。ショックとa敬の念に加えられた複雑さの例のように思えます。
アリ

18
@Ali:無能によってよりよく説明されているものを悪意に起因することはありません。言い換えれば、コードはおそらく、この種の混乱に進化したのです。なぜなら、実際にそれを見て、実際に何をするのかを見るのに十分な時間を費やす勇気のある人はいなかったからです。これは、残されたすべてが不機嫌になるまで、何度も何度も適用される簡単な修正のように聞こえます。
すぐに

1
@quickly_nowの場合は+1。通常、それが最終的に発生します。誰もが、それが壊れるのを恐れて「機能する」ものに触れることを恐れています(または、天国は禁止しています。実際にコードを改善するためにタスクに時間がかかります!恐ろしいことです!)。そのため、コードは腐敗し、何年も後に最終的に崩壊します。
ウェインモリナ

@Ali、最も意味的で合理的であると思われるコードが、おそらくこれがおもしろい、または自慢していると思うと説明されている場合があります。そして、私とは逆に、他の人のコードを見ることもあります。誰がおかしいのかはわかりませんが、ほとんどの場合、それは経験と好みにかかっています。(ここで客観的に悪いコードについて話していない、ちょうどそのような記述が簡単に投げられることだけ)
ミハイル・マロスタニディス

73

私はこのようなコードを見ていませんが、他の理由で無意味に見える、または無意味なコードを見ました:

  1. 下位互換性。より良い方法を見つけましたが、サードパーティのモジュールがこのAPI /関数を何かに使用している可能性があるため、古い(そして今ではあまり役に立たない)API /関数を保持する必要があります。関数が何も役に立たない場合でも、それがないとコードが壊れる可能性があります。

  2. 防御コーディング。このコードのチェックは、他の場所ですでにチェックされているため、意味がありません。しかし、誰かがこれを別の場所でコードを変更し、チェックを削除または変更して、前提条件と一致しないようにしたらどうでしょうか?

  3. オーガニック成長。大きなプロジェクトでは、長年にわたって多くのものが変化し、以前に使用されていたいくつかのメソッドは使用されなくなりましたが、この特定のメソッドが使用されているかどうかを誰も追跡していないため、誰もそれらを削除することはありません彼らのコードの断片と偶然、彼らはすべてこのメソッドを使用することを止めました。または、かつては意味があったが、アプリケーションは他の場所でリファクタリングされたため、条件は常に真になりましたが、誰もそれを削除することはありませんでした。

  4. 過剰設計。人々は「必要な場合に備えて」いくつかのことをコーディングするかもしれませんが、実際にはそれを必要としません。「オフラインで作業をしなければならない場合に備えてスレッドを作成しましょう」と言っても、誰もオフラインで何もする必要はなく、プログラマはそれを忘れて他のプロジェクト(または別の会社)に移動し、そのコードはそこに残りますなぜ存在するのか、それを安全に削除できるのか誰も知らないからです。

そのため、悪意のある仕事やセキュリティの誤ったアプローチで行われたことは一度もありませんでしたが、ソフトウェア開発の自然な結果として起こることが何度もありました。


22
#3、Organic Growthは、私が仕事で見た役に立たないコードの大部分を説明していると思います。しかし、これら4つの理由はすべて、インテリジェントプログラマーを想定しています。役に立たないコードは、何が起こる必要があるのか​​、何が必要でないのかを理解せず、純粋に(種類の)動作を変更することを恐れて多くのコードを残すことに由来します。
ブルースエディガー

2
私のプロジェクトで4番を見ました:多くの場合、会社内でより多くの力を得るために意図的に行われるのではなく、必要ではなくても、より一般的なソリューションを常に作成しようとする人々がいます。#2に関しては、私があなたが説明したまさにその理由で私自身をたくさん使っています:私見では、最小の関数やメソッドでさえ、残りのコードがどのように機能するか、または変化するかについて仮定をしてはいけません。代わりに、私のコードは単純なパターンに従います:「入力OKならば、それ以外はエラーを出力します」。これは、依存関係を最小限に抑えるという一般的な設計原則に従います。
ジョルジオ

3
あなたも忘れました:悪い開発者。コードを書いている人はそうすべきではなく、多くの店には良いレビュープロセスが存在しません。
ジョー

20

私の質問は。他の誰かがこのようなコードを見ましたか?そのコードが存在した理由は何でしたか?

1)はい。

2)私が見たケースでは、私はそれをいろいろと書きました:

  • プログラマーの経験不足
  • プログラマーが修正しようとしている特に複雑な、および/または不十分に実行された設計を理解していない
  • (たとえば)リファクタリングの途中で中断されるプログラマ。
  • 不注意

今、私はそれについて慈善活動をしているかもしれませんが、私の一般的なアプローチは、指を指し、質の悪いことを続けるよりも、これらのことについて寛容/非対立的である方が良いということです。明らかに、物事は十分に悪くなり、何かをしなければならないかもしれませんが、通常、正しい方向への穏やかな微調整で十分です。

もちろん、品質/間違いが「ビジネス」に深刻な影響を与える場合、そのような自由放任的なアプローチを取ることはできません。しかし、そのような状況では、包括的なテスト手順と組み合わせて、すべての義務的かつ勤勉なコードレビューが必要です。


私の経験では、人々は自分の標準を傷つけるので、品質の悪いコード(少なくとも部分的に)について「きつい」傾向があります。完全に(個人的に)努力することは非常にうまくいきますが、個人の基準を他の人に投影するのは少し不合理です。物事の音によって(例の性質から)、これがあなたがしていることです。

IMO、これは生産的ではなく、同僚との良好な仕事上の関係を助長しません。


+1応答を入力していたところ、私が言及しようとしていたすべての理由がほとんどリストされていることがわかりました。
カナダの

慈善のために+1。指を指すことなく誰かの間違いを修正すると、同僚はあなたの技術的スキルと人的スキルの両方を尊重します。安っぽいコードを書いた著者にハランゲと同僚はあなたのアプローチに腹を立て、あなたの能力を割り引くでしょう。
カレブ

13

多くの場合、これらはすべてプロジェクトの経年変化の症状です。

 1.価値のないメソッドまたは関数呼び出し。いくつかのコードが単にそのまま残される場合がたくさんあります(おそらく、非推奨の大きな警告がありますが、ほとんどの言語にはその警告がないため、常に従わない...)真の目的であり、問​​題のある行が削除された場合に何が起こるか誰も知りませんでした。

私はこれをdailywtfから覚えているようです:

@deprecated // he might have been crazy enough to use reflection...
boolean getTrue() {
    return false; 
}

 2.個別のクラスファイル、オブジェクト、またはメソッドで行われる冗長チェック。コミュニケーションの層も不完全です(Mythical Man Monthを読んだことがありますか?そうでない場合は、コンピューターで何をしていますか?Go!読んでください!)。多くの場合、ある人が何かに取り組んでからプロジェクトを去り、次の人が奇妙なバグを見つけて、あちこちに余分なチェックを投げてそれを排除しようとします。バグが削除されても、チェックは問題ではありません。壊れていない場合は修正しないでください。

 3.常にtrueと評価されるifステートメント。ああ、私はこれをやった。一度プロジェクトを取得しましたが、おそらく10〜15個のif / elseブロックのシリーズがありました。動作を変更するにtrue||は、最初のブロックに単にa を配置します。数か月(数年?)後になって戻ってきて、「ああ、このコードは破壊されたはずだったが、破壊されなかった」と言ったのです。

 4.スピンオフし、何の注目もしないスレッド。私は次のような一連の思考を想像できます。

  1. 知っている!これら2つの問題を非同期に処理できます!スレッドfooとbarを作成します。
  2. (2か月後)ええと、ご存知のように、barの機能はfooの方が少し優れています。いくつか移動します。
  3. (1年後)ご存知のように、この他の要素をbarからfooに入れるのは理にかなっています。
  4. (多く、何年も後)「ねえ、このbarスレッドは何もしているようには見えません。削除できますか?」「いや、それは何年も何年もありました...」

5
「ベターではない、それは何年もそこにあった...」の+1-これは何度も起こります。結果への恐怖のために削除することへの恐怖(「何かを壊していないことをどのようにテストするのか」-特に単体テストがない場合)。
すぐに

11

私はもう少し楽観主義者です。あなたが記述したことは、コードが不注意にリファクタリングされたときにしばしば起こると思います。


13
難しいですが、愚かによって説明できることを悪意に起因することはありません。
ブルースエディガー

8

昔の仲間は私が、コンサルタントが彼らが作成したコードの行数で支払いをしたときのことを話した。そして、彼らは驚くほど長く巻き込まれた構造を使用して利益最大化しました。

今日、私はいつも、その男が仕事をしている間にまだ言語学んでいると思います。そして彼は急いでいます。


顔をいじめるために鼻を切ることについて話してください。もう一度コードを見る必要がなければ大丈夫だと思います。
JeffO

6

ほとんどの答えは、次の2つの単純な事実に要約されます。
[1]コード​​はコードの履歴を反映し、
[2]コードはコードの予想される将来を反映します。

現在の仕様を考慮すると、現在のアプリケーション環境では価値のない機能を記述しましたが、将来必要になる可能性があります。

AT PRESENTでは常にtrueと評価されるifステートメントを書きました。しかし、おそらく過去には間違っている可能性があります。

冗長なチェックについては、ちょっと、他のコードは信用していません。自分のコードも信用していません。モジュールがNが1または2または3であることに依存している場合、それを確実に確認し、そうでない場合は情報に基づいてクラッシュします。モジュールAがねじ込んだため、モジュールBが爆発するのは違法です。モジュールBがモジュールAが台無しになったと文句を言うのは非常に合法です。そして、来月、そのパラメータはまだ書かれていないモジュールCから来ている可能性があることを覚えておいてください。


1
私はその悪いコーディングを呼び出します。あなたは将来それが必要になると期待していますが、それはめったに起こりません。ヤグニ。常に真と評価されるifを書くことは無駄な努力であり、最初からまったく異なる機能を追加しなければならない人を混乱させます。来月に来るパラメータは、来月が追加されるまで待つことができます。コードを乱雑にするのは無意味です。
アンディ

1
if(language = 'en'またはlanguage = th ')-来月は中国語を試すかもしれませんか?if(!isset($ TITLE))-すべてのモジュールは$ TITLEを設定するようにサポートされていますが、誰かが間違った綴りをするかもしれません。if(file_exists($ TARGET))-良いコードは既にファイルを作成していますが、システムエラーが発生し、作成されなかった可能性があります。私の標準PHP / MySQLインターフェイスコードは、まだエラーを検出したことがないにもかかわらず、常にエラーをチェックします。
アンディキャンフィールド

3

私はこれを数回見ました。実際、昨日、ボスのコードのいくつかを新しいアプリにマージする必要がありました。彼の場合、それは単にスキルと理解の一般的な不足と、彼が彼が非常に熟練した開発者であると考えるという信念にかかっています。

「価値のないメソッドまたは関数呼び出し」また、「常にtrueと評価されるifステートメント」は、彼のコードの大きな問題です。


3

多くの人がこれらの問題を抱えているコードをてきましたが、同じことを書くことにfする人はほとんどいないと思います。おそらく、あなたが見ているのは蓄積されたソフトウェアの腐敗です-誰かが何かを追加しますが、実際には機能しません。場所; その後、誰かが問題レポートを取得し、問題の特定のインスタンスに対してさらに多くの装甲を追加します。別の人がより一般的なチェックを追加し、以前に追加されたより具体的な症状などに対処した古いコードの一部を削除するのを忘れています。

次に、コードのクリーンアップの問題があります。デッドコードのように見えるものを削除する特別なインセンティブありません。欠陥があると、システムが壊れてしまいます。


2
  • 価値のないメソッドまたは関数呼び出し。

必ずしも悪いわけではありません。基本クラスのメソッドは、多くの場合、サブクラスのオーバーライドポイントとなる空のメソッドを呼び出します。例:Cocoa TouchのUIViewには-didAddSubview:、デフォルトバージョンでは何もしないと文書化されているメソッドがあります。UIViewの-addSubview:メソッドは-didAddSubview:、サブクラスがそれを実装して何かを行うことがあるため、何もしなくても呼び出す必要があります。もちろん、何もしないメソッドとその理由は文書化する必要があります。

歴史的な理由で空のまたは役に立たない関数/メソッドが明らかに存在する場合は、削除する必要があります。よくわからない場合は、ソースコードリポジトリ内の以前のバージョンのコードを見てください。

  • 個別のクラスファイル、オブジェクト、またはメソッドで行われる冗長チェック。

コンテキストがなくても大丈夫かどうかはわかりません。同じ理由でチェックが明確に行われる場合、特に両方のチェックで同じアクションが実行される場合、責任の明確な分離がなく、リファクタリングが必要になることがあります。両方のチェックの結果のアクションが同じでない場合、条件が同じであっても、おそらく2つのチェックが異なる理由で実行されており、おそらく大丈夫です。

  • 常にtrueと評価されるifステートメント。

次の間に大きな違いがあります。

if (1) {
    // ...
}

そして:

if (foo() == true) {
    // ...
}

どこでfoo()常に戻るtrue

最初のケースは、人々がデバッグしているときによく起こります。を使用しif (0) {...て、バグを切り分けようとしているときにコードのチャンクを一時的に削除し、次にを変更し01そのコードを復元するのは簡単です。ifあなたはもちろん、終わったら削除する必要がありますが、それはそのステップを忘れるために、またはあなたはいくつかの場所でそれをやった場合は、1つまたは2を欠場するのは簡単です。(後で検索できるコメントでこのような条件を識別することをお勧めします。)唯一の害は、将来発生する可能性のある混乱です。コンパイラがコンパイル時に条件の値を決定できる場合、それは完全に削除されます。

2番目のケースは許容可能です。によって表される条件をfoo()コード内の複数の場所からテストする必要がある場合、たった今foo()常に真実であったとしても、それを別の関数またはメソッドに分解することが正しいことです。foo()最終的にを返す可能性がある場合false、メソッドまたは関数でその条件を分離することは、コードがその条件に依存するすべての場所を識別する1つの方法です。ただし、これを行うと、foo() == false条件がテストされずに後で問題が発生する可能性があるというリスクが生じます。解決策は、falseケースを明示的にテストする単体テストを必ず追加することです。

  • スピンオフし、注目に値しないスレッド。

これは、歴史の産物であり、コードのレビュー中またはソフトウェアの定期的なプロファイリングによって特定できるもののように聞こえます。意図的に作成できると思います、誰かが実際にそれを意図的に行うと想像するのは大変です。


1

それは起こります。かなり頻繁に実際に。

時々、これらのコーディングの行き止まりは、より効率的/近代的/高速の高速道路がそれらの周りに設置されたときに荒廃した古い山羊のようなものです。

他の場合(そしておそらく私はこれに罪を犯します)、それらは説明されているが未確認の機能/機能のセットが要求されたときにソフトウェアを拡張するための基盤です。(「ボルトオン」を予定している後の作業のためにハンドルなどを提供する初期ビルドに少し作業を入れると、人生が楽になり、それが起こったとき、またはそれ以上の作業がなければ難しい/面倒になることがあります最終的に。)

そして、それの多くは、古い「壊れていないなら、合わない」に直接起因しています。理解できないコードや未使用のコードを引き裂くと、「The Butterfly Effect」のプログラミングバージョンが発生することがあります。それは一度か二度も起こりました。


1

グローバルブール値をtrueに設定し、コードの後半でif(bool)を設定し、実行時にifステートメントにブレークポイントを設定して、ブール値を切り替えてテストすることがあります。


0

私はif true文を「無意味なコード」として無差別に分類することに反対します。

を使用する正当なケースがあります if (1) { ... }Cコードでブロック変数定義を関数の先頭に置くことを要求するC標準との互換性が必要、またはローカル変数をできるだけローカルに定義する場合です。

switch (i) {
    case 23:
        if (1) {
            /* I can declare a local var here! */
        }
        break;
}

5
「if(1)」の必要はありません、なぜブロックを持たないのですか?
FigBug

3
C / C ++とC#の両方、およびJava(および他の多くの同様の言語)が匿名ステートメントブロックを許可していることは確かです。ifwhileまたは同様の構成は必要ありません。非常にクリーンである可能性は低いですが、言語仕様に従って確実に許可されます。
CVn

0

私の教授は、ある日、以前の雇用主が完了した行数に基づいて支払うという話を私たちに関連付けました。そのため、呼び出されなかった数十個の関数を書いた。無意味なコードを書く大きな理由のようです。


0

@Andyが述べたように、私が見た大きなコンポーネントはYAGNIを壊しています。

誰かが、多くの要素が必要とするかもしれないものの代わりに、すべての要素がどうなるかについての仮定から始まります。これは、「is a」の混乱です「has a」の関係の。

この混乱は、継承の厳格な構造につながり、実際には呼び出されないため実装されないままにされるメソッドであり、一部を微調整する必要があるロジックを繰り返し、ビジネスモデルに合わない一般的に奇妙なワークフローにすぎません。

ここにいる他の多くの人と同じように、これは悪意を持って行われたのではなく、優れたデザインに関する知識の欠如と、他の人にそのように見せようとする試みからです。おもしろいことに、少なくとも彼らのコードが過度に設計されたアドナジウムにならないため、知識の乏しい開発者はこの点でよりうまくいくようです。(KISS原則

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.