좋아, 우리는 두 가지 자원을 가지고 Album
와 Song
. API는 다음과 같습니다.
GET,POST /albums
GET,POST /albums/:albumId
GET,POST /albums/:albumId/songs
GET,POST /albums/:albumId/songs/:songId
우리는 우리가 어떤 노래를 싫어한다는 것을 알고 Susy
있습니다. 우리는 어디에 search
행동 을해야 합니까?
다른 질문. 이제 더 현실입니다. 앨범 1을 열고 모든 노래를로드합니다. 우리는 JS 객체를 생성하고 각각 노래 데이터를 보유하며 다음과 같은 방법이 거의 없습니다 : remove
, update
.
노래 개체에는 ID, 이름 및 항목이 있지만 쿼리로 노래 목록을 검색하므로 부모 ID를 반환하는 것이 좋지 않기 때문에 어떤 부모가 속하는 지에 대한 실마리가 없습니다. 내가 잘못?
따라서 해결책이 거의 없지만 확실하지 않습니다.
-
부모 ID를 선택적으로 get-parameter로 설정하십시오. 이 접근법은 현재 사용하고 있지만 그 방법이 추악하다고 생각합니다.
List,Create /songs?album=albumId Update,Delete /songs/:songId Get /songs/?name=susy # also, solution for first question
-
잡종.
OPTIONS
메타 데이터를 얻기 위해 쿼리를 수행하려면 앨범 ID가 필요하기 때문에 편리 합니다.List,Create /album/:albumId/songs Update,Delete /songs/:songId POST /songs/search # also, solution for first question
-
각 리소스 인스턴스와 함께 전체 URL을 반환합니다. API는 동일하지만 다음과 같은 노래가 표시됩니다.
id: 5 name: 'Elegy' url: /albums/2/songs/5
이 접근법을 HATEOAS라고 들었습니다.
-
그래서 … 부모 ID를 제공하려면
id: 5 name: 'Elegy' albumId: 2
어떤게 더 좋아? 아니면 어리석은가? 몇 가지 조언을 던져!
답변
검색 액션을 어디에 두어야합니까?
에서 GET /search/:text
. 그러면 일치하는 앨범이 포함 된 모든 일치 항목이 포함 된 JSON 배열이 반환됩니다. 클라이언트가 트랙 자체가 아니라 전체 앨범에 관심이있을 수 있기 때문에 이것은 의미가 있습니다.
부모 ID를 각각 반환하는 것은 좋지 않습니다. 내가 잘못?
개별 트랙에는 앨범이 포함될 수 있습니다. 이렇게하면 앨범이나 검색 (여기서는 앨범 없음)을 통해 트랙을 얻을 수있는 경우 트랙 표현이 균일해야합니다.
어떤게 더 좋아?
앞에서 언급했듯이 앨범을 포함하는 것이 좋습니다. 세 번째 요점 (상대 URI가있는)은 경우에 따라 흥미로울 수 있지만 (URI가 형성되는 방식에 대해 생각할 필요는 없지만) 앨범을 명시 적으로 제공하지 않는 단점이 있습니다. 네 번째 요점이이 문제를 해결합니다. 응답에 상대 URI가 있다는 이점이 있으면 포인트 3과 4를 결합 할 수 있습니다.
아니면 어리석은가?
올바른 URI가 없기 때문에 좋은 URI를 선택하는 것은 쉬운 일이 아닙니다. API와 동시에 클라이언트를 개발하면 API 사용 방법을 더 잘 시각화하는 데 도움이 될 수 있습니다. 즉, 다른 사람들은 API를 개발할 때 생각하지 않은 다른 사용법을 선호 할 수 있습니다.
문제가 될 수있는 측면은 내부적으로 데이터를 구성하는 방법, 즉 계층 구조 사용입니다. 귀하의 의견에서에 대한 응답을 포함해야 할 것이 무엇인지 궁금합니다 GET /artist/1/album/10/song/3/comment/23
. 이는 매우 트리 지향 비전을 보여줍니다. 나중에 시스템을 확장 할 때 몇 가지 문제가 발생할 수 있습니다. 예를 들어 :
- 노래에 앨범이 없으면 어떻게 되나요?
- 앨범에 여러 아티스트가있는 경우 어떻게합니까?
- 앨범에 댓글을 달 수있는 기능을 추가하려면 어떻게해야합니까?
- 의견에 대한 의견이 있으면 어떻게해야합니까?
- 기타
이것은 본질적으로 내 블로그에서 설명 한 문제입니다 . 트리 표현에는 많은 경우 효과적으로 사용하기에는 너무 많은 제한이 있습니다.
계층을 파괴하면 어떻게됩니까? 보자
-
GET /albums/:albumId
앨범에 대한 메타 정보 (예 : 앨범을 게시 한 연도 또는 앨범 표지를 표시하는 JPEG의 URI 등) 및 트랙 배열이 포함 된 JSON을 반환합니다. 예를 들면 다음과 같습니다.GET /albums/151
{ "id": 151, "gid": "dbd3cec7-b927-423f-894b-742c4c7b54ce", "name": "Yellow Submarine", "year": 1969, "genre": "Psychedelic rock", "artists": ["John Lennon", "Paul McCartney", ...], "tracks": [ { "id": 90224, "title": "Yellow Submarine", "length": "2:40" }, { "id": 83192, "title": "Only a Northern Song", "length": "3:24" } ... ] }
예를 들어 각 트랙의 길이를 왜 포함시켜야합니까? 타이틀을 기준으로 트랙을 나열하면 앨범을 보여주는 고객이 관심을 가질 수 있다고 생각하지만 각 트랙의 길이도 보여줍니다. 다른 한편으로, 나는이 정보가이 레벨에서 필요하지 않다고 결정하기 때문에 모든 트랙에 대해 작곡가 나 아티스트를 보여주지 않을 수 있습니다. 분명히, 당신의 선택은 다를 수 있습니다.
-
GET /tracks/:trackId
특정 트랙에 대한 정보를 반환합니다. 더 이상 계층이 없기 때문에 앨범이나 아티스트를 추측 할 필요가 없습니다. 실제로 알아야 할 것은 트랙 자체의 식별자뿐입니다.아니면 어쩌면? 이름으로 이름을 지정할 수 있으면 어떻게
GET /tracks/:trackName
합니까?GET /tracks/Only%20a%20Northern%20Song
{ "id": 83192, "gid": "8d9c4311-9d7b-40a4-8aeb-4fe96247fe2b", "title": "Only a Northern Song", "writers": ["George Harrison"], "artists": ["John Lennon", "Paul McCartney", "Ringo Starr"], "length": "3:24", "record-date": 1967, "albums": [151, 164], "soundtrack": { "uri": "http://audio.example.com/tracks/static/83192.mp3", "alias": "Beatles - Only a Northern Song.mp3", "length-bytes": 3524667, "allow-streaming": true, "allow-download": false } }
이제 좀 더 자세히 살펴보십시오
albums
. 당신은 무엇을 봅니까? 한 장이 아니라 두 장의 앨범. 계층 구조가 있으면 레코드를 복제하지 않는 한 그렇게 할 수 없습니다. -
GET /comments/:objectGid
. 응답에서 추악한 GUID를 발견했을 수 있습니다. 이러한 GUID를 사용하면 앨범, 아티스트 또는 트랙에 적용 할 수있는 작업을 수행하기 위해 데이터베이스에서 엔터티를 식별 할 수 있습니다. 댓글 달기 등.GET /comments/8d9c4311-9d7b-40a4-8aeb-4fe96247fe2b
[ { "author": { "id": 509931, "display-name": "Arseni Mourzenko" }, "text": "What a great song! (And I'm proud of the usefulness of my comment)", "concerned-object": "/tracks/83192" } ]
주석은 관련 객체를 참조하므로 컨텍스트 외부에서 주석에 액세스 할 때 (예 :을 통해 최신 주석을 검토 할 때) 해당 객체로 이동할 수 있습니다
GET /comments/latest
.
그렇다고 API에서 계층 구조를 피해야한다는 의미는 아닙니다. 말이되는 경우가 있습니다. 경험적으로 볼 때 :
-
자원이 상위 자원의 컨텍스트 외부에서 의미가 없으면 계층 구조를 사용하십시오.
-
자원이 (1) 단독으로 또는 (2) 유형이 다른 상위 자원의 컨텍스트에서 살 수 있거나 (3) 여러 상위가있는 경우 계층 구조를 사용해서는 안됩니다.
예를 들어, 파일 행은 파일 컨텍스트 외부에서 의미가 없으므로 다음과 같습니다.
GET /file/:fileId
과:
GET /file/:fileId/line/:lineIndex
괜찮아.