「変更しない」とマークされたコードをリファクタリングする必要がありますか?


148

私はかなり大きなコードベースを扱っており、既存のコードをリファクタリングするために数ヶ月を与えられました。リファクタリングプロセスが必要なのは、すぐに製品に多くの新しい機能を追加する必要があり、現在のところ、他の機能を壊すことなく機能を追加することができなくなっているためです。要するに:私たちの多くが彼らのキャリアで見た、乱雑で巨大なバグのあるコード。

リファクタリング中に、時々、クラス、メソッド、または次のようなコメントのあるコード行に遭遇します

モジュールAに何かをする時間を与えるためのタイムアウトセット。このようにタイミングが合わないと、壊れてしまいます。

または

これを変更しないでください。私を信じて、あなたは物事を壊すでしょう。

または

私はsetTimeoutを使用することは良い習慣ではないことを知っていますが、この場合は使用しなければなりません

私の質問は、著者からのそのような警告に遭遇したときにコードをリファクタリングする必要がありますか(いいえ、著者と連絡を取ることができません)?


157
おめでとうございます!これでコードの作成者になりました。

12
行うべきことと実際に行うことの両方を理解するまで、修正することはできません(変更の完全な結果を理解するには、後者を知る必要があります)。ジョブ#1をリファクタリングする必要があります。そうしないと、変更ごとに事態が悪化します。あなたが尋ねるべき質問は、その方法です。その質問には、言語とプラットフォームの依存関係がかなりあります。例:stackoverflow.com/questions/3099794/finding-threading-bugs
sdenham

14
@sdenhamのコメントのフォローアップ:コードベースを実行する自動化された単体テストをまだ持っていない場合は、明確な目標を持たない「リファクタリングウィッチハント」に時間を費やすのではなく、そのような単体テストの作成に時間をかけることをお勧めします念頭に置いて。コードベースを徹底的に実行する単体テストのスイートを作成したら、コードの一部を書き換える必要がある場合に、コードが引き続き機能するかどうかを客観的に知ることができます。幸運を祈ります。
ボブジャービス

17
作成者が非常に妄想的で、誰かがその近くで息を吸うとコードが壊れる場合、おそらく既に壊れており、未定義の動作はたまたま彼らが望むように動作するようになります。特に最初の1つは、競合状態があり、ほとんどの場合うまくいくようです。sdenhamが正しい。それが何をすべきかを理解し、それが実際に何をするかを仮定しないでください。
レイ

7
@Ethanそれほど簡単ではないかもしれません。コードを変更すると、すぐには分からない形でコードが壊れる場合があります。この現在のリファクタリングが原因である可能性があることを忘れた後、それが壊れる場合があるので、あなたが持っているのは謎の原因を持つ「新しい」バグだけです。これは、タイミング関連の場合に特に発生します。
ポールブリンクリー

回答:


225

新機能の開発が行われるときに、コードベースのどの部分が詳細に変更されるかを正確知ることなく、「念のため」にリファクタリングしているようです。そうでなければ、もろいモジュールをリファクタリングする必要が本当にあるのか、それともそのままにしておくことができるのかがわかります。

率直に言うと、これは運命のリファクタリング戦略だと思います。あなたは会社の時間とお金を投資して、それが本当に利益をもたらすかどうかを誰も知らないものに投資しており、作業コードにバグを導入することで事態を悪化させようとしています。

より良い戦略は次のとおりです。時間をかけて

  • リスクのあるモジュールに自動テスト(おそらく単体テストではなく、統合テスト)を追加します。特に、あなたが言及したこれらの脆弱なモジュールでは、そこで何かを変更する前に完全なテストスイートが必要になります。

  • テストを実施するために必要なビットのみをリファクタリングします。必要な変更を最小限に抑えるようにしてください。唯一の例外は、テストでバグが明らかになった場合-すぐにバグを修正します(そして、安全に行う必要がある程度にリファクタリングします)。

  • 同僚に「ボーイスカウトの原則」(別名「日和見的リファクタリング」)を教えるため、チームが新しい機能の追加(またはバグの修正)を開始するときに、変更する必要があるコードベースの部分を正確に改善およびリファクタリングする必要があります。それ以上でもそれ以上でもない。

  • チーム向けに「レガシーコードを効果的に使用する」というFeatherの本のコピーを入手してください。

