TDDを勉強するのが難しい理由と、それについてどうするか。 パート1

翻訳者から:ロシア語のインターネット上でTDDに関する情報がほとんどないことがたまたまあり、開発者の機械的な動作が主に説明されています。 主なもの- アイデア -はほとんど注目されていません。 この記事は、このギャップを埋める試みです。 テストの時間がない人向けではなく、特に疎​​結合アーキテクチャの重要性を認識していない人向けではないことに注意することが重要です。 この記事( オリジナル )は、TDDの最初のステップを実行している、または実行しようとしている人を対象としています。



最近、私はTDDトレーニングの実施を提案されました。これには、このテクニックにあまり慣れていない非常に知的な開発者と協力して作業することが含まれていました。 面白いことに気づきました。彼が尋ねた質問の多くは、TDDの勉強を始めたばかりの頃に私が持っていた質問と驚くほど似ていました。 また、誤った初期仮定から多数の質問が寄せられたことがわかりました。 私たち両方が同様の仮定をしたという事実は、私にこの理由を考えさせました。



この記事では、TDDを日常のタスクの使用レベルに習得することを正確に妨げるものを正確に理解しようとします。 次に、TDDがどのように、なぜ動作するのかを見て、既に持っている情報を批判的に評価し、学習プロセスを遅くする可能性のある誤った仮定を避ける機会を新参者に提供します。 最後に、TDDの実際の適用を妨げる一般的な質問に答えるために、新しい知識を使用する方法を検討します。



なぜそんなに難しいのですか?



いくつかの理由があると思います。 まず、TDDを取り巻く誇大広告は学習プロセスにとって十分に悪いものです。 この手法に関する情報がどこから来たのかに応じて、それが唯一の正しい開発方法であるという印象を簡単に得ることができ、単純な手順に従うだけでコードは純粋に輝き始め、美しく明白な抽象化で満たされます。 ただし、これは、最も単純な例を除き、すべての場合に当てはまりません。



その結果、非現実的な期待は、アルゴリズムの背後にあるアイデアを理解せずにアルゴリズム自体に焦点を当て、TDDのその後の非効率的な使用につながります。 そして、これは、スタックの実装中に完全に機能していたプロセスがWebページに非常に単純なものを表示しようとすると失敗する人に非常に悪影響を及ぼす。



TDDは思考に代わるものではなく、設計スキルの必要性を排除するものでもありません。 実際、TDDはそれ自体では何も行いません。開発者はすべてを行いますが、この手法は開発者自身と同じくらい優れています。 より現実的な見方は、TDDは作業を簡単にするために使用できる単なるツールであるということです。 もちろん、この手法は非常に便利ですが、最終的な目標はタスク*を完了することであり、失敗したテストで最小のコードの作成を常に開始するとは限りません。



*品質の低いコードは、完了したタスクとは見なされません



TDDの学習が難しいもう1つの理由は、この手法だけではその適用方法をあまり教えていないという事実です。 新しいことを学ぶための通常のアプローチは、これらの規則をいつ適用し、いつ破るかを理解するのに十分な経験を積むまで、単に規則に従うことです。 最終的に、これらのルールの背後にある考え方のビジョンを取得し、それらの使用は主にコンテキストに依存するということです。 ここから、典型的な答えが「そしてそれは状況に依存します」 (「依存します」-およそTransl。)です。



そのため、TDDのルールは非常に単純です。 実際、これらは非常に単純であるため、TDDを本当に成功させるために必要なスキルのレベルに達するまで、単純に適用することはできません。 それどころか、オブジェクト指向設計、パターン、SOLIDとDRYの原則などの分野における深い知識を必要とする適切な抽象化を既に構築できるはずです。 この知識のギャップが埋められるまで、TDDを適用することは不可能です。 一般に、一部の分野の知識の不足を完全に特定して、TDDはそれを記入するのに不十分な仕事をします。



テクニックを理解してから、それを適用する方法を学ぶ



