2017-02-13 12 views
0

Я прочитал противоречивые «мнения» о том, следует ли удалять конверт по запросу или ответу JSON.Будущее доказательство: снимает ли конверт JSON текущую лучшую практику?

Пример:

{ 
    "data": { 
     "foo" : "bar", 
     "baz" : "Xyzzy" 
    } 
} 

должен (предположительно) быть записана в виде:

{ 
    "foo" : "bar", 
    "baz" : "Xyzzy" 
} 

Но, в соответствии с принципами ТВЕРДЫХ, эта структура должна быть открыта для расширения, но закрыты для модификации. Таким образом, удаление конверта было бы плохой идеей. Правильно?

Если, позже, я решаю, что мне нужно добавить еще немного информации для входящей информации JSON, гораздо чище, чтобы сделать это:

{ 
    "data": { 
     "foo" : "bar", 
     "baz" : "Xyzzy" 
    }, 

    "extended-data": { 
     "abc" : 123 
    } 
} 

чем это было бы сделать это:

{ 
    "foo" : "bar", 
    "baz" : "Xyzzy", 
    "abc" : 1234 
} 

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

Какова нынешняя передовая практика и, пожалуйста, сайт для ваших источников: Мне нужны общепринятые стандарты, а не мнения.

Update:

Чтобы ответить на возражение: «Если добавить поля, которые вы должны изменить свой код.»

Не совсем. Я не должен изменить код для обработки новых полей, я только добавить новый обработчик для новых данных:

Пример:

function delegateTask($json) { 
    $this->doSomething($json->data); 
} 

после расширения:

function delegateTask($json) { 
    $this->doSomething($json->data); 
    $this->doSomethingElse($json->extended); 
} 

Если Я использую только HTTP в качестве конверта, мне нужно перезаписать doSomething(). Если я делаю это SOLID, мне нужно только добавить функцию, которая смотрит на новые данные.

Не дублировать: Этот вопрос не является дубликатом When in my REST API should I use an envelope? If I use it in one place, should I always use it?, потому что этот вопрос конкретно касается принципов S.O.L.I.D и расширения для кода, как он относится к конверту. Не только сообщения об ошибках возвращаются клиенту.

+0

Если вы используете конверт или нет, вам все равно придется менять код для обработки новых полей. – codenheim

+0