したがって、(新機能の開発のため、またはステップ1で追加したテストがバグを明らかにするために)脆弱なモジュールを変更してリファクタリングする必要があることが確実にわかったとき、あなたとあなたのチームは準備ができていますモジュールをリファクタリングし、これらの警告コメントをほぼ安全に無視します。

いくつかのコメントへの回答として:公平に言うと、既存の製品のモジュールが定期的に問題の原因であると疑われる場合、特に「触れない」とマークされているモジュールは、すべてに同意します君は。そのプロセスでレビュー、デバッグし、おそらくリファクタリングする必要があります(私が言及したテストをサポートし、必ずしもその順序である必要はありません)。バグは変更を強力に正当化するものであり、多くの場合、新機能よりも強力です。ただし、これはケースバイケースの決定です。「触れない」とマークされたモジュール内の何かを変更するのが本当に面倒な価値があるかどうか、非常に慎重にチェックする必要があります。


70
私は下票したいと思っていますが、私は控えます。複数のプロジェクトでこの考え方がずっと悪い製品につながるのを見てきました。障害が最終的に発生すると、それらはしばしば壊滅的であり、定着のために修正がはるかに困難になります。私は定期的にスラッジを修正しますが、最悪の場合、修正するのと同じくらい多くの問題を引き起こすか、既知の問題を残さないようです。それは全体的に大きなプラスです。そして、コードは将来の開発に向いています。時間内に1回のステッチで9個節約できますが、無視された問題は悪化する可能性があります。
アーロン

98
「モジュールAに何か時間を与えるためにタイムアウトが設定されています。このようにタイミングが合わないと、壊れる」というコメントが付いたコードには、すでにバグがあります。バグがヒットしていないのは引き分けの運だけです。
17年

10
@ 17of26:必ずしもバグではありません。サードパーティのライブラリを使用しているとき、目標を達成するためにあらゆる種類の「優雅な」譲歩を強いられます。
-whatsisname

30
@ 17of26:関係するモジュールにバグがあると疑われる場合、リファクタリングの前にテストを追加することがさらに重要です。そして、それらのテストでバグが明らかになったら、そのモジュールを変更する必要があるため、すぐにリファクタリングするための正当化が必要になります。テストでバグが明らかにならない場合は、コードをそのままにしておくことをお勧めします。
Doc Brown

17
@Aaron:テストを追加したり、ボーイスカウトの原則に従うことで製品の品質が低下すると思う理由がわかりません。
Doc Brown

142

はい、他の機能を追加する前にコードをリファクタリングする必要があります。

このようなコメントの問題は、コードベースが実行されている環境の特定の状況に依存することです。特定の時点でプログラムされたタイムアウトは、プログラムされたときに本当に必要だった可能性があります。

ただし、この方程式を変更する可能性のあるものはいくつもあります。ハードウェアの変更、OSの変更、別のシステムコンポーネントの無関係な変更、一般的なデータボリュームの変更などです。現在でもそれがまだ必要であるか、それでも十分であるという保証はありません(保護するはずだったものの完全性が長い間壊れていたかもしれません-あなたが気付かないかもしれない適切な回帰テストなしで)。これが、別のコンポーネントを終了させるために固定遅延をプログラミングすることがほとんどの場合正しくなく、誤ってのみ機能する理由です。

あなたの場合、あなたは元の状況を知らず、また元の著者に尋ねることもできません。(おそらく、適切な回帰/統合テストも行われていないか、単に先に進んで、テストで何かを壊したかどうかを伝えることができます。)

これは、注意を払って何も変更しないという議論のように見えるかもしれません。しかし、とにかく大きな変化が必要になるとあなたは言うので、この場所で達成されていた微妙なバランスを混乱させる危険性はすでにそこにあります。あなたがしている唯一のものがリファクタリングであるとき、リンゴカートを動揺させることははるかに良いです、そして、もし何かが壊れたらそれを引き起こしたリファクタリングであることを確実にしてください確かに。


46
ここで最高の答え。あまりにも悪い、それは負け犬です。上記の受け入れられた答えは良いアドバイスではありません、特に「不運な」ことに重点を置いています。昨年、私はこれまでに見た中で最大の(私のセクションだけで最大10 ^ 6LOC )、最も古い、恐ろしいコードに取り組んでおり、私が持っているときに見る列車の残骸を修正することを習慣にしています私が取り組んでいるコンポーネントの一部ではない場合でも。これを行うことで、開発チームが存在することすら知らなかったバグを見つけて修正しました(ただし、エンドユーザーはおそらくそうでしたが)。実際、私は指示されています。結果として製品が改善されます。
アーロン

