入力パラメータの変更による予期せぬ副作用を防ぐためのベストプラクティス

入力パラメータの変更による予期せぬ副作用を防ぐためのベストプラクティス プログラミング

関数の入力パラメータを変更することは、予期せぬ副作用を引き起こす可能性があります。
本記事では、入力パラメータの変更によって発生する問題と、それを防ぐためのベストプラクティスについて解説します。

入力パラメータの変更がもたらす問題

以下のコードは、ユーザーの残高を更新する関数の例です。

def update_user_balance(user, amount):
    user['balance'] += amount
    save_user_to_database(user)

user = {'id': 1, 'name': 'Alice', 'balance': 1000}
update_user_balance(user, 500)
print(user['balance'])  # 1500

この関数は、ユーザーの残高を更新し、データベースに保存することを目的としています。
しかし、関数内で入力パラメータ user を直接変更しているため、呼び出し元の user オブジェクトにも影響を与えてしまいます。

これは、呼び出し元にとって予期せぬ動作となる可能性があります。
呼び出し元は、user オブジェクトを関数に渡しても、そのオブジェクトが変更されないことを期待するかもしれません。

入力パラメータの変更による問題は、以下のようなものがあります。

  1. 呼び出し元のコードに予期せぬ影響を与える
  2. バグの原因となる
  3. コードの理解を困難にする

解決策: 新しいオブジェクトを返す

入力パラメータを変更せずに、新しいオブジェクトを返すことで、予期せぬ副作用を防ぐことができます。

def update_user_balance(user, amount):
    updated_user = user.copy()
    updated_user['balance'] += amount
    save_user_to_database(updated_user)
    return updated_user

user = {'id': 1, 'name': 'Alice', 'balance': 1000}
updated_user = update_user_balance(user, 500)
print(user['balance'])  # 1000
print(updated_user['balance'])  # 1500

この例では、update_user_balance 関数内で user オブジェクトのコピーを作成し、そのコピーに対して残高の更新を行っています。
そして、更新後のオブジェクトを返しています。

これにより、呼び出し元の user オブジェクトは変更されず、予期せぬ副作用を防ぐことができます。

パフォーマンスへの影響を考慮する

入力パラメータを変更せずに新しいオブジェクトを返すことは、メモリ使用量や実行時間に影響を与える可能性があります。
特に、大量のデータを扱う場合や、パフォーマンスが重要な場合は、入力パラメータを変更せざるを得ないこともあります。

その場合は、関数名やドキュメントで入力パラメータが変更されることを明示し、呼び出し元が適切に対処できるようにします。

def sort_list_in_place(lst):
    """
    リストを in-place でソートする関数
    
    注意: この関数は入力リストを変更します
    """
    lst.sort()

numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
sort_list_in_place(numbers)
print(numbers)  # [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

この例では、sort_list_in_place 関数は、パフォーマンス上の理由から入力リストを直接変更しています。
ただし、関数名と docstring で入力リストが変更されることを明示的に説明しています。

まとめ

入力パラメータを変更することは、予期せぬ副作用を引き起こす可能性があります。
新しいオブジェクトを返すことで、予期せぬ副作用を防ぐことができます。

ただし、パフォーマンスが重要な場合は、入力パラメータを変更せざるを得ないこともあります。
その場合は、関数名やドキュメントで変更を明示し、呼び出し元が適切に対処できるようにします。

入力パラメータの変更に注意することで、バグを減らし、コードの理解を容易にすることができるでしょう。

タイトルとURLをコピーしました