I have written chess engines before, and I don't think it's over-optimizing. Keeping your code board-representation-agnostic using macros is not very realistic, because many of the algorithms you will use (Static Exchange Evaluation, repetition detection, what terms to use in the evaluation function...) and other data descriptions (moves, transposition-table entries...) will be heavily affected by the choice of representation. If you want to change your board representation after you have written an engine, you will be better off starting from scratch.
Bitboards are great, but they require a shift in how you think about a lot of things. In particular, being outside the board is not a very meaningful concept. For the most part, you don't handle squares one at a time when using bitboards: The basic data structure is a subset of the squares, and operations like moving North move all of them. Some of the bits that were set before moving North will seem to have disappeared, and that's about all there is to it.
typedef unsigned long long u64;
u64 North(u64 x) {
return x << 8;
}
If you have a specific example of code where you feel you need to check if a square is outside the board, post some details about what you are doing and I'll try to help you express it with bitboards.