Does Information Hiding mean I should minimize the number of properties my classes have? Is that right? Do you tend to make your classes private fields with methods?
Declaring something private in scope does not really "hide" the information.
I believe hiding information refers to isolating your logic from the consumer via an interface, so you can change the logic without affecting the consumer.
Information hiding has to do with how much data in your class (fields, properties) is accessible to outside classes. The more you hide, the easier it is to change your implementation later without affecting dependent classes (i.e. your "public interface"). This ultimately leads to more stable designs.
Information hiding means not to expose to consumers of your class what they don't need to know. Hiding properties and replacing them with methods is pointless because properties are actually special type of methods
Information Hiding is hiding both logic and data. You should be able to change both radically and not affect users of your class.
It seems that many people understand Information Hiding in principle, but then also think that getters and setters for everything / properties for everything is an example of it.
The incendiary article by Allen Holub called "Why Getters and Setters Are Evil" can be an eye-opener on the topic.
In short, private members with direct getters and setters are little more than dressed-up public members. It is true that getters and setters are needed at layer boundaries (UI, persistence, etc), but their visibility should be restricted to those classes that have a legitimate need to call them.
Private fields that are accessed through Public methods. Although it may seem silly doubling up to do something like:
private int _myInt;
public int MyInt
{
get { return _myInt; }
set { _myInt = value; }
}
Although now you can just do (IIRC, my 3.5 knowledge isn't complete):
public int MyInt { get; set; }
You may ask why are you making accessors that just provided the exact same access that making the original property public. But by having the original property private, if you decide you only want even numbers allowed, you can do this:
public int MyInt
{
get { return _myInt; }
set
{
_myInt = (value % 2 == 0) ? value : _myInt;
}
}
(Note: not the best example as it doesn't let the use know that their operation failed.)
Basically, you never want to expose internal operations to any consumer of your class. And the way you do that is by hiding as much as possible and only exposing what you have to.
If the outside world doesn't need to see it, then don't show it. You should try to encapsulate your objects so that they are losely coupled and the outside world knows just enough about them as they need to.
The point of information hiding is to limit exposure to consumers of your object to changes that occur in how your object operates internally. The more likely a piece is to change, the more important it is to keep it away from the interface. This is why getters and setters are common ... the value that is emitted by the interface can change in any way except type without affecting the contract with the consumers of the interface. It's also a common general rule that only the object itself may affect its state, so setters provide a way of enforcing a contract about how the object's state can change, also ideally without affecting the interface. I think you're usually better off maintaining state in private variables and providing getters and setters as a public interface to them (when outside objects need to access them) mostly because you'll always have the option to provide some kind of validation or transformation if it becomes necessary down the line without breaking your interface.
Ever strike up a conversation by asking "How are you?", only to be met with a litany of their troubles and triumphs, pet peeves and uninteresting interests, feelings of insecurity and maybe an in-depth review of the breakfast muffins...
...that's not information hiding. Most of us don't do that. Kids do, at least until they first meet someone who uses all the irrelevant information they're sharing to hurt or humiliate them in some way... then, they learn to be secretive and paranoid, one more step on the road to adulthood.
Most of us also learn to do the same sort of thing with the code we write, exposing just enough to get along with other code, but not so much as to allow it to become dependent on our implementation. This is somewhat more nuanced than simply not exposing internal data - merely placing accessor methods or property getters/setters between internal data and the cold outside world is no more information hiding than launching into a conversation about "this friend of mine" and "his" herpes problem...
You arrive at the heart of the question when you start to differentiate between interface and implementation. When you expose properties because they match the view of the world your client code expects, rather than because they provide a convenient way for them to manipulate your implementation. It's rarely a clean divide, even when developing top-down, and contrived examples can easily do more harm than good: going out of your way to obfuscate an implementation detail that happens to be a perfectly good interface is down-right harmful.