Мы все любим REST, особенно когда речь идет о разработке API. Делая это в последние годы, я всегда сталкиваюсь с одной и той же проблемой: вложенными ресурсами. Кажется, мы живем по двум краям шкалы. Позвольте мне привести пример.
/galaxies/8/solarsystems/5/planets/1/continents/4/countries.json
Neato. Подобные случаи, кажется, случаются повсюду, независимо от того, в какой форме они материализуются. Теперь я хотел бы иметь возможность выбирать все страны в солнечной системе, в то же время имея возможность выбирать страны с высокой степенью охвата, как показано выше.
Кажется, у меня есть два варианта здесь. Во-первых, я сглаживаю свою вложенную структуру и ввожу множество параметров GET (которые должны быть хорошо документированы и поняты моим пользователем API), например так:
/countries.json?galaxy=8&solarsystem=5&planet=1&continent=4
Я мог бы сгладить все свои ресурсы и выиграть уникальный базовый URL-адрес для каждой конечной точки. Хороший момент ... уникальные конечные точки на ресурс!
Но какова цена? То, что не кажется естественным, не обнаруживается и не ведет себя как древовидная структура под моими ресурсами. Вывод: плохая идея, но хорошо отработанная.
С другой стороны, я мог бы попытаться избавиться от как можно большего количества дополнительных параметров GET, создавая конечные точки, подобные этому:
/galaxies/8/solarsystems/5/countries.json
Но мне также нужно было:
/galaxies/8/solarsystems/5/planets/1/continents/4/countries.json
Кажется, это другая сторона шкалы. Наименьшее количество дополнительных параметров GET, более естественное поведение, но все же не то, что я ожидал как пользователь API.
Большинство API, с которыми я работал в прошлом году, следуют той или иной парадигме. Кажется, есть хотя бы одна пуля, чтобы кусать. Так почему бы не сделать следующее:
Если есть ресурсы, которые вложены естественным образом, давайте вложим их точно так, как мы ожидаем, что они будут вложенными. То, что мы достигаем, - это, во-первых, уникальная конечная точка для каждого ресурса, когда мы остаемся такими:
/galaxies.json
/galaxies/8/solarsystems.json
/galaxies/8/solarsystems/5/planets.json
/galaxies/8/solarsystems/5/planets/1/continents.json
/galaxies/8/solarsystems/5/planets/1/continents/4/countries.json
Хорошо, но как решить начальную проблему, я хотел собрать все страны в солнечной системе, при этом имея возможность выбирать страны, полностью ограниченные галактиками, солнечными системами, планетами и континентами? Вот что для меня естественно:
/galaxies/8/solarsystems/5/planets/0/continents/0/countries.json # give me all countries in the solarsystem 5
/galaxies/8/solarsystems/0/planets/0/continents/0/countries.json # give me all countries in the galaxy 8
… и так далее, и так далее. Теперь вы можете возразить: «Хорошо, но ноль есть…», и вы правы. Выглядит не очень красиво. Так почему бы не изменить два верхних вызова на что-то подобное:
/galaxies/8/solarsystems/5/planets/all/continents/all/countries.json # give me all countries in the solarsystem 5
/galaxies/8/solarsystems/all/planets/all/continents/all/countries.json # give me all countries in the galaxy 8
Аккуратно, а? Так чего же мы достигаем? Никаких дополнительных параметров GET и все еще стабильных базовых URL для каждой конечной точки ресурсов. Сколько стоит? Да, по крайней мере, длинные URL-адреса, особенно во время ручного тестирования с использованием таких инструментов, как curl.
Интересно, может ли это улучшить не только удобство обслуживания, но и простоту использования API. Если так, то почему никто так не подходит? Я не могу себе представить, чтобы быть первым с такой идеей. Таким образом, должны существовать встречные аргументы против такого подхода. Я не вижу никого. Вы?
Мне бы очень хотелось услышать ваше мнение и аргументы за или против такого подхода. Может быть, есть идеи по улучшению ... было бы здорово услышать от вас. На мой взгляд, это может привести к гораздо лучше структурированным API, так что, надеюсь, кто-то прочтет это и ответит.
С уважением.
Jan