Pruning
The problem Imagine you have a tree of various Indicators that track something about a country's population. The client wants to display them, but only a few of them at a time.
These Indicators are part of a tree, and they’re grouped by Themes, Sub-themes, and Categories. For example, we have an indicator called “Crude death rate”. It resides in the Category "Births per year", which lives inside the Sub-theme “Births and Deaths”, which in turn lives inside the Theme “Demographics”.
This data comes from a client-provided service, which doesn’t support picking and choosing which things to filter. Because of valid reasons we won’t expound on here, it wouldn’t make sense to add this feature to the upstream service, and it’s on us to build an intermediary service that can do this.
How to run
Use ruby 2.5.1
$ cd pruning
$ bundle install
$ rackup
Server will be listening on port 5000
Assumptions
Software is done under following assumptions:
- Tree structure will not be changed (themes -> subthemes -> categories -> indicators)
- Indicators are leaf nodes in the tree
- Tree structure will always be complete (no categories with missing indicators etc...)
- If there are no indicator ids present then user does not want any indicators (opposed to: wants them all)
- There can be more indicators with the same id
Decisions
- Retries have a random delay between them (to allow server to get itself together)
- Structure is built to support more than just this one API call
- Expected error reporting is done through custom exceptions captured by the top level sinatra App class
- API always returns JSON
- All parameters are whitelisted and coarced into respective types (eg. name must be A-Za-z)
- Search does not stop if all the indicators are found - software searches the whole tree
What could be improved
- API call tests are missing
- Logging should be added (e.g. when the retry happened)
- "Integration" tests on the server level (with separate mocked origin server)
- Validate results before entering pruning algorithm