It's hard to use up all the program space in the larger PICs unless you've got a lot of table data, or perhaps pages of LCD graphics data. And that type of stuff is perfect for sticking on an external EEPROM. So there's rarely a case where you'd want to store program code externally.
The later PICs have an I2C module implemented in hardware. However, I have to mention it requires significant software control & buffering, yet is extremely poorly documented on just how to do it. On top of that, there were hardware errata (bugs) in some case. Like, there's a rare case in the PIC18F452/252 where the BufferFull (that is, a byte's been received) flag and corresponding interrupt will be skipped, and all you can hope to do is keep track of the expectation so you can perform a timeout.