8:インデックス番号に意味を持たせない

Pythonでリストやタプルの インデックス番号 を使ったほうが良いプログラムになる場合は、非常に稀です。 インデックス番号に意味を持たせてしまうとどうなるでしょうか?

具体的な失敗

from .item import item_exists


def validate_sales(row):
    """
    rowは売上を表すタプル
    1要素目: 売上ID
    2要素目: 商品ID
    3要素目: ユーザーID
    4要素目: 個数
    5要素目: 売上日時
    """
    # IDのチェック
    if not item_exists(row[1]):
        raise ...

    # 個数のチェック
    if row[3] < 1:
        raise ...

たとえば辞書であれば row['item_id'] のように、処理そのものが意味を表してくれます。 しかしこの例では処理の中で row のインデックス番号が意味を持っているので、プログラムが読みにくくなっています。 プログラムを読んでいるときに row[1] が商品IDであると覚えておかないといけません。

またインデックス番号で処理すると、間に新しい値が入ると処理が壊れます。 たとえば row の仕様が変わって2要素目に「販売店ID」が入るようになったとすると、それ以降の要素を指定する処理を書き換える必要があります。 その場合は、 row[3]row[4] にする必要があります。

ベストプラクティス

タプルで管理せず辞書やクラスにしましょう。 row のタプルを Sale というクラスに置き換えると、 validate_sales 関数がとても読みやすくなります。

@dataclass
class Sale:
    sale_id: int
    item_id: int
    user_id: int
    amount: int
    sold_at: datetime


def validate_sales(sale):
    """ 売上 sale が不正なデータの場合エラーを送出する
    """
    if not item_exists(sale.item_id):
        raise ...

    if sale.amount < 1:
        raise ...

cover

(中略)詳細は書籍 自走プログラマー をご参照ください