web-dev-qa-db-ja.com

コードレビューのために提出されたコードが複雑すぎると思われる場合はどうすればよいですか?

コードの追跡は困難ですが、少なくとも表面的なテストでは、(ほとんど)うまく機能しているようです。あちこちに小さなバグがあるかもしれませんが、より深い問題や単純な修正の兆候であるかどうかをコードを読んで判別することは非常に困難です。ただし、コードレビューを使用して全体的な正当性を手動で確認することは、たとえそれが可能であっても、非常に困難で時間のかかる作業です。

この状況での最善の行動方針は何ですか?やり直しを主張しますか?部分的なやり直し?最初にリファクタリングしますか?バグのみを修正して 技術的負債 を受け入れますか?これらのオプションについてリスク評価を行ってから決定しますか?他に何か?

116
Brad Thomas

審査できない場合、審査に合格できません。

コードレビューはバグを見つけるためのものではないことを理解する必要があります。それがQAの目的です。コードレビューは、コードの将来のメンテナンスが可能であることを確認することです。今すぐコードに従うことができない場合、機能の拡張やバグ修正を行うように割り当てられている6か月後にどうすればよいでしょうか。すぐにバグを見つけることは副次的な利点にすぎません。

複雑すぎる場合は、大量の SOLIDの原則 に違反しています。リファクタリング、リファクタリング、リファクタリング。それを適切に名前が付けられた関数に分割します。あなたはそれをクリーンアップすることができ、テストケースはそれが正しく機能し続けることを確認します。テストケースがありますよね?そうでない場合は、追加を開始する必要があります。

247
Kevin Fee

あなたが言及することはすべて、コードレビューで指摘するのに完全に有効です。

コードレビューを受け取ったら、テストをレビューします。テストが十分なカバレッジを提供しない場合、それは指摘するべきものです。テストは、コードが意図したとおりに機能し、変更が加えられても意図したとおりに機能することを保証するために役立つ必要があります。実際、これはコードレビューで最初に探すものの1つです。コードが要件を満たしていることを証明していない場合、私は時間をかけてそれを調べるつもりはありません。

コードに対して十分なテストが行​​われると、コードが複雑であるか追跡するのが難しい場合、それも人間が注意すべきことです。静的分析ツールは、複雑さのいくつかの測定値を指摘し、過度に複雑なメソッドにフラグを立てるだけでなく、コードの潜在的な欠陥を見つけることができます(人間によるコードレビューの前に実行する必要があります)。しかし、コードは人間によって読み取られ維持されるため、最初に保守性のために作成する必要があります。保守性の低いコードを使用する理由がある場合にのみ、そのように記述してください。複雑なコードや直感的でないコードが必要な場合は、そのコードを(できればコード内に)文書化し、コードがそのようになっている理由と、将来の開発者がコードを実行する理由と内容を理解するのに役立つコメントを記載する必要があります。

理想的には、適切なテストがないか、過度に複雑なコードがあるコードレビューを正当な理由なしに拒否します。先に進むにはビジネス上の理由があり、そのためにはリスクを評価する必要があります。コードで技術的な負債を抱えている場合は、すぐにバグ追跡システムにチケットを入れて、何を変更する必要があるかについての詳細と、変更するためのいくつかの提案を添えてください。

44
Thomas Owens

ただし、コードレビューを使用して全体的な正当性を手動で確認することは、たとえそれが可能であっても、非常に困難で時間のかかる作業です。

これは、コードレビューの要点ではありません。コードレビューを考える方法は、コードにバグがあり、それを修正する必要があることを想像することです。この考え方で、コード(特にコメント)を参照し、「問題の全体像を理解して問題を絞り込めるようにするのは簡単ですか?」と考えます。もしそうなら、それはパスです。そうでなければ、それは失敗です。少なくとも追加のドキュメントが必要です。または、コードを合理的に理解できるようにするために、おそらくリファクタリングが必要です。

