Как вы проверяете логику приложения, используя пирамидальный дуршлаг?

До сих пор я использую дуршлаг для проверки данных в моем приложении aiohttp.

Проблема, с которой я сталкиваюсь, заключается в том, что я не знаю, как сделать "глубокую" проверку.

Дана следующая схема:

import colander

class User(colander.MappingSchema):
    username = colander.SchemaNode(colander.String())
    password = colander.SchemaNode(colander.String())
    confirmation = colander.SchemaNode(colander.String())

Я проверяю, что во входной структуре данных есть все обязательные поля (для ясности ограничения минимальны), но мне также необходимо проверить, что:

  • username еще не занято другим пользователем
  • password а также confirmation подобные

Так что в моих контроллерах код выглядит следующим псевдокодом:

def create_user(request):
    user = await request.json()
    schema = User()
    # do schema validation
    try:
        user = schema.deserialize(user)
    except colander.Invalid, exc:
        response = dict(
            status='error',
            errors=errors.asdict()
        )
        return json_response(response)
    else:
        # check password and confirmation are the same
        if user['password'] != user['confirmation']:
            response = dict(
                status='error'
                errors=dict(confirmation="doesn't match password")
            )
            return json_response(response)
        # check the user is not already used by another user
        # we want usernames to be unique
        if user_exists(user['user']):
            response = dict(
                status='error',
                errors=dict(username='Choose another username')
            )
            return json_response(response)

        return json_response(dict(status='ok'))

В основном существует два вида проверки. Можно ли иметь обе логики в схеме одного дуршлаг? Это хороший шаблон?

1 ответ

Решение

Очевидно, что это дело вкуса, но ИМХО лучше держать проверку данных отдельно от логики приложения.

Вы также столкнетесь с несколькими проблемами, пытаясь подтвердить, что имя пользователя уникально:

  1. Дуршлаг должен иметь знания о вашем приложении, например. получить доступ к соединению с базой данных, чтобы проверить с базой данных, что это имя пользователя не существует.
  2. Colander (AFAIK) не настроен для асинхронного программирования, поэтому у него будут проблемы с async метод, который проверяет пользователя, существует.
  3. Вы действительно хотите, чтобы создание пользователя было ACID, поэтому одновременные вызовы create_user с одним и тем же именем пользователя невозможно создать двух пользователей с одним и тем же именем.

Проверка соответствия паролей - это еще одна история, которая не требует никаких знаний об остальном мире и должна быть довольно тривиальной с дуршлагом. Я не специалист по дуршлагу, но похоже, что вы можете использовать отложенный валидатор для проверки совпадения двух паролей.

Несколько других примечаний к вашему коду:

  1. create_user должен быть async метод
  2. Я ничего не знаю о вашей БД, но чтобы получить какое-либо преимущество от асинхронного программирования user_exists тоже должен быть асинхронным
  3. Проверка существования пользователя должна быть включена в создание пользователя ACID. Например. Вы должны использовать Postgres's on conflict или эквивалент, чтобы поймать дубликата пользователя при его создании, а не проверять, существует ли он первым
  4. Чтобы быть спокойным и упростить тестирование, ваше представление должно вернуть правильный http-код ответа на ошибку (в настоящее время вы возвращаете 200 для всех состояний). Вы должны использовать 201 для созданного, 400 для недействительной даты и 409 или конфликт имени пользователя.
Другие вопросы по тегам