Abstraction is critical to programming. It is the core activity we use to make more interesting and complex programs.
Most of us understand abstraction as finding commonalities between different concepts, and modeling these as an inheritance hierarchy. If you are a retail store, then toy cars, trash cans, and pillows are all sellable items. Thus, abstraction is finding similarities in disparate things. Identifying patterns.
But there is another side: breaking concepts down into components. While the trash cans and toy cars are the same at the cash register, they are different when stocked on shelves. That GUI button has a view, a model, and some event triggers. Thus, abstraction is also finding differences in what appears to be same. Breaking what appears to be an indivisible whole into disparate components. Design is the process of breaking things apart.
This second application of abstraction is important in analyzing cause and effect. We started an agile process, and then a bug made it into production. Agile is a failure! But really, did our process changes have anything to do with it? Perhaps the two events were unrelated. Or perhaps the same frustrations led to both. As humans we get overexcited about X happened, and then Y happened; therefore X led to Y. We are too quick to form patterns where none exit. Laurie won both poker nights, therefore Laurie is skilled at poker. It is challenging to break Laurie's play into components of luck and skill - skill we can control, so it's a much more appealing cause. Breaking a cause or effect into multiple components requires abstraction, and if we use it, we will be better at programming and at life.