A well-designed class encapsulates its data and provides operations to access or manipulate it. These operations ensure that the object remains in a valid state without inconsistencies. Better yet, they do so in a way that the clients of the class don’t even need to know about it.
One of the greatest advantages of object-oriented programming is the ability to ensure that objects are always in a consistent state. Compare it with, say, procedural programming languages like C. In C, you can define data structures (known as structs). However, there’s no way to control who changes the values inside the structs. Any piece of code, anywhere in the codebase, can change them.
When code is not appropriately encapsulated, developers feel they can never find where to patch the code or fully fix a bug in one shot. When code is spread out and not encapsulated, developers have to constantly search for things. Just going to the class that defines the abstraction isn’t enough. A developer may find a place to fix the code, only to have the same bug appear somewhere else.