まだデバッグをいじっていますか?

こんにちは親愛なる読者。



ロシア語では、OOPの原則に関する普遍的な不朽の文献はあまりありません。 この機会に、Matt Weisfeldの「 Object-Oriented Thinking 」をダウンロードしてください。 しかし、そのような本は時々登場し、有名な真理を粉砕するだけでなく、革新的で応用されたスタイルで書かれたものがあります。 その1つは「 エレガントオブジェクト 」と呼ばれ、ロシア語での公開を真剣に考えています。







著者のブログの最新記事の翻訳で、著者のスタイルと哲学を評価することを提案します。







デバッグとは、「プログラム/メソッドをインタラクティブに起動するプロセスであり、各命令の実行フローは中断され、結果が表示されます...」。 基本的に、これは非常に効率的なテクニックです...貧しいプログラマーにとって。 または、まだCで手続き型コードを書いている昔ながらのプログラマーのために。OOPの専門家はコードをデバッグせず、ユニットテストを書いています。 ユニットテストは、アジェンダからデバッグを完全に削除すると言えます。 デバッグが必要な場合、 プログラムの設計は不十分です







私が悪いプログラマであると仮定して、私は命令型の手続き型スタイルで記述し、Javaでそのようなコードを生成します。



class FileUtils { public static Iterable<String> readWords(File f) { String text = new String( Files.readAllBytes(Paths.get(f)), "UTF-8" ); Set<String> words = new HashSet<>(); for (String word : text.split(" ")) { words.add(word); } return words; } }
      
      







この静的ヘルパーメソッドは、ファイルの内容を読み取り、ファイル内のすべての一意の単語を検索します。 すべてがシンプルです。 しかし、彼が仕事を拒否した場合、私たちは何をしますか? ファイルが次のとおりであるとしましょう:



 We know what we are, but know not what we may be.
      
      







それから、次の単語のリストを抽出します。



 "We" "know" "what" "we" "are,\n" "but" "not" "may" "be\n"
      
      







この場合、私はそれが好きではありません...ちょうど次のステップ-どれですか? ファイルがエラーで読み取られるか、改行でエラーが発生します。 デバッグしましょう。 入力を介してファイルを実行し、すべての変数を追跡し、それらを観察しながら、段階的に実行します。 バグを見つけ、修正します。 しかし、同様の問題が繰り返し発生する場合は、再度デバッグする必要があります! そのような場合は、単体テストで防止する必要があります。



単体テストを1回作成して、問題を再現する必要があります。 次に、問題を修正し、テストに合格することを確認します。 したがって、問題は合理的に解決されます。 エラーが発生しなくなるため、再度コミットする必要はありません。 私たちのテストはこれを保証します。



ただし、これらはすべて、単体テストの作成が簡単な場合にのみ機能します。 書くのが難しいなら、私は怠けすぎて書かないでしょう。 デバッグを行い、問題を修正するだけです。 この特定のケースでは、テストの作成は簡単ではありません。 つまり、テスト自体の難易度は非常に高いです。 一時ファイルを作成してデータを入力し、メソッドを実行して結果を確認する必要があります。 何が起こっているのか、ここのバグはどこにあるのかを理解するには、複数のテストが必要になります。 コードの重複を避けるために、一時ファイルを作成してデータを入力するのに役立ついくつかのユーティリティを作成する必要もあります。 たくさんの仕事。 「多すぎない」かもしれませんが、デバッグすれば数分で処理できました。



したがって、デバッグが複雑すぎて停止しているように思われる場合は、コードの品質について考えてください。 上のリストのコードのように、彼にはリファクタリングのオプションがたくさんあるに違いありません。 これは私がそれを変更する方法です。 最初に、補助的な静的メソッドは悪質であるため、クラスにそれをやり直します。



 class Words implements Iterable<String> { private final File file; Words(File src) { this.file = src; } @Override public Iterator<String> iterator() { String text = new String( Files.readAllBytes(Paths.get(this.file)), "UTF-8" ); Set<String> words = new HashSet<>(); for (String word : words.split(" ")) { words.add(word); } return words.iterator(); } }
      
      







すでにはるかに優れていますが、まだ挑戦的です。 次に、より小さなクラスに分割します。



 class Text { private final File file; Text(File src) { this.file = src; } @Override public String toString() { return new String( Files.readAllBytes(Paths.get(this.file)), "UTF-8" ); } } class Words implements Iterable<String> { private final String text; Words(String txt) { this.text = txt; } @Override public Iterator<String> iterator() { Set<String> words = new HashSet<>(); for (String word : this.text.split(" ")) { words.add(word); } return words.iterator(); } }
      
      







まあどう? Words





クラスのテストを書く Words





-完全に簡単なタスク:



 import org.junit.Test; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; public class WordsTest { @Test public void parsesSimpleText() { assertThat( new Words("How are you?"), hasItems("How", "are", "you") ); } }
      
      







これにどれくらいの時間を費やしましたか? 1分未満。 Words



クラスはファイルでは機能しないため、一時ファイルを作成してデータを入力する必要はありません。 彼は単に入力文字列を解析し、その中の一意の単語を見つけます。 テストは小さいため、エラーを修正するのは簡単です。他のテストを書くことは難しくありません。たとえば:



 import org.junit.Test; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; public class WordsTest { @Test public void parsesSimpleText() { assertThat( new Words("How are you?"), hasItems("How", "are", "you") ); } @Test public void parsesMultipleLines() { assertThat( new Words("first line\nsecond line\n"), hasItems("first", "second", "line") ); } }
      
      







ユニットテストの記述にTrace-In / Trace-Outボタンを押すよりもかなり長い時間がかかる場合、デバッグが必要だと思います。 これは論理的です。 私たちは皆怠zyで、シンプルで迅速なソリューションが大好きです。 しかし、デバッグは時間と労力の無駄です。 問題を見つけるのに役立ちますが、その再発から安全ではありません。



デバッグは、コードが目標が何であるかではなく、目標がどのように達成されるかを記述するときに、手続き型およびアルゴリズムのコードで必要です。 上記の例をもう一度確認してください。 最初の静的メソッド全体で、ファイルの読み取り、解析、および単語の検索方法について説明します。 readWords()



と呼ばれることもあります(「read」は動詞です )。 対照的に、2番目の例は、どの目標を達成する必要があるかを示しています。 Text



ファイルのテキストか、テキスト内の単語(これらは名詞です )のいずれかです。



適切なOOPでは、デバッグは不適切だと思います。 単体テストのみ!



All Articles