Code size (ROM) should generally not be the first thing on your mind. If you are in a position to pick a platform where you are not likely to run into code size issues, do so. Optimizing for smaller code size is a time-consiming (read expensive) task, which does not add value to your project. Smaller code size is often traded against longer execution times. Longer execution times also means more power consumption. Even if your device is mains-powered, it does not hurt minding our planet a little, does it?
It is good practice to start your project with compiler settings that are a healthy mix of optimization for speed and the ability to debug. If code size becomes an issue, turn off settings that trade speed against code size (e.g. loop unrolling). If compiler output is already optimized for smallest code size, you will need some additional tricks up your sleeve. Unfortunately there are no common patterns for code optimization on source level. Code size is not directly proportional to physical lines of code. Results are largely dependent on the platform used. You could lose a lot of effort spent on reducing code size if you switch to a different platform.
That said, there will be times in which your application just does not fit in ROM and you do not have the luxury of switching platforms. Having a set of tools to decrease code size will definitely come in handy. I intend to create a series of posts here to describe some techniques you can apply to decrease code size, but I should start with a warning: your milage may vary. Do not blindly depend on my advice or your intuition, but remember the most important engineering principle: measure! Always compare code size of various options in your situation.