Nice article, David, as usual...
As you are aware, I suspect that any performance differences will only occur where joins of different data types occur due to implicit conversions... but I'm with you... size the columns correctly if for nothing else than to reduce the size of backups (the OTHER thing that designers always forget about).
However I would say plan for the long term. If you know you have a potential you will need the larger row size be prepared so you don't have to reconsider decission later. And as for the - I have use the following to del with printouts so I could still use the - side of the spectrum.
A = -B = +
Your application can handle the translation or even handle in a Stored Procedure, butthe later means a longer string must be passed instead of the shorter interger value.
There are many ways to conserve space that are often overlooked and interger size is no different. Consider the fact that no matter how big or small your data is the value that is stored will always be the entire length of the datatype. So tinyint will be 1 byte, smallint 2, int 4 and bigint 8 event if the values is 0 it will be represented by all bytes for the datatype.
Decent article I would just say it probably needs to be a little more focus on it's point.