I am not going to re-invent what this means. Just jotting down what it fundamentally means... and what we should keep in mind when we write code.
Dictionary.com definition Abstraction, one of the listed meaning from that link that I like is
"the act of considering something as a general quality or characteristic, apart from concrete realities, specific objects, or actual instances."
We have to consider always what can be a general characteristic of this piece of code that I write. It may not be always re-usable, that is where re-factoring helps to re-use and improve these code pieces.
Applying abstraction to code..
a) How best should this be accessed?
b) How can we name it in a manner that conveys the functionality or the purpose properly?
Abstraction and Inheritance are related. In that inheritance passes abstraction to higher level classes.
In the overall architecture abstraction can be applied at different levels of the architecture.
Benefits of abstraction, quick search on the web shows "
a) Reduce Complexity.
d) Analysis is easier on properly abstracted system.
The above things can be kept in mind as test cases. If it is too complex, it needs to be abstracted. If the section or system is not flexible, then it needs to be abstracted. The same can be applied for "Maintainability" and "Analysis" If the work is not meeting those goals then it is not properly abstracted.
When do you stop abstracting?
a) When it crosses the point where it is no longer a single meaningful entity of it's own then it should not be abstracted. Otherwise we will have an object that means everything.
b) Time and business constraints are another big factor in writing / developing goode code/systems. We may not have the time=money to do some of these tasks.