それがあなたの雇用者が求めているものであることが確かでない限り、それについて完璧主義者にならないことが重要です。ほとんどのコードは非常に多くのコードを吸引するため、連続して10回簡単にリファクタリングでき、そのたびに読みやすくなります。しかし、雇用主はおそらく、世界で最も読みやすいコードを用意するためにお金を払いたくないでしょう。

30
DepressedDaniel

ただし、コードレビューを使用して全体的な正当性を手動で確認することは、たとえそれが可能であっても、非常に困難で時間がかかります。

何年も前、学生の宿題を採点することはまさに私の仕事でした。そして、多くの人がバグをあちこちに置いてある程度の妥当な品質を提供しましたが、目立ったのは2人でした。どちらも常にバグのないコードを送信しました。提出されたコードの1つは、上から下まで高速で読み取ることができ、ゼロの労力で100%正しいとマークできます。もう1つは、次々とWTFであるコードを送信しましたが、なんとかしてバグを回避することができました。マークする絶対的な痛み。

今日、2番目のものは、コードレビューで彼のコードが拒否されました。正当性の検証が非常に困難で時間がかかる場合、それはコードの問題です。きちんとしたプログラマーは、問題を解決する方法を理解し(時間Xがかかります)、コードレビューに渡す前に、問題をリファクタリングするだけでなく、明らかにで問題を解決します。時間はXよりはるかに短く、将来的には多くの時間を節約できます。多くの場合、コードレビューの段階に進む前にバグを発見します。次に、コードレビューを大幅に高速化します。そして、いつの時代もコードをより簡単に適応させることによって。

別の回答によると、一部の人々のコードは10回リファクタリングされ、そのたびに読みやすくなる可能性があります。それはただ悲しいことです。それは別の仕事を探すべき開発者です。

15
gnasher729

これは古いコード少し変更されましたか? (10000行のコードベースで変更された100行のコードは、まだわずかな変更です)時々、時間の制約があり、開発者は、古くて不便なフレームワーク内に留まることを余儀なくされます。 。 +通常、リスクが伴い、誤って評価すると数百万ドルの費用がかかる可能性があります。それが古いコードである場合、ほとんどの場合、あなたはそれとともに生きる必要があります。自分でそれを理解できない場合は、彼らと話し、彼らの言うことに耳を傾け、理解してみてください。覚えるのは難しいかもしれませんが、他の人にとっては問題ありません。彼らの側を取り、彼らの端からそれを見てください。

これは新しいコードですか?時間の制約に応じて、できる限りリファクタリングすることを推奨する必要があります。必要に応じて、コードレビューにより多くの時間を費やしてもかまいませんか。自分自身を15分にタイムボックス化して、アイデアを得て次に進むべきではありません。著者が何かを書くのに1週間を費やした場合、それをレビューするのに4-8時間を費やしても大丈夫です。ここでの目標は、リファクタリングを支援することです。 「今すぐリファクタリングする」というコードを返すだけではありません。分解できるメソッドを確認し、新しいクラスを導入するためのアイデアを考えてみてください。

6
Neolisk

多くの場合、「複雑な」パッチ/変更リストは、一度に多くの異なることを行うものです。新しいコード、削除されたコード、リファクタリングされたコード、移動されたコード、拡張されたテストがあります。全体像が見えにくくなります。

よくある手がかりは、パッチが巨大であるが、その説明が小さいことです:「$ FOOを実装する」。

このようなパッチを処理する合理的な方法は、パッチを一連の小さな自己完結型のピースに分割するよう依頼することです。単一責任の原則が、関数は1つのことだけを行うべきであると述べているように、パッチも1つのことだけに焦点を当てるべきです。

たとえば、最初のパッチには、機能的な変更を行わない純粋に機械的なリファクタリングが含まれている場合があり、最後のパッチは、実際の実装と$ FOOのテストに集中でき、気晴らしと赤のニシンが少なくなります。

