特定の条件でプログラマーの注意を引く方法


13

例から始めましょう。

たとえば、exportDBスキーマに大きく依存するというメソッドがあります。また、「大きく依存する」ということは、特定のテーブルに新しい列を追加すると、頻繁に(非常に頻繁に)対応するexportメソッドが変更されることを知っています(通常、エクスポートデータにも新しいフィールドを追加する必要があります)。

プログラマーは、exportメソッドを変更することを忘れることがよくあります。これを確認する必要があるかどうかは明確ではないからです。私の目標は、プログラマーがメソッドを見るのを忘れたのか、エクスポートデータにフィールドを追加したくないだけなのかを明確に決定するようプログラマーに強制することexportです。そして、私はこの問題の設計ソリューションを探しています。

私には2つのアイデアがありますが、どちらにも欠点があります。

スマートな「すべてを読む」ラッパー

すべてのデータが明示的に読み取られるようにするスマートラッパーを作成できます。

このようなもの:

def export():
    checker = AllReadChecker.new(table_row)

    name    = checker.get('name')
    surname = checker.get('surname')
              checker.ignore('age') # explicitly ignore the "age" field

    result = [name, surname] # or whatever

    checker.check_now() # check all is read

    return result

そのため、読み取られなかった別のフィールドが含まれてcheckerいるかどうかをアサートしtable_rowます。しかし、このことはすべて重そうに見え、(おそらく)パフォーマンスに影響します。

その方法を確認する」unittest

最後のテーブルスキーマを記憶し、テーブルが変更されるたびに失敗するunittestを作成するだけです。その場合、プログラマーは「exportメソッドをチェックアウトするのを忘れないでください」のようなものを見るでしょう。警告プログラマーを非表示にするには、問題をチェックアウトしexport手動で(別の問題です)新しいフィールドを追加してテストを修正します。

私には他にもいくつかのアイデアがありますが、それらは実装するのが面倒で、理解するのが難しすぎます(そして、プロジェクトをパズルにしたくないのです)。


上記の問題は、私が時々遭遇するより広範なクラスの問題の例です。いくつかのコードやインフラストラクチャをバインドしたいので、それらのいずれかを変更すると、すぐにプログラマに別のコードをチェックするよう警告します。通常、一般的なロジックの抽出や信頼性の高い単体テストの作成などの簡単なツールがありますが、より複雑なケースのツールを探しています。


exportスキーマに基づいて生成できますか?
コアダンプ

アウトマティックに生成することはできないため、プログラマーにコードをて決定を下すように依頼する必要があります
ワディムプシュテエフ

フィールド名の2つのリスト(exportとdont-export)をエクスポートクラスに追加し、これらの2つのリストが一緒にデータベースのフィールドの完全なセットを含むことを確認する単体テストを行うソリューションですか?
シェードジョブポストマス

export現実的に必要なものがすべて揃っているかどうかをチェックするテストを自動生成できますか?
-biziclop

1
ソースコード内のコメントは単純すぎる解決策ですか?通常、リマインダーがないため見逃されますが、コメントで修正できます。
gbjbaanb

回答:


11

単体テストのアイデアは順調に進んでいますが、実装が間違っています。

場合はexport、スキーマとスキーマ変更に関連して、2つのケースが考えられます

  • exportスキーマのわずかな変更の影響を受けなかったため、まだ完全に機能するか、

  • または壊れます。

どちらの場合も、この可能な回帰を追跡することがビルドの目標です。一連のテスト(統合テスト、システムテスト、機能テストなど)は、前回のコミット以降に変更されたかどうかに関係なく、exportプロシージャが現在のスキーマで動作することを確認します。これらのテストに合格した場合、素晴らしい。失敗した場合、これは開発者が何かを見逃している可能性があることを示すサインであり、どこを見ればよいかを明確に示しています。

実装が間違っているのはなぜですか?さて、いくつかの理由があります。

  1. 単体テストとは関係ありません...

  2. ...そして実際には、テストすらありません。

  3. 最悪の部分は、「テスト」を修正するには、実際には「テスト」を変更する必要があることです。つまり、「テスト」とはまったく関係のない操作を行うことですexport

代わりに、exportプロシージャの実際のテストを行うことにより、開発者がを修正することを確認しますexport


より一般的には、あるクラスの変更が常に、または通常は完全に異なるクラスの変更を必要とする状況に遭遇した場合、これは設計を誤っており、単一責任原則に違反していることを示す良い兆候です。

クラスについて具体的に説明しますが、他のエンティティにも多少適用されます。たとえば、データベーススキーマの変更は、たとえば多くのORMで使用されるコードジェネレーターを介してコードに自動的に反映されるか、少なくとも簡単にローカライズされる必要DescriptionがありProductます。テーブルに列を追加し、ORMまたはコードジェネレーターを使用しない場合、少なくとも、DALのクラス内で単一の変更を行うことを期待しています。Data.Productすべてのコードベースを検索Productし、たとえばプレゼンテーション層でクラスの出現箇所を見つける必要はありません。

変更を1つの場所に合理的に制限できない場合(単に機能しない場合、または膨大な量の開発が必要な場合)、回帰のリスクが生じます。classを変更し、コードベースのどこかのAクラスBが機能しなくなると、リグレッションになります。

