As my new ray tracer is spectral I am rewriting some of the basics from scratch including dielectric code. I figured I could cut and paste some stuff out of ancient "
ray tracing news" but ran into some problems with normal vectors. So I am rederiving this for my own benefit.

Sketch created with limnu iphone app from limnu.com 
All renderers have some convention about which way surface normals point and whether that depends on incoming rays. I am a fan of surfaces being boundaries between materials, and a dielectric has a surface normal
N pointing to the side with refractive index
n. One thing that means is that in the diagram
N might be pointing "down" along the dotted line.
First what about reflection? It is usually the classic formula:
S =
D  2*
N*dot(
D,
N)
Does that formula still work if
N points along the dotted line? Happily, yes try substituting 
N in there and you get a "" on the
N and the dot product and they cancel. Also,
D need not be a unit vector. I rarely require that in my ray tracers so I can use instancing if I want.
N however does need to be a unit vector.
Now what about refraction? It obeys Snell's law:
n sin(
theta) =
n' sin(
theta')
We can use the same trick as in reflection where we use
N and
D as a 2D basis. First let's make life easy on ourselves and assume
D is a unit vector and
N points "up" like in the picture, and make an orthogonal basis (let's change the sin() and cos() with c, c', s, s')
D = c
N + s
Q
Here
Q is to the right and perpendicular to
N. We don't know what is is yet, but it we know what it is by rearranging the terms above to be get
Q = (
D + c
N) / s
We also know that
T = c'
N + s'*
Q
We know c = dot(
D,
N), and s = sqrt(1  c^2)
Further we know that s' = (
n/
n') s
Right there is a place we can get into trouble n can be high (over 2 for diamond) so if the more dense medium is where
D is (the top medium), we could have s > 1. In that case we get all reflection and no refraction (total internal reflection). Here's a nice image of that:

The water acts as a perfect mirror due to total internal reflection (from wikipedia) 
OK plug and chug the algebra:
T = c'
N + s'
Q
T = c'
N + s'(
D + c
N) / s
We know s'/s = n'/n.
We also know c' = sqrt(1s'^2) = sqrt(1  (n/n')^2 (1c^2) ).
T = (n'/n)
D +(c(n'/n)
 sqrt(1  (n/n')^2 (1c^2) ))
N
putting back in c = dot(
D, N) we get
T = (n'/n) D +(dot(D, N)(n'/n)  sqrt(1  (n/n')^2 (1dot(D, N)^2) )) N
Ok! That agrees with the ray tracing news formula. Now what happens when
N points down? Only the last term is different:
T = (n'/n)
D +(dot(
D, N)(n'/n) + sqrt(1  (n/n')^2 (1dot(
D, N)^2) ))
N
Well isn't that annoying? That sign difference is just sgn(dot(
D, N)). I never know how to best code that sort of thing, but when in doubt, be very readable!
if (dot(D,N) > 0) temp_normal = N // now proceed with original formula