Has anybody come up with a better technique for managing tags and branches in subversion than what is generally recommended (the parallel directories called 'tags' and 'branches')?
The only other thing you can do besides having parallel directories when you have Branches is to do an SVN Switch between two branches whenever you want to work on one or the other. Perhaps you should clarify what you want to be "better" about this system and people could make suggestions.
Using the repository namespace to convey information like branches / tags / etc is fundamentally the SVN model; if what you want is a different model, you probably really want something other than SVN.
The lack of metadata like CVS-style labels in SVN is an intentional design decision. No matter what arrangement of branches/tags/projects you choose in your tree, it's all going to reduce to sets of parallel directories for each purpose. What's left is just choosing the right naming strategy for your branches and tags to make things more clear to you.
One convention that I'm fond of is a separation between full heavyweight branches and lightweight "twigs". The convention in the group where I work is that long-lived development goes in a branch, and the release engineers must know of and be partially responsible for each branch, but that any engineer can create a short-lived twig to use as scratch space for a problem that's too large to fit into one checkin but not massive enough to require release engineering support. Twigs here live in a separate parallel 'twigs' directory similar to branches, and the naming convention often has the creator's user ID and the bug ID number for the issue the twig is intended to address in it.
We use a "trunk, tag, branch and stream" strategy.
The "trunk" is where the most current version of whatever is out in production is supposed to be placed.
A "tag" is where a "copy to" occurs when a stream is complete and we need to store the status of the stream for archival purposes. It also allows development to continue from a specific point.
A "branch" is when something completely different than mainstream development is to take place. Usually, branches are very rare.
"Streams" are what we most use. A stream of development is a task-based focus, such as a stream for a particular fix or development effort (for instance, a change requests' completion). Streams are allowed to merge with each other, but different streams are ranked based on svn strategy. For instance, we had one stream for a cr release, and another stream for pushing out app support releases. Since the CR stream had to incorporate the app support fixes in addition to its own changes, it was ranked higher. Streams that are higher ranked have lower streams (as needed) merged into them. Finally, a stream becomes production-ready. It is tagged, and then "copied to" trunk, which is then used (normally, although sometimes tags are used) as the base for further streams.
The best use of streams, however, are for short tasks that take less than two weeks to complete. These streams can be merged quickly into multiple, higher ranked streams, which then get merged later into any other higher ranked streams. For example, since app support was lower than cr, any app support quick fix could be copied to a stream and then worked on, merged to app support which would then be merged to the cr stream.