今日コードレビューを行っていたところ、コードが機能するが、簡単に読みやすくできることに気づきました。
具体的な例は、おおよそ次のとおりです。
def group(x):
GROUP_ALPHA = ('a', 'b', 'e', 'f', 'i', 'j', 'k', 'l')
GROUP_BETA = ('m', 'n', 'o', 'p', 'q')
GROUP_CHARLIE = ('x', 'y', 'z', 'aa', 'ab', 'ae', 'af')
GROUP_DELTA = ('ag', 'ah', 'ai', 'aj')
GROUP_ECHO = ('ak', 'al', 'am', 'an', 'ao', 'ar', 'as')
if x in GROUP_ALPHA:
return 'ALPHA'
Elif x in GROUP_BETA:
return 'BETA'
Elif x in GROUP_CHARLIE:
return 'CHARLIE'
Elif x in GROUP_DELTA:
return 'DELTA'
Elif x in GROUP_ECHO:
return 'ECHO'
すべてのグループがばらばらであることに注意してください。
私にとっては、これは次のように読みやすくなります:
def group(x):
GROUPS = {
'ALPHA': ('a', 'b', 'e', 'f', 'i', 'j', 'k', 'l'),
'BETA': ('m', 'n', 'o', 'p', 'q'),
'CHARLIE': ('x', 'y', 'z', 'aa', 'ab', 'ae', 'af'),
'DELTA': ('ag', 'ah', 'ai', 'aj'),
'ECHO': ('ak', 'al', 'am', 'an', 'ao', 'ar', 'as')
}
for group_name, group_elements in GROUPS:
if x in group_elements:
return group_name
これについて言及する必要がありますか?元のコードは機能し、重要ではない容量で使用されます。調べていたところ、 この答え に気づきました。
すべての変更にはお金がかかります。機能し、変更する必要がないと思われるコードを書き直すことは、無駄な労力となる可能性があります。変更の対象となるセクション、またはプロジェクトにとって最も重要なセクションに注意を向けます。
これは答えがノーであることを示唆しますが、元の方法が「機能する」としても、コードレビューをすることは無駄であり、物事を行うためのより良い方法を示唆しないようです。個人的に私は誰かにそのような提案をしてほしいです。
注:上記の例は、質問が最初に作成されてから編集されています。同様に、各エントリ('a'
、'b'
など)は、実際にはビジネスロジックに関連する人間が読めるstr
です。
与えられた例では、IMHOは読みやすさに大きな違いはありません。実際、2番目のバリアントが最初のバリアントよりも実際に読みやすいかどうかは、かなり議論の余地があります。ただし、これは明らかに [〜#〜] dry [〜#〜] の原則に従うことによる改善であり、これは非常に有効な理由ですコードを変更します。
これらすべてのグループを常に同様の方法で処理することを意図しているとしましょう。おそらくそうなると思います。また、これらのグループが少なくとも5つあると仮定します。これで、ロジックを次のように変更するという新しい要件が得られます
if lower(x) in GROUP_ALPHA:
次に、最初の例では、5つの場所を変更する必要があります。それらを同じように変更し、場所を忘れないようにしてください。 2番目の例では、変更する場所は1つだけです。これは間違いなく改善です。さらに、この関数、または特にこの関数の変更の単体テストを作成する場合、最初のバリアントは完全なカバレッジを達成するために5つの異なるテストケースを必要とし、2つ目は1つだけをテストします。
さらに簡単です-別のグループを追加するだけだと仮定します-最初の例では、コードの2か所を変更する必要があります(「検索」セクション全体のコピーを含みます)。2番目の例では、辞書。
コードを保持するDRYは、単に「味」の問題ではありません-コードを将来の頭痛の原因となる可能性が低い状態にすることです。そして、コードレビューは、この。
コードレビューの利点の1つは、実際に、より良い方法を提案することです。もちろん、より良いとは異なるコンテキストで異なることを意味しますが、より読みやすく、より高速で、より少ないメモリを消費し、優れた設計原則に従い、より複雑ではないなどのコードを含めることができます。より読みやすい変更の提案は完璧な例ですコードレビューの際に注意すべき点があります。
すべての変更にはお金がかかりますが、6か月後の悪質に記述されたコードを解読しようとする場合もそうです。
ただし、対象読者を念頭に置いて、読みやすいだけでなく他の人には読みにくい可能性があることを認識してください(特に、多くのジュニアエンジニアと作業している場合)。また、これらの変更を提案するときは、アプリケーション環境/ニーズを念頭に置いてください。ソリューションはより高速かもしれませんが、より高速なコードは必要ないかもしれません。辞書に3つの要素のリストにマップする2つのキーのみが含まれる場合、設定方法に関係なく、パフォーマンスに問題はありません。残りのチームは次回からそれを使用できるので、おそらく立ち上げる価値はありますが、これはすぐに掘り下げるものではないことを理解してください。
提案された変更は微妙なバグをもたらすので、これは提案が慎重に吟味されるべき理由の良い例だと思います。
x
が複数のグループのメンバーである場合、最初の例は、if
の明示的な順序で見つかったfirstグループを返します。 2番目の例では、グループは不特定の順序でチェックされます(辞書は順序付けされていないため)。したがって、どのグループが返されるかは定義されていません。 mightは単体テストで予想される出力であるため、これは特に油断できませんが、別のプラットフォームまたはバージョンの更新によって変更される可能性があります。
根本的な問題は、新しいコードが意図を明確に伝えていないことです。期待される結果が実際に非決定的である場合、ドキュメントでそれを明確に伝達する必要があると思います。これは、「最小の驚きの原則」を確実に破るからです。
一方、xが正確に1つのグループに現れることを期待する場合、これを明確に伝えるためにデータ構造を変更する必要があると思います。
def group(x):
GROUPS = {
'a': 'ALPHA',
'c': 'ALPHA',
'd': 'ALPHA',
'h': 'BETA',
'k': 'BETA',
'l': 'BETA'
}
return GROUPS[x]
仮定は反復ループではなくデータ構造でエンコードされるため、これもはるかに単純なコードです。
とはいえ、コードレビューで読みやすさの改善を提案することは良い考えであることに同意します。しかし、これは実際にチームで話し合うべきことです。