I agree with this approach.For my line of work there is a 1.5: Make it reliable and resilient. This is where understanding the basics of computer theory matters because this skill happens during the make it work phase by designing checks, fallback by design. Optimal and elegant don't mean much if the gadget crashes in the field randomly. Learn to build programs like we build physical structures. "Premature optimization is the Root of All Evil".
Make programs modular, use abstraction to break dependance, always check for errors and deal with them, and do not try to do any premature optimisation.
"Premature optimization is the Root of All Evil".
Robust working code is your aim.