TDDの使用時に機能または機能を削除する方法


20

TDDに関するテキストでは、リファクタリングのステップ中に「重複の削除」または「読みやすさの向上」についてよく読みます。しかし、未使用の関数を削除する理由は何ですか?

たとえばC、メソッドa()とを持つクラスがあるとしましょうb()。今私はそれにf()追いやられる方法を持つことが良いと思うC。実際、定義/記述された単体テストを除くf()すべての呼び出しを置き換えます。これはもう必要ありません-テストを除いて。b()b()

削除してb()、それを使用したすべてのテストを削除するだけでいいですか?その部分は「読みやすさの改善」ですか?


3
関数が存在しないことを確認するために別のテストを追加し、失敗したテストケースを修正してください;)
Filip Haglund

@FilipHaglund言語によっては、これが可能になる場合があります。しかし、コードのドキュメントとして、これは奇妙に見えます。
-TobiMcNamobi

1
よく知らない人のために:@FilipHaglundのコメントは明らかに冗談です。それをしないでください。
ジョット

回答:


16

はい、もちろん。読みやすいコードは、そこにないものです。

とはいえ、リファクタリングとは一般に、動作を変更せずにコードを改善することを意味します。コードを改善する何かを考えているなら、それをしてください。許可する前に、鳩の穴に入れる必要はありません。


@ jpmc26アジャイル、男、アジャイル!:-)
TobiMcNamobi

1
「読みやすいコードは、そこにないものです。」-私はその引用を壁に掛けています:D
winkbrace

27

パブリックメソッドの削除は「リファクタリング」ではありません。リファクタリングとは、既存のテストに合格し続けながら実装を変更することです。

ただし、不要なメソッドを削除することは、完全に合理的な設計変更です。

TDDはこれをある程度引き出します。なぜなら、テストをレビューする際に、不要なメソッドをテストしていることがわかるからです。「見て、このテストは私の目標とは何の関係もない」ということができるので、テストが設計を推進しています。

コードカバレッジツールと組み合わせて、より高いレベルのテストでさらに明らかになる場合があります。コードカバレッジを使用して統合テストを実行し、メソッドが呼び出されていないことを確認した場合、メソッドが使用されていないことがわかります。静的コード分析は、メソッドが使用されていないことも示すことができます。

メソッドを削除するには、2つのアプローチがあります。両方とも異なる状況で機能します:

  1. メソッドを削除します。コンパイルエラーに従って、依存コードとテストを削除します。影響を受けるテストが使い捨てであることに満足している場合は、変更をコミットします。そうでない場合は、ロールバックします。

  2. 古いと思われるテストを削除します。コードカバレッジを使用してテストスイート全体を実行します。テストスイートで実行されていないメソッドを削除します。

(これは、テストスイートが最初から適切にカバーされていることを前提としています)。


10

実際、f()は、b()を定義/記述した単体テストを除き、b()へのすべての呼び出しを置き換えます

私見、典型的なTDDサイクルは次のようになります:

  • f()の失敗したテストを書く(おそらくb()のテストに基づいている):テストが赤くなる

  • f()の実装->テストが緑色になります

  • リファクタリング:-> b()およびb()のすべてのテストを削除

最後のステップでは、最初にb()を削除して何が起こるかを検討することを検討します(コンパイルされた言語を使用する場合、コンパイラは既存のテストについてのみ文句を言う必要があります。そうでない場合、bの古い単体テストは失敗します。それらも削除する必要があることは明らかです)。


4

はい、そうです。

バグがなく、最も読みやすい最良のコードは、存在しないコードです。要件を満たしながら、できるだけ多くの非コードを書くよう努めてください。


9
「ハウツー」の部分を見逃しました。
ジェフ

2

削除することが望ましい b()使用されなくなった関数は、最初に使用されていない関数を追加しないことが望ましいのと同じ理由で、一度ことが望ましいです。あなたがそれを「読みやすさ」または他の何かと呼んでも、他のすべてが同じであれば、それはそれが役に立たない何も含まないコードの改善です。持っていない方が良い特定の対策を少なくとも1つ持つために、それを削除すると、その変更後の将来のメンテナンスコストがゼロになることが保証されます。

テストでそれを実際に削除するために必要な特別な技術は見つかりませんでした。b()新しいものに置き換えるという考えにはもちろんb()、現在呼び出しているすべてのコードの考慮が必要であり、テストは「すべてのコード「。

一般的に私のために動作することを推論のラインがポイントで、私はそれが気づくところということでf()作られたb()ので、廃止されたb()少なくとも廃止されるべきであり、私はすべてのコールを見つけるために探していますb()への呼び出しに置き換えることを意図してf()Iテストコードも考慮してください。特に、b()不要になった場合は、単体テストを削除できますし、削除する必要があります。

あなたは、それがもはや必要ではないことに気付くように強制するものは何もないということはまったく正しいb()。それはスキルの問題です(そして、スリムが言うように、コードカバレッジは高レベルのテストについて報告します)。単体テストのみで機能テストがない場合は、を参照してb()、公開されたインターフェイスの一部ではないことを慎重に楽観的にすることができます。したがって、それを削除することは、私の直接制御下にないコードの重大な変更ではありません。

赤/緑/リファクタリングサイクルは、テストの削除を明示的に言及していません。さらに、b()コンポーネント明らかに修正のために開かれているため、削除するとオープン/クローズの原則に違反します。したがって、このステップを単純なTDD以外の何かと考えたい場合は、先に進んでください。たとえば、テスト「不良」を宣言するプロセスがある場合があります。このプロセスは、存在しないはずの何か(不要な関数b())をテストするという理由でテストを削除する場合に適用できます。

実際には、ほとんどの人はおそらく赤/緑/リファクタリングのサイクルに沿ってある程度の再設計を行うことを許可するか、厳密に言えば「リファクタリング」の有効な部分である冗長ユニットテストの削除を検討すると思いますリファクタリングではありません。あなたのチームは、この決定を正当化するのにどのくらいのドラマと書類作業が含まれるべきかを決めることができます。

とにかく、b()重要な場合は機能テストがあり、それらは簡単には削除されませんが、ユニットテストのみがあると既に述べています。ユニットテスト(変更したコードの現在の内部設計に書き込まれます)と機能テスト(公開されたインターフェイスに書き込まれ、おそらく変更したくない)を適切に区別しない場合は、より注意する必要があります単体テストの削除について。


2

常に覚えておくべきことの1つは、バージョン管理でコードリポジトリを使用していることです。削除されたコードは実際には消えていません...前のイテレーションのどこかにまだあります。だからそれを吹き飛ばす!いつでも便利だと思っていた貴重なエレガントな方法をいつでも取り戻せるので、いつでも戻ることができるので、削除キーで寛大になります。それはそこにある。

もちろん、それは、下位互換性のないリリースの危険性と危険性に伴います...インターフェース実装に依存していた外部アプリケーションは、(突然)非推奨のコードによって孤立しています。


一般に、コードを削除しても問題はありません。私は大好き削除行、関数、または...よく、全体のモジュールを削除するには!可能なら。そして、私はこれをすべてTDDの有無にかかわらず行います。しかし、TDDワークフローに(非複製)コードが削除されるポイントはありますか?そうでない場合は、とにかく削除されます。しかし、そこにありますか?それが私の質問でした。
TobiMcNamobi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.