It's applicable everywhere. Conceptually, you want to design your software with many layers (like an onion) and have each layer responsible for progressively larger and larger areas of code. Each layer defining how it will recover from failures it can handle and then propagating failures it can't handle to the outer layer. The real mentality comes from designing the application from the beginning with recovery in mind. People who do a lot of defensive programming actually treat errors as after-thoughts, attempting to "handle" them at every place they think they will encounter them. In any complex application however, there will always be errors in places they didn't think they would encounter them. Instead, one should have the mindset that no matter what you do, you will get an error somewhere and thus you must figure out how to recover from any error, anywhere in the code.