Here is a great link that explains the challenges of debouncing switched inputs. All switches (even things like relays) will oscillate between on and off as they transition to and from their opened and closed states. This transition time is usually considerably longer than a clock cycle on a microcontroller, so you can expect your interrupt to be triggered multiple times from a single switch transition.
The most common and basic solutions are either a R/C low-pass filter on the input (which tries to minimize the high-frequency noise) or a software algorithm that waits until the state read stays constant for a certain amount of time. The former can be tricky to tune (as it depends on the resistance of the switch and the capacitance of the input pin), whereas the software one can waste power and clock cycles.
Some nicer microcontrollers have built-in input debouncing, though it may need to be enabled by setting a flag in a register somewhere. These are usually the simple software debouncers, but built in hardware. They may or may not be available on interrupt pins, which are the most sensitive to bouncing, since they immediately cause a jump in software when a transition is detected.
No matter what you do, you have to trade-off the probability of false transitions with the speed at which you respond to that transition. The longer you wait to acknowledge the transition, the more likely that it's a proper transition, but the longer it will be until you can act on that transition.
The most important thing to know is how long your bouncing period is. You should be able to measure this easily with even a cheap oscilloscope. Flip the switch a bunch of times, have the oscilloscope set to trigger on an edge (either direction is fine), and look at how long the bouncing is before it settles out. Pick the worst, add some margin, and that's a good place to set your switching time.
If you are using an RC filter, the
time it takes for the RC to charge up to 63% of the transition is T=R*C. You also need a circuit that will respond abruptly and stably to this slowly changing voltage. A Schmidt trigger will do this. Often, microcontrollers have built-in Schmidt triggers on their pins, but again, these may need to be enabled.
If you are using software, try to avoid using it on an interrupt, since it is very disruptive to the execution cycle to have an interrupt triggered multiple times. You'll probably also want to avoid a busy loop. Instead, use the sensing of the first transition to start a timer, set at some fraction of the total time you want to wait. Every time the timer goes off, check the input state, and keep a count. Reset it if the state changes. If the counter goes over the threshold, the input signal looks stable at whatever state you are reading. You'll want to try to make sure the timer frequency isn't similar to external noise sources, like 60 or 120Hz.