複数戻り値(タプル)のレビュー:情報過多になっていないか
Pythonの関数では戻り値として複数の値を返すことが簡単にできる。これは非常に便利な一方で、関数の責務が曖昧になる原因や、コードの読みづらさを引き起こす要素にもなり得る。レビューアーは、単に「動いているか」を見るのではなく、戻り値がどのような意味を持ち、関数設計と整合しているかを構造的に判断する必要がある。
Pythonにおける複数戻り値の基本と乱用リスク
Pythonでは以下のように簡単に複数の戻り値を返すことができる。
複数戻り値の例
def analyze_text(text):
word_count = len(text.split())
char_count = len(text)
return word_count, char_count一見すると便利だが、次のようなコードを見るとどうだろうか。
情報過多な戻り値
def process_data(file_path):
status = True
warnings = []
parsed_rows = []
meta = {'source': file_path, 'parsed_at': '2024-06-01'}
return status, warnings, parsed_rows, meta過剰な戻り値の問題点
- 返される情報が多く、関数の目的が明確でなくなる
- 利用側が戻り値の順番や意味を把握する必要があり、認知負荷が高い
statusやwarningsなどは呼び出し側での処理ルールが不明瞭
レビューアーはこのような場合、「関数の粒度が適切か」「戻り値に責務の分離ができているか」を明確に指摘する必要がある。
戻り値の意味と構造を明示する改善方法
複数戻り値の情報が密結合になっている場合、NamedTupleやdataclassを使って構造を明示することが望ましい。
NamedTupleの活用
from typing import NamedTuple
class ParseResult(NamedTuple):
status: bool
warnings: list[str]
parsed_rows: list[str]
meta: dict
def process_data(file_path: str) -> ParseResult:
...
return ParseResult(status, warnings, parsed_rows, meta)あるいは、責務の分離を兼ねて dataclass を使うこともできる。
dataclassの活用
from dataclasses import dataclass
@dataclass
class ParseResult:
status: bool
warnings: list[str]
parsed_rows: list[str]
meta: dict
def process_data(file_path: str) -> ParseResult:
...
return ParseResult(...)こうした構造を使うことで、戻り値が「構造化された意味あるデータ」であると明示でき、読み手や保守者がコードの意図を理解しやすくなる。
構造イメージ
会話形式のレビュー例
レビュー対象コード
def fetch_config():
return True, "loaded", {"retry": 3}Comment
@Reviewer: 戻り値が順番依存かつ非構造的です。"True"と"loaded"の関係性が不明で、辞書がどの役割かも文脈から判断する必要があります。NamedTupleや構造体で意図を明示してください。改善案
class ConfigStatus(NamedTuple):
success: bool
message: str
config: dict
def fetch_config() -> ConfigStatus:
return ConfigStatus(True, "loaded", {"retry": 3})複数戻り値レビュー時のチェックポイント
結論とレビューアーの指摘視点
Pythonの複数戻り値は利便性が高い一方、構造的に乱用されると読み手に負荷を与える設計となりやすい。レビューアーは以下の点を重視してチェックすべきである:
- 戻り値が関数の責務を表現できているか
- 利用側の明快さ・保守性を阻害していないか
- 意図が構造的に明示されているか(構造体の導入提案)
可読性と再利用性の高いコードは、戻り値の設計にも表れる。意味ある設計を支援するレビューができるかどうかが、レビューアーの質を左右するポイントである。
