Picking a Hiera hierarchy is harder than it appears. Ultimately we're trying to create a data model within the confines of Hiera that accurately represent your system. Ideally it will cover the current system and be flexible as your system grows or changes in the future.
The primary driver for your hierachy is going to be the way your system is currently organized. You probably have a few environments, many roles, and perhaps different sites. Each of these probably affect settings so they should be represented. A secondary concern in my opinion is how your modules written. Overall I lean towards pushing system data into Hiera and settings defaults in my modules in a params class. However as parametrized classes have matured moving what has normally been internal module data in a ::params class into Hiera might work better for you.
Assuming you want to handle both internal module data and system data your hierarchy might look like this.
I recommend using directories to provide simple namespaces for your hierarchy. Nothing worse than a $::role conflicting with an $::environment and matching where you weren't expecting.
Most people choose common or default at the bottom of the hierarchy and $::fqdn or $::clientcert as the top. This make conceptual sense and provides a simple method to have the last word on setting a value. I choose to put $::osfamily which can match many OS beneath $::operatingsystem which is the more specific case.
We wrote two custom facts $::location and $::role to help classify our machines. $location is as simple as checking IP address or subdomain. Our naming scheme is fairly sane so $::role is just parsing the hostname. If you don't have multiple sites no need for location. If you have multiple business units in a singe location you many want to add an additional fact into your hierarchy. These facts could be more complex and query services like an internal Opsdb or AWS EC2 metadata.
Setting $::environment, $::role, and $::location is that order is personal preference. You could easily have done $::environment, $::location, and $::role.
Some people have built hierarchies using $::calling_class or $::calling_module, but I find that too specific and the more general $::role works better.
Using the Varnish proxy server as an example we might set different amounts of RAM to use based on size of machines of role. Frontend servers just need a small cache for application acceleration. The Cache servers will need a larger storage size because their primary function is to cache.
In this example fe01.stage would get the value from common.yaml of 128MB for the storage size.