10
私はそのリファクタリングとは呼びませんが、バグ修正と呼びます。
パエロエベルマン

7
コードベースの設計の改善はリファクタリングです。再設計によって修正可能なバグが明らかになった場合、それはバグ修正です。私のポイントは、最初のものはしばしば2番目のものにつながり、2番目のものはしばしば最初のものなしでは非常に難しいということです。
Kramii

10
@Aaronあなたはそれをする際に管理者/開発者のサポートを持っていることが幸運です。ほとんどの環境では、貧弱なデザインとコードによって引き起こされる既知および未知のバグは、物事の自然な順序として受け入れられます。
ルドルフオラー

5
@nocomprende私は、システムのテストを書くのに十分なシステムを十分に理解していない場合、それがどのように機能するかを変更するビジネスはないと主張します。
パトリックM

61

私の質問は、著者からこのような警告が発生した場合、コードをリファクタリングする必要がありますか

いいえ、または少なくともまだ。自動テストのレベルが非常に低いことを意味します。自信を持ってリファクタリングするには、テストが必要です。

今のところ、何かを壊すことなく機能を追加することはできません

今は、リファクタリングではなく、安定性の向上に集中する必要があります。安定性の向上の一環としてリファクタリングを行うこともできますが、それは本当の目標である安定したコードベースを達成するためのツールです。

これはレガシコードベースになったように聞こえるので、少し異なる方法で扱う必要があります。

特性評価テストを追加することから始めます。仕様について心配する必要はありません。現在の動作をアサートするテストを追加するだけです。これにより、新しい作業によって既存の機能が損なわれるのを防ぐことができます。

バグを修正するたびに、バグが修正されたことを証明するテストケースを追加します。これにより、直接回帰が防止されます。

新しい機能を追加するときは、新しい機能が意図したとおりに機能することを少なくともいくつかの基本的なテストに追加します。

おそらく「レガシーコードを効果的に使用する」のコピーを入手できますか?

既存のコードをリファクタリングするのに数ヶ月かかりました。

テストカバレッジを取得することから始めます。最も壊れやすい領域から始めます。最も変化の大きい領域から始めます。不良なデザインを特定したら、それらを1つずつ交換します。

大規模なリファクタリングを行うことはほとんどありませんが、毎週小さなリファクタリングが絶え間なく行われます。ある大きなリファクタリングは、物事を壊す大きなリスクを抱えており、うまくテストするのは困難です。


10
特性評価テストを追加するための+1。テストされていないレガシコードを変更する場合に、リグレッションを最小限に抑える唯一の方法です。変更を開始してからテストが失敗し始めたら、仕様を考慮して以前の動作が実際に正しいかどうか、または新しい変更された動作が正しいかどうかを確認できます。
レオ

2
右。または、使用可能な仕様がない場合、以前の動作が実際にソフトウェアにお金を払っている、またはソフトウェアに興味がある人々によって望まれているかどうかをチェックします。
bdsl

おそらく「レガシーコードを効果的に使用する」のコピーを入手できますか?その本を読むのに何週間かかりますか?そしていつ:職場での勤務時間中、誰もが眠る夜ですか?
ビラルBegueradj

23

GK Chestertonのフェンスを覚えておいてください。なぜ建設されたのかを理解するまで、道路を遮るフェンスを取り壊さないでください。

コードの作成者と問題のコメントを見つけ、それらを参照して理解を得ることができます。コミットメッセージ、電子メールスレッド、またはドキュメントがある場合は、それらを確認できます。次に、マークされたフラグメントをリファクタリングするか、コメントにあなたの知識を書き留めて、このコードを保守する次の人がより多くの情報に基づいた決定を行えるようにします。

あなたの目的は、コードが何をするのか、そしてなぜそのコードに警告が付けられたのか、そして警告が無視された場合に何が起こるのかを理解することです。

その前は、「触れないでください」とマークされているコードには触れません。


4
OPは「いいえ、著者と連絡を取ることはできません」と言っています。
FrustratedWithFormsDesigner

