There are two different uses of conditional GETs
There are two different (although overlapping) uses of conditional GETs, especially the HTTP ETag header; reducing bandwidth, and reducing your computation. A successful conditional GET always reduces bandwidth usage, and it may let you skip doing expensive operations to compute the request page.
Reducing bandwidth is useful in general because it improves the user experience (although these days there is evidence that the big time hit comes from the number of requests, not their size), but it probably doesn't help your servers very much; most websites are not constrained by their outgoing bandwidth (although cloud services may change this). Reducing computation helps your servers for the obvious reason.
This implies that you need to think about what your goal is before
you start implementing conditional GET in your application. The most
straightforward and general ways of computing
ETag values are all
post-facto approaches (you get the
ETag value for a page as part
of generating the page itself), but obviously these only reduce your
bandwidth, not your computation.
If your goal is reducing your computation, you need to be able to check
(and possibly generate)
ETag values with as little work as possible;
this implies things about your internal application architecture and
how you work out
ETag values. For example, the traditional black box,
highly dynamic page templating system is not very suitable for such an
environment, because it's hard (or sometimes impossible) to check if
it's going to give you the same output without running it.
(The other obvious approach to fast
ETag checking is a cache with
explicit invalidation, but then you have to track which pages are
changed by some low-level change, and this too has implications
for your architecture.)