Как правильно написать абстракции для взаимодействия с ресурсами RESTful? - PullRequest
0 голосов
/ 29 февраля 2012

У меня есть простой REST-клиент, который хорошо работает.В моем коде приложения я делаю что-то вроде этого:

restClient = new RestClient(configurationData)
restClient.get('/person/1') //Get Person
restClient.get('/equipment/auto/3') //Get an Auto
restClient.get('/house/7') //Get a House

Это работает хорошо, но все становится сложнее, и я хотел бы отделить код приложения от конкретных местоположений ресурсов.

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

restClient = new RestClient(configurationData)
restClient.getPerson(1) //Get Person
restClient.getAuto(3) //Get an Auto
restClient.getHouse(7) //Get a House

Я начал добавлять эти обертки в свой класс RestClient, но он очень быстро раздулся и почувствовал, что абстракция должна быть наболее высокий уровень.Смешивание спецификаций ресурсов с моим клиентом также показалось неправильным.

Итак, вместо этого я разделил на подклассы RestClient, и у каждого ресурса был свой класс.Проблема в том, что теперь мне нужно создать новый клиент для каждого типа ресурса:

personRestClient = new PersonRestClient(configurationData)
personRestClient.get(1);
autoRestClient = new AutoRestClient(configurationData)
autoRestClient.get(3);
housesRestClient = new HousesRestClient(configurationData)
housesRestClient.get(7);

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

Есть ли хороший пример или шаблон, которому я должен следовать, когда хочу написать абстракции для своих ресурсов?Моя база RestClient работает нормально, но мне не нравится помещать местоположения серверного API в код моего приложения.Но я также не хочу создавать экземпляр одного специализированного клиентского класса для каждого ресурса, с которым я хочу взаимодействовать.

Ответы [ 2 ]

1 голос
/ 01 марта 2012

Я думаю, что-то вроде этого, снова какой-то способ сопоставления ваших конечных точек для клиента. Вы можете иметь отображение в виде XML-файла или файла свойств, который можно загружать и кэшировать во время запуска приложения. Файл должен иметь пары ключ-значение PERSON_ENDPOINT = / человек / AUTO_ENDPOINT = / оборудование / авто / ... Клиент должен передать этот ключ фабрике, это может быть ClientFactory, который имеет этот кэш xml и извлекает конечную точку из кэшированного файла. Параметры могут быть переданы на завод как пользовательский объект или карта. Фабрика возвращает полную конечную точку, скажем, «/ person / 1», которую вы можете передать своему клиенту. Таким образом, вам не нужно иметь разные классы для клиента. Если вам не нравится XML или файл, вы можете использовать его в качестве статической карты с парами ключ-значение. Если это XML или файл, вам не нужно менять код каждый раз, когда это является преимуществом. Надеюсь, это поможет вам.

1 голос
/ 29 февраля 2012

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

Мой уровень пользовательского интерфейса должен выполнять вызовы в мою службу REST, поэтому я создал абстракцию под названием ServiceManagers.Interfaces.IAccountManager. Интерфейс имеет методы, называемые GetAccounts (Int64 userId).

Затем я создал Rest.AccountManager, который реализовал этот интерфейс, и внедрил его в свой AccountController. Rest.AccountManager - это то, что охватывает специфику REST (URL, get / post / put ..., параметры и т. Д.).

Итак, теперь мой код пользовательского интерфейса должен вызывать только accountManager.GetAccounts (userId). Вы можете создать всеобъемлющий интерфейс, чтобы у вас был только Get, но я чувствую, что он менее выразителен. Можно использовать много разных интерфейсов для каждого компонента (например, PersonManager, HouseManager, AutoManager), поскольку каждый из них представляет собой отдельную задачу, возвращающую разные данные. Не бойтесь иметь много интерфейсов и классов, если ваши имена выразительны.

В моем примере в моем пользовательском интерфейсе имеется отдельный менеджер для каждого контроллера, и выполненные вызовы соответствуют каждому контроллеру (т. Е. GetAccounts for AccountController, GetPeople for PeopleController).

Кроме того, что касается корневых данных конфигурации, вы можете просто использовать класс configurationCreationFactory или что-то еще. Таким образом, все реализации имеют соответствующую конфигурацию с базовой логикой в ​​одном месте.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...