5
著者と連絡を取ることも文書もありません。
-kukis

21
@kukis:著者やドメインの専門家に連絡できず、問題のコードに関連するメール/ wiki /ドキュメント/テストケースが見つかりませんか?さて、それはソフトウェア考古学における本格的な研究プロジェクトであり、単純なリファクタリング作業ではありません。
9000

12
コードが古く、著者が去ったことは珍しいことではありません。彼らが競争相手のために働いてしまったなら、それについて議論することは誰かのNDAに違反するかもしれません。いくつかのケースでは、著者は永久に利用できません。彼が数年前に亡くなったため、Phil ZipにPKzipについて尋ねることはできません。
pjc50

2
「著者を見つける」を「コードが解決した問題を理解する」に置き換えた場合、これが最良の答えです。時々、これらのコードは、通常の種類の単体テストでは見つけられないバグを見つけて追跡し、対処するのに数週間または数か月の作業を要したバグに対する最も恐ろしい解決策ではありません。(時々、彼らは何をしているのか知らないプログラマーの結果です。あなたの最初の仕事はそれが
何で

6

あなたが示したようなコメントのあるコードは、リファクタリングするもののリストの一番上にあり、そうする理由がある場合のみです。ポイントは、コードがひどく悪臭を放つということです。コメントを通してそれを嗅ぐことさえできます。このコードに新しい機能を追加しようとするのは無意味です。そのようなコードは、変更する必要があるとすぐに消滅する必要があります。

また、コメントは少なくとも役に立たないことに注意してください。コメントのみを提供し、理由はありません。はい、それらはサメのタンクの周りの警告標識です。しかし、近くで何かをしたい場合は、サメと一緒に泳ぐことを試みるポイントはほとんどありません。私見、これらのサメを最初に取り除く必要があります。

そうは言っても、そのようなコードに取り組む勇気を得るには、良いテストケースが絶対に必要です。これらのテストケースを作成したら、実際に動作を変更していないことを確認するために、変更している小さなすべてのことを必ず理解してください。コードのすべての動作特性を、効果がないことを証明できるまで維持することを最優先にします。サメを扱っていることを覚えておいてください-あなたは非常に注意しなければなりません。

そのため、タイムアウトの場合:コードが何を待っているかを正確に理解するまでそのままにしておき、それから削除する前にタイムアウトが導入された理由を修正します。

また、上司は、あなたが着手していることとそれが必要な理由を理解していることを確認してください。そして、彼らがノーと言ったら、それをしないでください。これには絶対に彼らのサポートが必要です。


1
実際の動作がドキュメントと一致しないシリコンのプリプロダクションサンプルで正しく動作する必要があるため、コードが混乱する場合があります。回避策の性質に応じて、コードがバグのあるチップで実行される必要がない場合は、コードを置き換えることをお勧めしますが、新しいコードに必要なエンジニアリング分析のレベルなしでコードを変更することはおそらく適切ではありませんアイデア。
-supercat

@supercat私のポイントの1つは、リファクタリングが動作を完全に保持する必要があるということでした。振る舞いを保存しない場合、それは私の本のリファクタリング以上のものです(そしてそのようなレガシーコードを扱うときは非常に危険です)。
cmaster

5

物事が正常に機能する場合、おそらくこのような警告を含むコードをリファクタリングすることはお勧めできません。

しかし、リファクタリングする必要がある場合...

最初に、いくつかの単体テストと統合テストを作成して、警告が警告している状態をテストします。生産のような条件を可能な限り模倣するようにしてください。これは、実稼働データベースをテストサーバーにミラーリングする、マシン上で同じ他のサービスを実行するなど、何でもできることを意味します。次に、リファクタリングを試みます(もちろん、孤立したブランチで)。次に、新しいコードでテストを実行して、元のコードと同じ結果が得られるかどうかを確認します。可能であれば、本番環境でリファクタリングを実装しても大丈夫でしょう。ただし、問題が発生した場合は、変更をロールバックする準備をしてください。


5

先に行くとそれを変更すると言います。信じられないかもしれませんが、すべてのコーダーが天才というわけではありません。このような警告は、改善の余地があることを意味します。著者が正しいとわかった場合、警告の理由を文書化または説明できます。


4

特定の問題のいくつかの側面が見過ごされているか、間違った結論を出すために使用されていると思うので、コメントを回答に拡大しています。

この時点で、リファクタリングするかどうかの問題は時期尚早です(おそらく「yes」の特定の形式で答えられるでしょうが)。

ここでの中心的な問題は、(いくつかの回答に記載されているように)引用するコメントは、コードに競合条件またはここで説明しような他の同時実行/同期の問題があることを強く示していることです。これらはいくつかの理由で特に難しい問題です。第一に、あなたが見つけたように、一見無関係な変更が問題を引き起こす可能性があります(他のバグもこの効果をもたらす可能性がありますが、同時実行エラーはほとんど常に起こります。)第二に、それらは診断するのが非常に困難です:バグはしばしば時間とコードが原因から遠い、それを診断するためにあなたが何をするにしても、それが消えてしまう可能性があります(ハイゼンバグ)。第三に、テストでは並行性のバグを見つけるのは非常に困難です。部分的には、組み合わせの爆発によるものです。シーケンシャルコードには十分ではありませんが、同時実行の可能性のあるインターリーブを追加すると、シーケンシャル問題が比較すると重要ではなくなるポイントまで爆発します。さらに、優れたテストケースであっても、問題を時折引き起こすことがあります。ナンシーレベソンは、Therac 25の致命的なバグの1つを計算しました。約350回の実行のうち1回で発生しましたが、バグが何であるかわからない場合、またはバグがある場合でも、何回繰り返して効果的なテストを行うかはわかりません。さらに、このスケールでは自動テストのみが実行可能であり、テストドライバーが微妙なタイミング制約を課して、実際にバグがトリガーされないようにすることができます(ハイゼンバグ)。

POSIX pthreadsを使用するコードのHelgrindなど、一部の環境では同時実行テスト用のツールがいくつかありますが、ここでは詳細を知りません。ご使用の環境に適したツールがある場合は、静的分析でテストを補完する必要があります(またはその逆ですか?)。

難易度を上げるために、コンパイラ(および実行時のプロセッサ)は、スレッドセーフについての推論を直観に反するような方法でコードを再編成することができます(おそらく最もよく知られているケースは、ダブルチェックいくつかの環境(Java、C ++ ...)を改善するために変更されていますが、ロックイディオム。

このコードには、すべての症状を引き起こす単純な問題が1つありますが、新しい機能を追加する計画を停止させる可能性のあるシステム上の問題がある可能性が高くなります。あなたがあなたの手に深刻な問題、おそらくあなたの製品への実存的な脅威を持っているかもしれないことをあなたに確信させたと思います、そして最初にすることは何が起こっているかを知ることです。これにより同時実行性の問題が明らかになった場合、より一般的なリファクタリングを行うべきかどうか、さらに機能を追加する前に質問する前に、まずそれらを修正することを強くお勧めします。


1
コメントの「競合状態」はどこに表示されますか?それはどこまで暗示されていますか?ここでは、コードを見る利点さえなく、非常に多くの技術的な仮定を行っています。
ロバートハーヴェイ

2
@RobertHarvey「モジュールAに何か時間を与えるためのタイムアウトセット。」-ほとんど競合状態の定義であり、タイムアウトはそれらを処理するための強力な方法ではありません。この推測を描くのは私だけではありません。ここで問題がなければ、それで問題ありませんが、これらのコメントが適切に処理されていない同期のレッドフラグであることを考えると、質問者は知る必要があります。
-sdenham

3

私はかなり大きなコードベースを扱っており、既存のコードをリファクタリングするために数ヶ月を与えられました。すぐに製品に多くの新機能を追加する必要があるため、リファクタリングプロセスが必要です[...]

リファクタリング中に、時々、["これに触れないでください!"]のようなコメントのあるクラス、メソッド、またはコード行に遭遇します

はい、特にこれらの部分をリファクタリングする必要があります。これらの警告は、前の作者によって「このようなものをむやみに改ざんしないでください。非常に複雑で、予期しないやり取りがたくさんあります」という意味です。あなたの会社がソフトウェアをさらに開発し、多くの機能を追加することを計画しているとき、彼らはあなたにこのようなものをクリーンアップすることを特に任せました。だから、あなたはそれを無造作に改ざんしていない、あなたはそれをきれいにする仕事で故意に請求されます。

これらのトリッキーなモジュールが何をしているのかを見つけ、それを小さな問題に分解します(元の作者がすべきこと)。混乱からメンテナンス可能なコードを取得するには、良い部分をリファクタリングし、悪い部分を書き直す必要があります。


2

この質問は、「コードを継承する方法」のダッシュでコードをリファクタリングおよび/またはクリーンアップするタイミング/方法の議論に関する別のバリ​​エーションです。私たちはすべて異なる経験を持ち、異なるチームや文化を持つ異なる組織で働いているので、「あなたがする必要があると思うことをして、解雇されない方法でそれを行う」以外の正しいまたは間違った答えはありません。

サポートするアプリケーションにはコードのクリーンアップやリファクタリングが必要だったので、ビジネスプロセスを脇に置いてくれるような組織はあまりないと思います。

この特定のケースでは、コードコメントは、コードのこれらのセクションを変更するべきではないというフラグを立てています。したがって、先に進んでビジネスが横行する場合、アクションをサポートするために表示するものがないだけでなく、実際には意思決定に反する成果物があります。

そのため、常にそうであるように、変更しようとしていることのあらゆる側面を理解した後にのみ慎重に進めて変更を行い、容量とパフォーマンスとタイミングに細心の注意を払ってそれをテストする方法を見つける必要がありますコード内のコメント。

しかし、それでもなお、経営者は自分がやっていることに内在するリスクを理解し、自分のやっていることがリスクを上回るビジネス価値を持ち、そのリスクを軽減するためにできることをしたことに同意する必要があります。

さて、私たち全員が私たち自身のTODOに戻りましょう。時間があれば、私たちが知っていることは私たち自身のコード作成で改善することができます。


1

そのとおり。これらは、このコードを書いた人がコードに不満であり、動作するようになるまでコードを突っ込んでいた可能性があることを明確に示しています。実際の問題が何であるかを理解していないか、さらに悪いことに、それらを理解していて修正するのが面倒だった可能性があります。

ただし、それらを修正するには多くの労力が必要であり、そのような修正にはリスクが伴うことを警告しています。

理想的には、問題が何であるかを把握し、適切に修正できるようになります。例えば:

モジュールAに何かをする時間を与えるためのタイムアウトセット。このようにタイミングが合わないと、壊れてしまいます。

これは、モジュールAがいつ使用できる状態になったか、または処理がいつ終了したかを適切に示していないことを強く示唆しています。おそらくこれを書いた人は、モジュールAの修正を気にしたくなかったか、何らかの理由でできなかったでしょう。これは、タイミングの依存関係が適切なシーケンスではなく運で処理されることを示唆しているため、災害が発生するのを待っているように見えます。これを見た場合、私はそれを修正したいと思います。

これを変更しないでください。私を信じて、あなたは物事を壊すでしょう。

これはあまりわかりません。コードが何をしていたかによります。それは、何らかの理由で実際にコードを壊す明白な最適化のように見えるものを持っていることを意味するかもしれません。たとえば、別のコードが依存する特定の値に変数を残すループが発生する場合があります。または、変数を別のスレッドでテストし、変数の更新順序を変更すると、他のコードが破損する場合があります。

setTimeoutを使用することはお勧めできませんが、この場合は使用する必要がありました。

これは簡単なように見えます。あなたは何setTimeoutをしているかを見ることができ、おそらくもっと良い方法を見つけることができるはずです。

そうは言っても、これらの種類の修正がリファクタリングの範囲外である場合、これらはこのコード内でリファクタリングを試みると作業範囲が大幅に増加する可能性があることを示しています。

少なくとも、影響を受けるコードをよく見て、少なくともコメントを改善して問題が何であるかをより明確に説明できるようになるかどうかを確認してください。それはあなたが直面する同じ謎に直面することから次の人を救うかもしれません。


2
条件が古い問題がまったく存在しないポイントに変更された可能性があり、警告コメントは「Here be dragons」という古いマップ上の場所のようになった可能性があります。状況に飛び込み、状況が何であるかを学ぶか、それが歴史に受け継がれていることを確認してください。

2
現実の世界では、一部のデバイスは信頼性のあるレディネスの表示を提供せず、代わりに最大のレディネス時間を指定します。信頼性が高く効率的な準備状況の表示は便利ですが、場合によってはそれらのないものを使用して立ち往生することがあります。
-supercat

1
@supercatたぶんそうではないかもしれません。ここのコメントからはわかりません。ですから、コメントを改善するために、他に何もないとしても、調査する価値があります。
デビッドシュワルツ

1
@DavidSchwartz:コメントは確かに役立つ可能性がありますが、特に問題が予想されるかどうかが明確でない場合、プログラマーがデバイスが仕様を順守できないすべての正確な方法をマッピングしようとするのにどれだけの時間を費やすべきかが不明な場合があります一時的または永続的なものになります。
supercat

1

コメントの作者はおそらくコード自体を完全に理解しなかったでしょう。彼らが何をしていたかを実際に知っていたなら、彼らは実際に役立つコメントを書いていたでしょう(またはそもそもレース条件を紹介していなかったでしょう)。「信頼してください、あなたは物事を壊します。」のようなコメントは、著者が完全に理解していなかった予期しないエラーを引き起こした何かを変更しようとすることを示します。

コードは、実際に何が起こるかを完全に理解することなく、推測と試行錯誤によって開発されたものと思われます。

これの意味は:

  1. コードを変更するのは危険です。理解するには明らかに時間がかかりますが、おそらく適切な設計原則に従っておらず、影響や依存関係があいまいになる可能性があります。テストが不十分である可能性が高く、コードの動作を完全に理解している人がいない場合、エラーや動作の変更が発生しないことを確認するためのテストを記述することは困難です。レース条件(暗示されるコメントのように)は特に面倒です-これは単体テストがあなたを救わない1つの場所です。

  2. コードを変更しないことは危険です。コードには、あいまいなバグや競合状態が含まれる可能性が高くなります。コードに重大なバグが発見された場合、または優先度の高いビジネス要件の変更により、このコードを予告なく変更せざるを得ない場合、深刻な問題に直面しています。これで、1で概説したすべての問題がありますが、時間的なプレッシャーにさらされています!さらに、コード内のこのような「暗い領域」は、接触するコードの他の部分に広がり、感染する傾向があります。

さらに複雑なこと:単体テストではあなたを救うことはできません。通常、このような古いコードを修正するための推奨されるアプローチは、最初に単体テストまたは統合テストを追加してから、分離してリファクタリングすることです。しかし、自動化されたテストではレース状況を把握できません。唯一の解決策は、コードを理解するまで座って考え、コードを書き直して、競合状態を回避することです。

これは、タスクが単なるリファクタリングよりもはるかに要求の厳しいことを意味します。実際の開発タスクとしてスケジュールする必要があります。

通常のリファクタリングの一環として、影響を受けるコードをカプセル化できるため、少なくとも危険なコードは分離されます。


-1

私が尋ねる質問は、誰かが書いた理由です、そもそも編集しないでください。

私は多くのコードに取り組んできましたが、その一部は見苦しく、その時点で与えられた制約の範囲内で作業するために多くの時間と労力を費やしました。

この場合、私はこれが起こり、コメントを書いた人は、誰かがそれを変更し、それから作業全体を繰り返して、それを機能させるために元に戻す必要があることを発見しました。この後、彼らは次のように書きました...編集しないでください。

言い換えれば、私は自分の人生にもっと良いことがあるので、これを再び修正する必要はありません。

「編集しない」と言うことは、私たちが今知っていることをすべて知っているので、将来は新しいことを決して学ばないと言う方法です。

編集しない理由について少なくともコメントが必要です。「触れないでください」または「入力しないでください」と言ってください。フェンスに触れてみませんか?入ってみませんか?「電気柵、触らないで!」と言ったほうがいいのではないでしょうか。または「Land Mines!Do Not Enter!」。それから、なぜ、そしてあなたはまだ入ることができますが、少なくともあなたがする前に結果を知っています。

また、システムにはこのマジックコードに関するテストがないため、変更後もコードが正しく機能することを誰も確認できません。問題コードの周囲に特性テストを配置することは、常に最初のステップです。コードの変更に取り組む前に、依存関係を解除してテスト対象のコードを取得する方法に関するヒントについては、Michael Feathersによる「レガシーコードの操作」を参照してください。

最終的には、リファクタリングに制限を設け、製品を自然で有機的な方法で進化させることは近視眼的だと思います。


2
これは、以前の9つの回答で作成され説明されたポイントに対して実質的なものを提供していないようです
-gnat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.