instead of using `std::pair<>` for presenting it. there are three
advantages:
1. better names for readability: `type` and `name` are better names
than `first` and `second`
2. so we can specliaze its behavior by its type: define
`operator<<` once, and use it everywhere. no need to worry
about ADL to pickup the generic operator of `operator<< (..., pair<>)`
anymore. so we can safely use `<< key`, and no need to
use `<< key.first << '.' << key.second`. kill the printed form of
`osd,1` once and for all, all of them are now "osd.1".
3. consolidate the print/parse in a single place