ОБЩАЯ ИНФОРМАЦИЯ
Предположим, у вас есть веб-служба (SOAP) BookService
, управляющая книгами в библиотеке. В информационной модели предполагается, что объект Book
имеет следующие атрибуты:
id
author
publisher
title
shelfId
Для управления данными определены четыре операции веб-сервиса:
AddBook
GetBook
UpdateBook
DeleteBook
Запрос и ответное сообщение определяются для каждой операции. Однако структура XML-схем сообщений об обновлении более сложна. Мы хотели бы достичь следующих качеств:
- R1: Возможность сбросить/удалить предыдущие значения атрибута. Например. скажите, что вы больше не будете хранить книгу в библиотеке и тем самым хотели бы сбросить/очистить/удалить значение атрибута
shelfId
для этой конкретной книги. - R2: Избегайте болтовни в веб-службах. См. службы Chatty против шаблонов.
- R3: подготовьтесь к будущим требованиям к управлению параллелизмом и оптимистичной блокировке. Мы можем свести к минимуму (или устранить) риск внесения обновлений на основе старой информации.
ДИЗАЙН АЛЬТЕРНАТИВЫ
Я вижу три альтернативы мэра, одна из которых имеет несколько дополнительных опций, для разработки сообщений об обновлении:
- Отправить весь бизнес-документ. Пропущенные элементы (имеющие
minOccurs="0"
в схеме) ИЛИ элементы, для которых явно установлено значение null, т. е.<shelfId xsi:nil="true"/>
, будут интерпретироваться как удаление предыдущих значений. - Highlight the changes or send only the diff.
- Send the entire business document, but mark the modified elements using an attribute specific to this purpose. Example:
<author dirty="true">Hemingway<author/>
. The provider of the service then updates only those elements marked as dirty and ignores the other ones. - В схеме сообщения установите для всех элементов, кроме идентификатора
id
, значениеminOccurs="0"
. Потребитель отправляет только те элементы, которые должны быть изменены. Пропущенный элемент не должен не семантически интерпретироваться как удаление. Чтобы удалить значение, необходимо использовать явное значение XMLNULL
. Пример:<shelfId xsi:nil="true"/>
. - Отправьте весь деловой документ, но также отправьте копию ранее прочитанного документа. Затем провайдер может сравнить два документа и обновить только те атрибуты, по которым отличаются новый и предыдущий документы.
- Send the entire business document, but mark the modified elements using an attribute specific to this purpose. Example:
- Определите несколько операций. Вместо использования одной операции,
UpdateBook
, определите несколько операций, исходя из того, какие элементы, по вашему мнению, должны быть обновлены, например.UpdateBookAuthor
,UpdateBookPublisher
и так далее. Каждый из них будет иметь только обязательные элементы, а для удаления элементов используйте явный NULL XML, например.<shelfId xsi:nil="true"/>
.
ОБСУЖДЕНИЕ
Преимущество Alt 3 состоит в том, что его легко понять, но недостатком является то, что потребителям придется вызывать несколько операций, если необходимо обновить несколько полей в объекте Book
. Это делает службу «болтливой» (см. R3 выше), что приводит к снижению производительности.
Альтернативный вариант 2 сложнее, чем Альтернативный вариант 1, но у Альтернативный вариант 2 есть некоторые преимущества, связанные с оптимистичным контролем параллелизма:
- Для ситуаций, когда оптимистическая блокировка с отметками времени/версиями для каждого поля хранится в базе данных (например,
authorVersion
) => Alt 2 позволяет нескольким пользователям изменять разные части, такие какauthor
иpublisher
, то же самоеBook
одновременно с меньшим риском возникновения неисправностей. - Для ситуаций, когда оптимистическая блокировка с одной единственной отметкой времени/версией для всего
Book
хранится в базе данных => Нет реального преимущества Alt 2 по сравнению с Alt 1. Даже если обновление изменяет только одно поле, слишком старый номер версии запроса приведет к ошибке. - В ситуациях, когда не используется управление параллелизмом или оптимистичная/пессимистическая блокировка => Альтернативный вариант 2 дает меньший риск перезаписи старых данных, чем Альтернативный вариант 1, но все же другие несогласованные изменения могут привести к проблемы.
Существует еще одна ситуация, когда Alt 2 (и Alt 3) дает преимущество перед Alt 1. Потребитель не может хранить все данные об объекте Book
. Например, робот, собирающий книги с полки, может быть запрограммирован более эффективно, если ему не нужно отслеживать (кэшировать) информацию об авторе, а только полку при обновлении информации о полке.
Преимущество подхода в Alt 2.3, когда потребитель отправляет целые копии предыдущих версий вместо номеров версий или временных меток, заключается в том, что для номера версии или временной метки не требуется специальный столбец в базе данных.
Подводя итог, я бы сказал, что Alt 2.2 выглядит наиболее привлекательным для большинства случаев. Проблема здесь заключается только в том, что фреймворки, десериализующие XML, должны уметь отличать пропущенный элемент от элемента, для которого явно задано значение NULL, например. <shelfId xsi:nil="true"/>
. См. пост на эту тему здесь.
ВОПРОС
Какой из вариантов вы бы выбрали? Видите ли вы другие, лучшие альтернативы? Что вы думаете об обсуждении?