コードレビューのために送信されたコードが複雑すぎると思われる場合の対処方法


115

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

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


4
現れるか?ソースファイルをすばやく測定することで、疑いを確認または拒否できます。測定後は、コードレビューで測定値を表示し、複雑さの数値をリファクタリングすることを提案します。
ジョンレイナー



4
「複雑すぎる」と定義してください。チームに馴染みのない既知のデザインパターンを使用しているため、またはチームに既知のパターンを使用できないために、コードが複雑すぎますか?「複雑すぎる」コードを判断する正確な理由は、今後の進め方を正しく評価するために不可欠です。コードレビューと同じくらい深く複雑な知識領域に関する「複雑すぎる」という単純な記述は、開発者の魔女狩りを示唆しています。
ピーターギアケンズ

7
@PieterGeerkensまたは、おそらく、複雑な問題を解決しているので、複雑すぎますか?
ケーシー

回答:


251

レビューできない場合、レビューに合格できません。

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

複雑すぎる場合は、大量の固い原則に違反しています。リファクタリング、リファクタリング、リファクタリング。それを適切に名前を付けた関数に分割し、それらの関数がはるかに少ない単純な処理を行います。あなたはそれをきれいにすることができ、あなたのテストケースはそれが正しく動作し続けることを確認します。テストケースはありますか?そうでない場合は、追加を開始する必要があります。


49
これ。このコードを読むのはあなたと作家だけではないことを忘れないでください。また、10年後にはランダムなインターンになるので、何が起こっているのかを理解できるようにする必要があります。
デビッドグリンバーグ

2
いい答えだ。「コードレビュー」の目的に依存します。読みやすさは一つのこと、構造は別のことです-しかし、それらは非常に密接に関連しています。fwiw MAJOR corpsによって書かれたいくつかのオープンソースで作業していますが、varとfnの名前は非常に頭がおかしいのでほとんど読めません。

19
@DavidGrinbergすべての実用的な目的のために、「あなたは6ヶ月で」は完全に異なる人です。
クリリス

2
しばらくコードを片付けます(彼がすべてを覚えていないのに十分な長さ)。元のコーダーに確認してもらいます。HEがそれを理解しているかどうかを確認します。
ネルソン

4
私は、バグを見つけるためのコードレビューが「そうではない」ことに同意しません。多くの場合バグを見つけますが、それはコードレビューの非常に強力で便利な側面です。さらに良いことに、将来のコードでバグを完全に回避する方法を見つけるのに役立ちます。ポイントはおそらく誇張されており、バグを見つけることだけではないはずです!
コーディグレイ

45

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

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

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

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


30

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

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

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


4
素晴らしいコメント!私はそれ:)をすることの有罪となっている、ボーイ「ほとんどのコードは、それが簡単にするたびに読みやすくなって、行に10回をリファクタリングすることができるように多くを吸う」
ディーン・ラドクリフ

1
「ほとんどのコードは非常にひどいため、10回連続で簡単にリファクタリングでき、毎回読みやすくなります。」確かに、それは現実の世界でのやり方です。
ピーターモーテンセン

@PeterMortensen現実世界で多くのことを見つけるのは確かに本当です。しかし、コードをそのように記述することは誰の利益にもなりません。そのようになっているのには2つの理由があると思います。開発者が受ける教育は、読み取り可能なコードの記述方法を教えることにほとんど労力を注ぎません。また、一部のビジネスでは、時間の無駄だと認識されています。「開発者が既に作業コードを書いている場合、読み取り可能かどうか気にする必要があるのはなぜですか?出荷するだけです。」
カスペルド16

15

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

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

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

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


コードを10回リファクタリングするのにかかる時間がはるかに短くなり、コードの最初のバージョンを書くのに時間がかかります。他の誰かが私がこのリファクタリングを行ったことを知っている場合、私は失敗しました。
イアン

6

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

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


2
「今すぐリファクタリング」というコードを返すだけではありません -なぜですか?少なくとも一度はそのようなレビューコメントを受け取りましたが、前回は役に立ち、正しいことがわかりました。大きなコードの塊を一から書き直す必要がありましたが、これを行うのは正しいことでした。振り返ってみると、古いコードは修復不可能な混乱であると自分自身で見たからです。レビューはそれに気づくために資格だけで十分だった(と私は明らかにしなかった)
ブヨ

4
@gnat:1つは、失礼だからです。コードの何が問題なのかを説明し、他の人がコードを改善できるように努力すると、見栄えが良くなります。大企業では、そうしないとすぐに出て行ってしまう可能性があります。特に、上級者のコードを確認する場合。
ネオリスク

私は上記の言及その場合には、それだけでは十分注意して起こった大規模な設立された会社にあったではないに尋ねたときに、少なくとも直接ではなく、その技術的な専門知識を共有することを理由に、彼らの最も優秀な開発者がドアから抜け出す
ブヨ

1
@gnat:「今すぐリファクタリング」というアプローチは下向きに機能します。つまり、10年以上の経験を持つ上級開発者が、1か月前に経験のない、または同様の状況で雇用されたジュニア開発者にリファクタリングする場合。上向き-問題があるかもしれません。他の開発者がどれだけの経験を持っているかわからない場合があるため、デフォルトの振る舞いとして敬意を払っても安全です。確かにあなたを傷つけることはありません。
ネオリスク

1
@Neolisk:時間の制約の下でコードを書く必要があり、それが十分ではないことを知っている経験豊富な開発者は、コードを拒否して、彼に時間とそれを改善する口実を与えた場合にのみ幸せになるかもしれません。PHBで十分だと判断すると、開発者は不幸になります。それが十分ではないと判断したレビュアーは彼を幸せにします。
gnasher729 16

2

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

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

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

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

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

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

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

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

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


Gitを使用する場合の1つのアプローチは、複数のコミットのプルリクエストを作成することです。各コミットは可能な限りアトミックで自己完結型であり、独自の説明があります。次に、PRの本文に、各変更を手動で確認できるという便利なメモを追加します。それは一般に、グローバルなリファクタリングや大きな、攻撃できないツールの変更など、非常に大きなPRを扱う方法です。
ジミーブレックマッキー

1

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

高レベルのアーキテクチャが複雑すぎたり、意味をなさない場合は、通常、チームメンバー数人と会議を開いて話し合います。悪いアーキテクチャを反復処理するのは難しい場合があります。開発者が初心者の場合、通常、悪いプルリクエストに反応するのではなく、彼らの考えが事前に確認されるようにします。これは、問題が選択される可能性が高い明らかな解決策を持たない場合、経験豊富な開発者でも通常当てはまります。

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

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

私は通常、本質的に複雑なコードが本当にそれであり、さらに単純化できないことを確認します。また、これらの部品のより多くのテスト範囲と優れたドキュメントを目指しています。プルリクエストプロセス中は、偶発的な複雑さをほぼ常にクリーンアップする必要があります。これらは処理するコードの大部分であり、短期間でもメンテナンスの悪夢を簡単に引き起こす可能性があるためです。


0

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.