#if !defined(XXX) позволяет добавлять дополнительные условия при помощи операторов && и ||, что иногда может понадобится в будующем, если проект большой, а так же использовать с нормальной читабельностью условие #elif. Согласитесь выглядит немного кривовато:
#ifdef TESTM
int testm;
#elif !defined(TESTM) && defined(TESTB)
bool testb;
#endif
А так я впринципе тоже всегда пользуюсь #ifndef,#ifdef по одной причине - потому что короче пишется... Да и мне кажется проблемм с читабельностью у этих пар нету (если конечно со зрением всё нормально) т.к. обнаружить отсутствие одной буквы (при нормальном выравнивании) можно даже тогда когда просто пробегаешь глазами по коду. Другое дело это опечатки - когда забыл дописать букву 'n', тогда появляются 'неопознанные ошибки'. Бывает редко, но бывает.