Artem
Artem

Reputation: 2314

Rest resource separation

Let's say we have an api enpoint to deal with a superhero resource:

The resource model is the following:

public class SuperHero
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int Age { get; set; }
}

Now a Product Owners say they'd like to introduce superhero teams. As of now a given team has a name and at least one hero attached. I can see two options to proceed with.

1) Straightforward

Introduce a new resource:

api/teams POST - creates a team

And the resource model will look like the following:

public class Team
{
    public int Id { get; set; }

    public string Name { get; set; }

    public IEnumerable<int> SuperHeroes { get; set; }
}

In such a way api users will send a single request to create a team. A list of superheroes must be specified and be non-empty

2) Revisit requirements

What does

team has a name and at least one hero attached

actually mean? Well, having no heroes the team is definetely not ready to save the world. But is it the obstacle to its existence? And do we really need to prevent users from creating a team with no heroes attached?

Let's introduce a team and attached superheroes as a resource and sub-resource respenctively:

My feeling is that the second approach contributes to endpoints' simplicity and responsibility separation. Also it might be better from performance perspective as fetching a team probably doesn't mean the user needs an associated superhero list. At the same time it forces api consumers to use two calls instead of a single one to create a ready-to-go team.

What additional questions should be asked here to choose the right option?

Upvotes: 0

Views: 114

Answers (1)

cassiomolin
cassiomolin

Reputation: 130927

Creating a team

When creating a team, you could allow the consumer to add heroes to it:

POST /api/teams HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "name": "justice-league",
  "heroes": [
    "batman",
    "superman",
    "wonder-woman"
  ]
}

Attaching a hero to a team

To add heroes to a team, you could:

POST /api/teams/avengers/heroes HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "value": [
    "captain-america",
    "iron-man"
  ]
}

Where you semantically append members to a collection.

To replace the heroes of a team:

PUT /api/teams/avengers/heroes HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "value": [
    "captain-america",
    "iron-man",
    "hulk",
    "thor"
  ]
}

You also could consider:

PUT /api/heroes/harley-quinn/team HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "value": "suicide-squad"
}

Where you semantically replace the team that the hero belongs to.

Detaching a hero from a team

To remove a hero from a team you could:

DELETE /api/teams/avengers/heroes/iron-man HTTP/1.1
Host: example.org

Or even:

DELETE /api/heroes/iron-man/team HTTP/1.1
Host: example.org

Bear in mind that your persistence model doesn't need to be like your API model.

Upvotes: 1

Related Questions