The most useful discovery I've ever made in programming wasn't actually a programming feature, but being able to use the debug features present in most IDEs. Debugging is one of the most difficult and mind-numbing tasks in programming, and makes up a large part of the programming process.
Debugging in the IDE usually revolves around something called breakpoints. In order to setup your IDE to work with a running program (the Spigot server for example) you simply have to add a few arguments to the script you use to start the server. In your IDE, just create a new Debug Run configuration and provide the port set in the startup parameters. You don't have to recompile your plugin to use any of the debug features.
Breakpoints allow points at which the server should stop at (freeze). In the IDE, data for that "frame" will appear, showing you the values for variables in the source at that breakpoint as well as in it's own window. This is especially useful when you don't know the specific issue you are having, and saves time (as opposed to making minor modifications at near random until it works).
You can also "step" around frames. A frame is a set of data for the level you're looking at. For example, if you have a function calling another function which does a calculation (a + b for example) you could place a breakpoint right before returning the function result. When the program reaches that point, it will stop and the IDE will provide the values for the variables as they appeared during runtime. The frame in that case is inside the function. If you wanted to know where the function was being called from, so you could get the context, you can step out of the frame to the function that's calling it. You will then get provided with all the variable data in that function.
One of my favorite features is being able to use breakpoints in libraries, without having the original source. For example, if the player was being healed from some other plugin or source and you wanted to know why, you could add a breakpoint to the Player#setHealth() function in CraftBukkit (as decompiled by the IDE). Whenever it's called by any plugin, it will halt the program. If you have the plugin calling it added as a library you can step out of that frame and find out what the execution parameters or requirements are for that plugin to execute the function.
Another cool features is being able to update the classes during runtime. If you wanted to change something small, changing a -1 to a 1 for example, you could actually update that part of the source on the server without having to restart the server or program. It is limited, though. You cannot change any class declarations (class names, function names, parameters, class/global variables, etc). It does work well for quick testing, though. You could switch out a URL to an API endpoint to a test one (provided by something like Postman) if you wanted to test it with different endpoint results.