It wasn't that bad. You had different memory models back then. If you wanted to keep things easy you just compiled for a memory model in which each pointer was either 16 bit (for code/data smaller than 64kb) or a memory model with far pointers (access to all the memory).
There have been mixed memory models and you could go crazy with near and far to break out of the limits of the easy memory models.
Most of the time it was just a mater of picking a suitable memory model for your code and forget about near/far though. Not so different than today.