Much of the slow performance from routes comes from the complexity of
expiry, :requirements matching, defaults providing and figuring
out which url pattern to use. With named routes we can avoid the expense of
finding the right route. So if they‘ve provided the right number of
arguments, and have no :requirements, we can just build up a
string and return it.
To support building optimisations for other common cases, the generation
code is separated into several classes