Alternate simplistic answer to (2):
One often has to cut off a signal at a beginning and an end to fit it into any finite length FFT. The sharp edges potentially produced by these two cuts (a rectangular window) in a longer time domain signal can result in various high and low frequency artifacts in the FFT result (especially for any signals or signal components that are not exactly integer periodic within the FFT's length). A Hamming window cuts a longer signal into the FFT's length using a softer rounder (raised cosine) edge, thus producing far less high frequency artifacts in the FFT result.
Alternate detailed answer to (1):
Line 2: A standard FFT returns a complex result. Many uses do not require a complex number result (with both real and imaginary components), so Line 2 uses the abs() function to return the magnitude value of each FFT result bin, which are strictly real valued (no imaginary stuff).
Line 3: An FFT of a strictly real input returns a result where the upper (or negative) half is identical in magnitude to the lower half (except for the DC and Fs/2 or Nyquist bin). So line 3 just throws away all that redundant information (it's the same as what's kept, why repeat it?).
Line 4: However, if you throw away half the FFT result, the total energy gets reduced by half. So Line 4 multiplies by 2 to fix that (everything except the DC and Fs/2 bins), and get the correct total energy.