テストにより回帰のリスクが低下し、はるかに重要であるが、回帰の場所が示されます。このため、ある場所での変更がコードベースのまったく異なる部分で問題を引き起こすことがわかっている場合、このレベルで回帰が発生するとすぐにアラームを生成する十分なテストがあることを確認してください。

すべての場合において、そのような場合にコメントだけに頼らないようにしてください。何かのようなもの:

// If you change the following line, make sure you also change the corresponding
// `measure` value in `Scaffolding.Builder`.

決して機能しません。開発者はほとんどの場合それを読まないだけでなく、しばしば削除されるか関係する行から遠く離れて移動し、理解できなくなります。


はい、その「テスト」は実際にはテストではなく、ある種のtrapであり、ある種のIf you change the following line...自動的に機能し、単純に無視することはできません。私は誰かが実際にそのようなトラップを実際に使用したのを見たことがないため、疑いがあります。
ヴァディムプシュテエフ

1
問題は、クラスBが機能しなくなることではなく、おそらく正しく機能しなくなることです。しかし、私は未来を予測することも、未来を予測するテストを書くこともできないので、開発者にその新しいテストを書くよう思い出させようとします。
ヴァディムプシュテエフ

@VadimPushtaev:テストに関しては、「多分不適切に動作を開始する」と「動作を停止する」はまったく同じことです。将来を予測することはできませんが、要件を正確に把握し、それらの要件が実際の製品によって満たされていることをテストできるはずです。
Arseni Mourzenko

ええ、それは事です。実際、開発者に新しい要件について考えるように思い出させたいと思います。私はただ手を振るだけです。「こんにちは、エクスポートを忘れないでよろしいですか?マネージャーか何かに尋ねてください、それはよくある問題です」。
ワディムプシュテエフ

とにかくありがとう、あなたの答えは私が私の考えを整理するのに役立ちました、そして、私は現在ある計画を持っています。
ワディムプシュテエフ

3

あなたの変更が不十分に指定されているように思えます。郵便番号がない場所に住んでいるとしましょう。したがって、住所テーブルに郵便番号の列はありません。次に、郵便番号が導入されるか、郵便番号がある場所に住んでいる顧客との取引を開始し、この列をテーブルに追加する必要があります。

作業項目に「住所テーブルに郵便番号列を追加する」と表示されている場合、はい、エクスポートは破損するか、少なくとも郵便番号をエクスポートしません。しかし、郵便番号の入力に使用される入力画面はどうでしょうか?すべての顧客とその住所をリストするレポートですか?この列を追加するときに変更する必要があるものが山ほどあります。これらのことを思い出すのは重要な仕事です。開発者を覚えさせるために開発者を「トラップ」するために、ランダムなコード成果物を当てにしてはいけません。

意味のある列(つまり、キャッシュされた合計または非正規化されたルックアップ、またはエクスポートやレポート、または入力画面に属さないその他の値だけでなく)を追加する決定が行われた場合、作成される作業項目にはすべての変更が含まれる必要があります必要-列の追加、移入スクリプトの更新、テストの更新、エクスポート、レポート、入力画面などの更新。これらはすべて同じ人に割り当てられている(またはピックアップされている)わけではありませんが、すべて完了しなければなりません。

開発者は、大きな変更を実装する一環として、列自体を追加することを選択する場合があります。例えば、誰かが入力画面とレポートに何かを追加するために、それがどのように実装されるかを考えずに作業項目を書いたかもしれません。これが頻繁に発生する場合、作業項目追加者が実装の詳細を知る必要があるか(すべての適切な作業項目を追加できるようにするため)、または開発者が作業項目追加を認識する必要があるかどうかを決定する必要があります加算器は時々物を省きます。後者の場合は、「スキーマを変更するだけでなく、停止して、他に影響を与えるものについて考える」という文化が必要です。

多くの開発者がいて、これが複数回発生した場合、チームリーダーまたは他の上級者がスキーマの変更についてアラートを受け取るように、チェックインアラートを設定します。その人は、スキーマ変更の結果に対処するために関連する作業項目を探し、作業項目が欠落している場合、それらを追加するだけでなく、計画から除外した人を教育することができます。


2

ほとんどの場合、エクスポートを作成するときに、対応するインポートも作成します。エクスポートされるデータ構造を完全に読み込む他のテストがあるので、完全に読み込まれたオリジナルをエクスポートされインポートされたコピーと比較するラウンドトリップユニットテストを構築できます。それらが同じ場合、エクスポート/インポートは完了しています。それらが同じでない場合、単体テストは失敗し、エクスポートメカニズムを更新する必要があることを知っています。


これにより、すべてのオブジェクトが保存され、dbからリロードされることを確認できます。既存のdb-fieldに対応するオブジェクトフィールドがない場合は対象外です。
k3b

@ k3b true。少なくとも私のシステムでは、それは通常、何かがもはや使用されていないがスキーマから削除されていない場合に発生します。スキーマはエクスポートメカニズムの範囲外です。オブジェクト永続性の単体テストでは、オブジェクトの各フィールドが持続しましたが、システム関数に目に見える影響がないため、未使用の列についてはテストしません。
ピートカーカム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.