Handling variations of a page (or, the revenge of REST)
Suppose that you have a web application with users, and different users (or different sorts of users) need to see slightly different versions of various pages and forms. It's both obvious and very tempting to implement these page and form variations with conditional logic in a single URL's view handler; you have to retrieve the user's information anyways (and check access permissions), so you simply put in some checks and switches based on what sort of user they are or what permissions they have.
(This is also the sort of situation where you start reaching for features like on the fly modification of what fields are included in a form, read-only fields, and so on.)
Through recent hard experience, I've come to feel that this is a mistake. What you should really do is put each separate version of the page or form on its own distinct URL.
The problem with having all of the versions of the page accessed through the same URL is that you have no simple, good way to give a single user access to more than one of them. You can't easily handle things like a user who has multiple roles that would get different versions of the page, or allowing administrative users to drop down to simpler, more restricted interfaces (or even to see the simpler interfaces for training purposes).
(I've recently stubbed my toes on both of these cases. Our current workarounds for both of them are unaesthetic and awkward.)
You can solve this several ways, but the easy solution is the RESTful way. Given that you actually have different (albeit closely related) pages, you should give each different page a distinct URL. Among other advantages, this means that users can immediately use as many different versions as they have permissions for just by going to different URLs.
(Under the hood you might still use all of the dynamic form modification and conditional templates and so on that you used to; it's just that now you're making choices based on the URL instead of the user's data. You only use the user's data to insure that they have access to this version of the page, and you needed to do those access checks anyways.)
What this really drives home for me is that REST is a really good idea. The moment I hid application state in my code instead of exposing it in my URLs, it bit me, just like REST told me it would. I can only hope that I'll learn the next time around.
Sidebar: how to avoid complicating URLs in the rest of your application
So, now you have three or four URLs for different versions of a page instead of a single page that displays differently for various people. How do you link to it from other pages? In particular, do you have to put conditional logic (or special rendering tags or the like) in your other pages that look up what version of the page the user is entitled to and link to just it?
My answer is no. Suppose that you have three different versions of a creation page (for three different classes of users), and you put them at /manage/create/sponsor, /manage/create/gradoff, and /manage/create/staff. Set up a fourth page, /manage/create/. What this page does is look up what the user can access, pick the preferred version, and answer with a HTTP redirect to it. Once you have this set up you can just point all of your outside links to /manage/create and everything will just work. Knowledge of what the user has access to and where they should wind up is now localized in /manage/create; no one else has to care.
This scheme gets a bit more complicated if you need to pass components of the URL through, if you have eg /manage/edit/<id> and it needs to be redirected to one of /manage/edit/staff/<id> or /manage/edit/sponsor/<id>. But this can be handled too with a bit more work.
A quick tour of my desktop
I've finally gotten around to creating a screenshot of my desktop, now available here (500Kb PNG). My desktop is two 1280x1024 LCD panels in side by side mode, so this is a 2560x1024 picture. (You can probably easily spot the dividing line between the two panels.)
This screenshot shows a number of things that I've talked about,
such as pyhosts and xrun; also
visible is an
xterm showing off the very handy ziconbeep feature (look at the top left). The overall appearance
is fairly representative of what my desktop normally looks like,
including the clutter of Firefox windows that drove me to lazy hacks.
One of my peculiarities is immediately visible; I like to have things present on both physical screens, so you can see duplicates of things like the fvwm pager. In practice I rarely use the ones on the left screen, but I like having them there for some reason. Another peculiarity is that I mostly work on the right screen (the left side of the right screen is my primary working area) and use the left screen mostly for overflow and secondary windows.
(Also, my 'working area' is the space below the
xruns; in practice
there is an invisible dividing line around there that I rarely cross
with active windows. You can see this in the top height of the browser
and emacs windows.)
The window manager is fvwm 2.5.x (specifically a relatively current
build from CVS). The thing at the top left is an FvwmIconMan
instance that swallows all of my terminal windows (primarily
xterms, but I also use
9term). Terminal windows
are my most common sort of windows and FvwmIconMan gives me a very
compact way of keeping track of all of them.
The thing at the right just below the pager is stalonetray, which I use to give all of the Gnome applets and widgets somewhere to hang out (since I don't actually use Gnome). Most of the time all it contains is the Gnome volume control.
(If this leaves you with further questions, leave a comment.)
Sidebar: a bonus from 1996
I have pulled out of the archives my desktop screenshot from 1996 that is referenced on my old desktop writeup on my old site; you can find it here. Although some of the details have changed, I think it's recognizable as a version of what I have now. I've changed things since 1996 but by and large not my tastes.
Looking back at the 1996 screenshot, some things now make me wince. For example, I can't believe that I spent so long wasting the valuable top left corner on nothing more than load monitors. (Of course today I am similarly wasting the top right corner on, well, nothing.)