Some.User@host.domain wrote: > > I am commenting that people confuse the concepts of modularity and > information hiding with all of the rest of the OO philosophy. There > is a lot more to OO programming than modularity and information > hiding. But that idea is useful whether or not you are using an OO > based design. Information hiding is stupid. 90% of my code can be best described as manipulating information, so why should I hide it? "Show me your flowcharts and conceal your tables, and I will continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious." (Frederick Brooks) Ok, so I didn't really mean that about information hiding. Dramatic license. But it is one of the things that bothers me the most about OO code. A "real OO programmer", when given the task of implementing a heart, would take a real heart and coat a meter thick layer of plaster around it, then drill holes down to the aorta and stick tubes in them. He would tell you how great it is that you can replace the buried heart with a vacuum cleaner or a rooster without changing anything else. When you complain about the tubes sticking out of your chest and the wheelbarrow you need to push your new heart around in, he'd quickly point out that the wheelbarrow is really an advantage because you can haul around all kinds of other great things at almost no added burden. Information hiding can be good, particularly when you're dealing with simple data and complex functionality. But when I have the concept of a person, where a person has a name, an age, and a shoe size, why do OO people keep telling me that the Right way to do things is to make accessor functions for everything? Data structures imply certain interfaces, and often they're far better ones than a forest of accessors/mutators. Yes, if I made a person.setAge(27) method then maybe someday I can make sure their shoe size grows accordingly. But I could then never be quite sure what would happen when I called setAge() (and I don't want to have to read the frigging documentation for every bit of code I use!) Far better to just say person.age = 27 (or $person{age} = 27), where I know that even if some bizarre side effect occurs (through tied variables or whatever), the original author is telling me that it'll still do what I asked. The _interface_ is that I can manipulate the parts of the data structure independently, I can pass references to them, etc. If there's a side effect -- writing the new value to disk, say -- then so what? The expected semantics don't change. Yes, the author isn't bound by this, but he at least knows he's going to cause trouble if he violates it. A method like setAge() implies just the opposite: it is explicitly saying that it might do just about anything now, and certainly will in the future, and you're a Bad Person if you write code that doesn't take into account the possibility of setAge() changing your computer's clock. (Current date: April 4, 1980. Alice is now 17. Alice.setAge(27). Current date is now April 4, 1990. What a clever programmer I am!, thinks the author. I'm sure glad I didn't prevent that optimization by exposing the age field!) It's not just accessor methods. They're easy to dismiss by saying "oh, that's the one time you shouldn't do that". Data structures more complicated than a simple structure have the same problem. If I have an array of those person things sorted by last name, and I want to find Mr. Nakamura's age, then how do I do it? Oh, I already told you -- I have an array sorted by last name. The algorithm is obvious. And don't tell me that I'll immediately go down in flames because somebody will stick in a person out of order, which would never have happened had I always gone through a method call. If they put something in the wrong place, then they're not using my data structure any more. They changed it to a different one (an unsorted array), and with that in mind, it's still obvious how to find Nakamura. Ok, the programmer can't use the compiler to think for him/her any more. But it's surprising how little you need the compiler to do your thinking if you keep close to your data. Aha! you say. But what if your data gets too large and you have to change to an on-disk structure? Now you'll wish you hid it behind an API. Well, that's a legitimate complaint. I guess I was wrong after all. Oh, wait -- I only have one of those person objects for each user of my machine. And if I ever have more than a few hundred users, then I'll pour raw egg yolks on my laundry and eat it for dinner. Or more abstractly, I assert that the flexibility of being able to muck with the data structure directly, together with the decreased programming time, combine to outweigh the decreased flexibility in being able to swap out the data structure under some impoverished API. This isn't always the case, but that's the topic of a future, as-yet-unwritten rant about making your code so flexible that it needs Viagra to actually accomplish anything. I just think that time is better spent designing the data structures appropriate to a task, rather than wrapping layers and layers of functionality around your embarrassing, not-quite-right data structures in an effort to make them do exactly what you want. OO survives because it accidentally stumbles upon some good in its rabid pursuit for the irrelevant. For example, "keep your functionality with the data being manipulated." A pointless goal that helps half the time and hurts the other half, but often has side effects of better modularity and better data structure design. You might respond that you can't be modular if your functionality is separate from the data, but how often do you manipulate one data structure at a time? If it needs that much masturbatory manipulation, then it's the wrong data structure. More often you'll be working with two or more things at once, and the code will be short and straightforward if you don't smother it with abstractions and orthogonalizations. Hey, that felt good!