多くの新しいコードを必要とする機能の場合、シリーズの最後のパッチが実際に新しいコードを呼び出す(フラグフリップ)までは、製品の動作を変更しないテスト可能なチャンクに新しいコードを導入できることがよくあります。

これを巧みに行うことについて、私は通常、それを私の問題として言葉にして、作者の助けを求めます:「ここで行われているすべてのことを実行するのに問題があります。一緒?"場合によっては、小さなステップについて具体的な提案をする必要があります。

「Implement $ FOO」のような大きなパッチは、次のような一連のパッチに変わります。

  1. $ FOOを実装するには、ベクトル以外のシーケンスで呼び出す必要があるため、イテレータのペアを使用するFrobnicateの新しいバージョンを導入します。
  2. Frobnicateの既存のすべての呼び出し元を、新しいバージョンを使用するように切り替えます。
  3. 古いフロブニケートを削除します。
  4. Frobnicateはやりすぎでした。 refrumpleステップを独自のメソッドに組み込み、そのためのテストを追加します。
  5. テスト付きのZerzifyを紹介します。まだ使用していませんが、$ FOOに必要です。
  6. Zerzifyと新しいFrobnicateの観点から$ FOOを実装します。

手順1〜5では、製品の機能が変更されないことに注意してください。それらはあなたがすべての正しいテストを持っていることを確実にすることを含めて、レビューするのは簡単です。ステップ6がまだ「複雑」でも、少なくとも$ FOOに焦点を合わせています。そしてログは当然$ FOOがどのように実装されたのか(そしてFrobnicateが変更された理由)についてより良い考えをあなたに与えます。

2
Adrian McCarthy

他の人が指摘したように、コードレビューは実際にバグを見つけるようには設計されていません。コードレビュー中にバグを発見している場合は、おそらく十分な自動テストカバレッジ(ユニット/統合テストなど)がないことを意味します。 コードが想定どおりに機能することを確信させるのに十分なカバレッジがない場合の場合、私は通常、より多くのテストを要求し、探している種類のテストケースを指摘し、通常はコードを適切なカバレッジを持たないコードベース。

高レベルのアーキテクチャが複雑すぎたり、意味がわからない場合は、通常、チームのメンバー数名とのミーティングに電話して話し合います。悪いアーキテクチャで繰り返すのは時々難しいです。開発者が初心者である場合、私は通常、悪いプルリクエストに反応するのではなく、彼らの考えがahead時間であるかを確認するようにします。これは通常、経験豊富な開発者であっても、問題が明らかに選ばれる可能性が高い明らかな解決策がない場合に当てはまります。

複雑さがメソッドレベルに分離されている場合、通常は反復的に、適切な自動テストで修正できます。

最後のポイントです。レビュー担当者は、コードの複雑さが必須によるものか偶発的複雑性によるものかを判断する必要があります。本質的な複雑さは、解決するのが正当に難しいソフトウェアの部分に関連しています。偶然の複雑さとは、理由もなく複雑すぎて簡単に簡略化できる、私たちが作成したコードの他のすべての部分を指します。

私は通常、本質的に複雑なコードが本当にそれであり、さらに単純化できないことを確認します。また、これらのパーツについて、より多くのテストカバレッジと優れたドキュメントを目指しています。偶発的な複雑さは、ほとんどの場合、プルリクエストプロセス中にクリーンアップする必要があります。これらは、私たちが扱うコードの大部分であり、短期的にもメンテナンスの悪夢を引き起こしやすいためです。

1
c_maker

テストはどのようなものですか?それらは明確で、シンプルで、理想的には1つのアサートのみで読みやすいものでなければなりません。テストでは、コードの意図する動作と ユースケース を明確に文書化する必要があります。

十分にテストされていない場合は、レビューを開始するのに適しています。

0
Tom Squires