One of the features of Object Oriented Programming (OOP) is that data can be encapsulated. This means that an object provides a way to group data into a single entity and hide its internal state requiring all interaction to be performed through the object’s methods. For example the data for a Person, would be his name, sex, and age. To change the name of a user a method would be used called “changeName”. The method changeName would encapsulate all the rules and logic that is involved with changing the name of a user. The interface would simply expose the method where as all the details would be hidden form the user in the implementation.
Data Abstraction compliments data encapsulation by exposing to the user of an object a clear and well defined interface to the object. Data Abstraction is strongly associated with Abstract Data Types (ADT). Here is a blog post that tries to explain Data Abstraction. The concept of Data Abstraction and its usefulness becomes more apparent when introduced to the idea of Inheritance.
Take once again the example above with the method “changeName”. The method “changeName” could have a different set of logical rules for a Person who is a doctor opposed to a person who is a lawyer.
Good Data Abstraction design aims to recognize the behavior of an object and abstract it to its lowest common denominator. Re-factoring is a useful technique that often helps to perfect the abstraction process. As with all OOP design, with more practice you get better at it.