У нас есть веб-приложение, которое принимает пользовательский ввод или поиск в базе данных для формирования некоторых операций с некоторыми физическими ресурсами. Дизайн можно просто представить в виде следующей диаграммы:
пользовательский ввод <=> объект модели <=> хранилище базы данных
проверки необходимы при запросе, поступающем от пользовательского ввода, но НЕ при поступлении от обращений к поиску в базе данных (поскольку, если запись существует, эти атрибуты уже должны быть проверены ранее). Я пытаюсь реорганизовать код так, чтобы проверки происходили в конструкторе объектов, а не по-старому (отдельные процедуры проверки)
Как бы вы решили, какой путь лучше? (Принципиальное отличие метода 1 (старый способ) и 2 состоит в том, что проверки в 1 не являются обязательными и не связаны с созданием объекта, но 2 связывает их и делает их обязательными для всех запросов)
Вот два примера фрагментов кода для дизайна 1 и 2:
Метод 1:
# For processing single request.
# Steps: 1. Validate all incoming data. 2. instantiate the object.
ValidateAttribures(request) # raise Exceptions if failed
resource = Resource(**request)
Метод 2:
# Have to extract out this since it does not have anything to do with
# the object.
# raise Exceptions if some required params missing.
# steps: 1. Check whether its a batching request. 2. instantiate the object.
# (validations are performed inside the constructor)
CheckIfBatchRequest(request)
resource = Resource(**request) # raise Exceptions when validations failed
В пакетном запросе:
Способ 1:
# steps: 1. validate each request and return error to the client if any found.
# 2. perform the object instantiate and creation process. Exceptions are
# captured.
# 3. when all finished, email out any errors.
for request in batch_requests:
try:
ValidateAttribute(request)
except SomeException, e:
return ErrorPage(e)
errors = []
for request in batch_requests:
try:
CreatResource(Resource(**request), request)
except CreationError, e:
errors.append('failed to create with error: %s', e)
email(errors)
Метод 2:
# steps: 1. validate batch job related data from the request.
# 2. If success, create objects for each request and do the validations.
# 3. If exception, return error found, otherwise,
# return a list of pairs with (object, request)
# 4. Do the creation process and email out any errors if encountered.
CheckIfBatchRequest(request)
request_objects = []
for request in batch_requests:
try:
resource = Resource(**request)
except SomeException, e:
return ErrorPage(e)
request_objects.append((resource, request))
email(CreateResource(request_objects)) # the CreateResource will also need to be refactored.
Плюсы и минусы, как я вижу здесь:
- Метод 1 следует более близко к бизнес-логике. Никакой избыточной проверки не происходит, когда объекты поступают из базы данных. Процедуры проверки более удобны в обслуживании и читаются.
- Метод 2 облегчает и очищает вызывающего абонента. Проверки являются обязательными, даже если из db lookup. Валидации менее понятны и читаются.