/note/tech

バリデーション処理を柔軟に取り扱うサンプル

Functional Validatorのパクリみたいなものだけど。

class NotNullValidator:
    def check(self, target):
        if target.name is None:
            return [{
                "name": "名前を入力してください"
            }]
        else:
            return []


class ValidatorContainer:
    def __init__(self):
        self.validators = []

    def add(self, validator):
        self.validators[] = validator
        return self

    def check(self, target):
        errors = []
        for v in self.validators:
            errors. extend(v.check(target))
        return errors;


if __name__ == '__main__':
    user = User(name=None)
    container = ValidatorContainer()
                    .add(NotNullValidator())
                    .add(XXXValidator()) #チェックしたい項目を追加していく

    errors = container.check(user)

    if len(errors) == 0:
        print("エラーなし")
    else:
        print("エラーあり")

つまり、ValidatorContainerに詰め込むValidatorを自由に変更することで、処理に応じたバリデーションロジックを自由に組み替えることができるようになる。

ここではクラスを使っているが、Pythonなのでバリデーションは関数にした方がよりシンプルに書ける。

何故このような事にしているかと言うと、バリデーションは処理の内容によってチェックしたい項目とそうでない項目が発生する(例えば、ユーザーが下書きの場合と本登録の場合ではチェック内容が変わってくる)ので、バリデーションロジックが密結合していると使い勝手が悪い。

そこでバリデーションロジック自体は単機能の部品として切り分けておき(疎結合)、必要に応じてバリデーションロジックを選択可能にしている。

関連記事