可変長キーワード引数の濫用
名前: 可変長キーワード引数の濫用
症状: 同じパラメータ群を渡す関数がたくさんあるので、何でも #キーワード引数 で受け取って使う分だけアクセス 気分: 関数呼び出しごとに同じ引数を渡すコードを何度も書きたくない
code:python
TypeError: save_new_address() got multiple values for keyword argument 'tel_id'
code:repo.py
def save_new_address(user_id, tel_id, **kwargs):
# DB保存前になにかやるコードがあったり、なかったり
...
# DBに保存するコード
address.add(
user_id=user_id,
tel_id=tel_id,
**kwargs,
)
# もうちょっと長い
...
code:view.py
def submit_address_view(request):
# コード
data = validate(request.POST, submit_address_schema)
user_id = request.user.id
tel_id = repo.get_or_create(data'tel') save_new_address(user_id, tel_id, **data)
code:schema.py
submit_address_schema = {
'name': {'type': 'str', 'required': True},
'address': {'type': 'str', 'required': True},
'tel': {'type': 'str', 'required': False},
'tel_id': {'type': 'int', 'required': False},
... # 10個くらい続く
}
アンチパターン
関数が **kwargs で受け取った"期待しないパラメーター"telを無視している
save_new_address関数の引数が **kwargs なので、受け取りたいデータ構造(キー)が不明
submit_address_view関数が、schema validationで作ったdataをsave_new_addressに丸投げしていて、不要なデータが含まれている
代替案
関数引数を一つ一つ書く(**kwargsを使わない)ことで、関数が期待しない余計なパラメータを渡す事や、2重にキーワードを渡すことを避ける
validation schemaと連動したパラメータクラスを定義する(関数引数を複数書かずにクラスにまとめる)
「関数呼び出しごとに同じ引数を渡すコードを何度も書いている」時点で設計を見直した方がよい
ただし、クラス継承時のメソッドオーバーライド処理では必要な場合もある