TDDの研究を促進する良い方法は、この手法がどのように機能するかに早期に集中することだと思います。 もちろん、StackやStringCalculatorなどのクラスを開発する最も単純な例から始めて、赤のストライプ(緑のストライプ)のリファクタリングプロセスを学ぶ価値があります。 しかし、実際には、このプロセスが何をするのかを止めて考える必要があります。



失敗したテストを書くことから始めます。 なんで? 既存のテストは正常に合格します。つまり、コードに既知の問題はありません。 欠落している機能を特定するテストを作成することにより、解決しようとしている問題を明確に特定します。 タスクを修正することにより、可能な解決策を講じることで、タスクの処理プロセスを簡素化します。 また、結果のコードが正しい実装のテストでカバーされ、リグレッションから保護されることを保証します(ただし、TDDを使用しなくても十分な深さの自動テストを実行できます)。



しかし、ここで最も重要なことは、将来のアーキテクチャをスケッチすることです。 描画ボードではなく(利点があります)、コードで直接行われるため、このコードの使用とテストがいかに簡単かをすぐに理解できます。 最初に失敗したテストを作成するときにどのような質問が発生するかを見てみましょう。



コードを作成するとき、リストされているすべての質問がいつか尋ねられるべきであり、TDDの力はこれに便利なツールを提供することです。 潜在的な競合の発生を防止することで問題を順次解決するプロセスの代わりに、TDDでは「次のテストをどのように書くことができますか?」という抽象的な質問をすることができます。 そのため、TDDがプログラマより優れているわけではありません。適切な知識と経験を必要とする同じ重要な質問に対する答えを探す必要があります。 TDDは検索を簡単にします。



上記の抽象的な質問は正確に何をしますか? 優れた抽象化と同様に、作成された多くの小さなコンポーネントを全体として考慮することが可能になり、利用可能なすべての技術的スキルやその他のスキルをすぐに適用できます。 さらに、この単一の質問に対する答えを見つけると、別のTDDプロパティが促進されます。それは、高速で正確なコードフィードバックを提供することです。



テスト作成プロセスは、開発中のモジュールの包括的な評価を提供します。 準備は面倒すぎて使用できませんか? おそらく、補助クラスが多すぎる(またはデメテル法則に違反している)ため、追加の抽象化の背後にそれらを隠すことができます。 多くのユースケースやフィクスチャが判明しましたか? おそらく、テスト対象のコードには多くの責任があります。 テストされた動作を分離するのは難しいですか、それをテストする方法が明確ではありませんか? おそらく、間違ったAPIまたは抽象化自体があるため、何らかの方法で区別する必要があります。 TDDでは、これらの問題はすぐに明らかになります。 そのソリューションには、他の開発方法が必要とする設計スキルが必要です。 ただし、最初にテストを作成すると、エラーに対応し、実装前にモジュール設計をチェックする絶好の機会が得られます。 コードを修正する最も安い時間は、コードが書かれる前です。



次に、テストを満たす最も単純なコードを記述します。 奇妙なことに、これはTDDの最も面白くない部分です。 必要な動作を特定するためのハードワークはすべて完了しましたが、今ではそれを実装するだけです。 実装は複雑すぎますか? その後、戻ってテストを変更する必要があります-TDDを使用して、モジュールの開発であまりにも大きなステップをとろうとしていることがわかりました。 実装は簡単で、明らかな欠陥がありますか? さて、次のテストがどうなるかがわかりました。



そして、ここでリファクタリングの段階にあります。 作成したばかりのコードはテストを満たしますが、アプリケーションのごく一部に焦点を当てたので、今が全体像を見るときです。 「額」ソリューションが実装された場合、重複を取り除くか、別の方法を選択して、コードが何をするのかをより適切に説明できます。 さらに重要なのは、高レベルの重複の識別です。つまり、コードのセクションだけでなく、抽象化として区別できる、または構造レベルに持ち込むことができる同様の動作の繰り返しです。



より具体的には、これらすべてをどうするかについて-続編で。



All Articles