Возможный дубликат [Когда в моем REST API я должен использовать конверт? Если я использую его в одном месте, должен ли я всегда использовать его?] (Http://stackoverflow.com/questions/9989135/when-in-my-rest-api-should-i-use-an-envelope-if- i-use-it-in-one-place-should-i) – jmargolisvt

+0

Я видел http://stackoverflow.com/questions/9989135/when-in-my-rest-api-should-i-use-an-envelope -ел-я потребительное это в одном месте, должен-я. Это похоже, но не то же самое. Да, HTTP «это конверт», но я специально прошу об этом в отношении принципов SOLID. – DrDamnit

ответ

0

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

Рассмотрите типы вещей, которые вы используете для использования API JSON. Сетки и т. Д. Разделение фактических данных от пейджинга и других метаданных менее хрупкое.

Я думаю, что вы можете применить «Я» в SOLID к этому.

Принцип разделения сегрегации - «многие клиентские интерфейсы лучше, чем один универсальный интерфейс.

С конвертом я могу использовать любую схему API и объединить ее с любым компонентом Javascript, который я выбираю, не беспокоясь о столкновениях или переименовывать поля, чтобы заставить работать.

То же самое относится к агрегации API. Я могу объединить два отдельных результата в одном вызове, чтобы обеспечить «модель представления», которая наиболее эффективна для конкретного использования. Легче объединить с конвертами.

Посмотрите на стандарты, такие как OData, много умных людей за этим стандартом.

Что касается расширений и жизненного цикла, я бы просто опубликовал API v2 и сохранил старый, пока он не устарел. Многоуровневое использование API-интерфейсов является обычной практикой (примеры: eBay, Salesforce).

1

Насколько я могу сказать, что это на самом деле об обработке сообщений, а также не относящиеся к JSON, REST, и т.д.

Бывший позволяет ранее написанный код, который ищет «данных» узла к выполняться без сбоев или изменений. Последнее требует, чтобы код был переписан для поиска нового значения.

Какова нынешняя передовая практика и, пожалуйста, разместите свои источники: мне нужны общепринятые стандарты, а не мнения.

Лучшая ссылка, которую я знаю, это Versioning in an Event Sourced System, автор Greg Young.

В коротком

  • Потребителей всегда готовит значение по умолчанию для любых данных, которые они ожидают, чтобы прочитать из сообщения, чтобы покрыть случай, когда данные не был предоставлен
  • Потребителей игнорируют данные, которые они делают не понимают
  • данных, предоставляемых провайдер вытесняет по умолчанию, предоставленное потребителю
  • семантики данных никогда не меняется; вместо этого вы удаляете старый смысл из схемы (потребители в зависимости от этого возвратятся к пониманию по умолчанию) и добавят новое значение (которое игнорируют существующие потребители).

Существует также ссылка Oracle на schema evolution, в которой описываются «модификации, которые вы можете безопасно выполнять для своей схемы без каких-либо проблем». Он ссылается на эти же правила.

Avro имеет данные schema migration rules, в которых описывается, как решена схема производителя и схема потребителя. Та же основная идея, с более подробной информацией об изменении типов данных.

RFC 4287 описывает требования «игнорировать иностранную разметку» в Atom Syndication. Versioning XML Vocabularies включает хорошее обсуждение Must Ignore.

Обратите внимание, что мы действительно говорим о модели обработки, как David Megginson points out. Гарантии совместимости являются следствием наличия правильной модели обработки.

, следует ли удалить конверт

Конверт выглядит как пустая трата времени для меня. Нет никакой полезной разницы между добавлением поля, значение которого является состоянием, и добавлением нового поля, которое содержит запись.

message.get('foo').orElse('baz') 

message.get('data').get('foo').orElse('baz') 

Извините, я не могу сказать разницы. Похоже на пролив велосипеда.

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

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

Так что, я убираю из вашего комментария следующее: если конверт обеспечивает смысловое значение, все в порядке. Можете ли вы привести пример?

Так что, с моей точки зрения, нет никаких оснований предпочесть какую-либо из следующего

get[xyzzy] 
get[data][xyzzy] 
get[data/xyzzy] 

Потому что «данные», в любой орфографии, не говорит ничего обработка двигателя полезного.

С другой стороны, разрывает сообщение на отдельные логические части, которые могут заинтересовать потребители. Рассмотрим событие HTTPRequestReceived - как могло выглядеть сообщение? Ясно, что мы беспокоимся о самом событии (чтобы наблюдатели могли оценить их интерес к сообщению) и данные о том, что было зарегистрировано), данные, возможно, оценка того, является ли это человеческим или бот-трафиком, источником событие ....

{ event : { type : HttpRequestReceived } 
, source : { logFile : ..., position : ... } 
, rawData : [ ... ] 
, botAnalysis : { ... } 
} 

Я мог бы так же легко использовать URI в качестве пространства имен.

Вы могли бы. Сексуальный вариант заключается в использовании в качестве ключей идентификатора, который может быть использован для поиска определения схемы

{ http://example.org/event : 
    { http://example.org/event/type : HttpRequestReceived } 
.... 

Schema.org имеет словарный запас общих понятий, которые предназначены для повторного использования

{ http://schema.org/dateCreated : 2017-02-13 } 
+0

Итак, я убираю из вашего комментария следующее: если конверт обеспечивает семантическое значение, все в порядке. Можете ли вы привести пример? Мне трудно думать о том, что я бы не просто реорганизовал другую службу. Я начинаю склоняться к удалению конверта; однако я просто не хочу останавливаться на коленях, разрабатывая решение, исключающее такую ​​передачу данных. Мне нравится концепция «конверт как пространство имен»; однако я мог бы так же легко использовать URI, как пространство имен. Мысли? – DrDamnit