What are the main differences between a fields DisplayName and a fields Title? Why are they sometimes different and sometimes the same? What is the best practice regarding naming the DisplayName and Title?
You are mixing up the object and it's XML schema.
There is no DisplayName property on the SPField object and it's derived types. In a field's XML schema, there is a DisplayName attribute but no Title attribute.
So, what you have is:
SPField.Title (Corresponds to XML Attribute DisplayName)
This returns the localized name of the field. In effect, if your field has TitleResource properties set for your current locale, it will return that. If not, it returns the field's DisplayName XML attribute value. If that contains a resource string ("$Resource:...") it will properly replace it.
SPField.InternalName (Corresponds to XML Attribute Name)
SPField.StaticName (Corresponds to XML Attribute StaticName)
These two should, most of the type, be identical. They will differ when you attempt to create a field with an already existing InternalName. In that case, InternalName will be postfixed with an increment (0, 1, ..) to diffentiate the fields
More exactly, as stated here:
If the field is in a list that has an external datasource, the StaticName property always returns the value of the InternalName property. An exception is thrown if you try to set the StaticName property to a value that is not the same as the value of the InternalName property.
Otherwise, the values returned by the StaticName and InternalName properties can be different. Note that you can set the StaticName property whereas the InternalName property is read-only.
The value of the InternalName property is unique within a field collection. The value of the StaticName property is not necessarily unique.
As best practice, you should always set both Name and StaticName in a field's XML, as they are both used by different parts of the API (bless SharePoint API's blatant lack of homogeneity). You should set them both to the same string, and although the documentation states that StaticName is read/write, once set you should not try to change it (there is no good design reason why one would need to manipulate a field's StaticName).