
1. Types. If it compiles, it works. Almost perfect - but at times still have to check if it does what we think it should. But at least no bugs.
2. Unittests. If they pass the code is good enough. Of course it would be better if tests passing were equal to getting compiled; we need tests because we do not have our code designed well enough - or if we do not have types... my condolences.
3. Debugging. This is where you waste tons of time - because you don't have tests that show you what went wrong, and you don't have a correct type design. My deep condolences. You can fix it. On the other hand, having a repl inside your running app may be better than...
4. Logs forensics. This is where you will waste most of your time, if you don't have better tools, you'll be looking through this shit guessing what this or that message could mean? Like "NullPointerException" with a three-page stacktrace (had it in my unittest yesterday). Even here you can improve your life by having your code be honest in its logs. Just tell what's wrong and why it thinks it's wrong, that's it. But of course, better not have it at all.
-Captain.