Pokemons described by Shakespeare. Did get to catcheth those folk all!
My response to a software engineering challenge.
To me, it was quite fun doing this challenge, I hope you'll have a good time looking at it!
Develop a REST API that, given a Pokemon name, returns its Shakespearean description.
- Main
- Unit tests
- Integration/E2E tests
- Patterns/practices
- Integrations
You'll need Docker, Java 8 and Maven 3.5+ installed on your favourite OS.
git clone https://github.com/noragami/pokeshake.git
cd pokeshake
mvn clean verify
You can build/run the application packaged as JAR file via Maven and Java...
mvn clean package
java -jar target/pokeshake.jar
... or with Docker (it might take a while to download images the first time):
docker build -t pokeshake/0.0.1 .
docker run -p 8080:8080 pokeshake/0.0.1
curl https://localhost:8080/pokemon/pikachu
{"name":"pikachu","description":"At which hour several of these pokémon gather, their electricity couldst buildeth and cause lightning storms."}
Shakespeare translator API has a quota limit on the free tier (60 API calls/day, 5 calls/hour).
If you reach the quota limit, the API will send an http response code 429 - Too Many Requests
.
For this reason, I made the decision to forward the same http response code to the client,
instead of failing badly with a 500
response code. So we can keep the information and provide the right feedback to the client.
I also implemented a 404
response code if the client requests a Pokemon that doesn't exist.
I encountered a problem during the integration of PokeApi. At first, every call returned a 403
error.
Fun facts:
- API Documentation didn't help at all
- The same call worked using the browser
Point 2 made me think that the only difference between the browser call and the console call was the user-agent. By setting up a dummy user-agent, the problem disappeared.
- Document API using OpenAPI/Swagger (using Swagger UI)
- Add a cache layer (all the requests are deterministic, same Pokemon name -> same Pokemon description, same description -> same Shakespeare description)
- We'd need a premium/ultra Shakespeare translator API subscription
- Add Spring Retry policy to automatically re-invoke a failed operation (on the integration side)
- Add a circuit breaker to fail fast if all else fails
- This is a single microservice, but in production you'll want a whole microservices ecosystem to scale the right way such as an api gateway/reverse proxy, a service locator, a config server...