The standard dogma of OO-design is, that you should certainly not allow access to the internals of an object to the outside world. Instead you are to expose operations on that type. Generally there seems to be a consent in my current environment that getters and setters are evil, as they do indeed expose internal state. However everyone is using them. So what is going on?
Recently functional programming got a lot of interest (rightfully so), e.g: F#, Scala and a modest come back of Haskell (Curry on!). While in OO we always strive to hide information (which might be a bit of a misunderstanding anyways), while in Haskell it is quite natural to decompose a bit of data and to define functions in terms of functions of the components.
Scala for example provides two alternatives for defining operations on datatypes. There is traditional polymorphism and case classes that allow pattern matching style operations. Odersky sees both approaches as complementary argueing that the traditional OO solution makes it easy to add a new type, by just implementing operations, while pattern matching allows for easy addition of new operations on given types.
My current thinking is that there is certain areas, essentially whenever we externalize state of objects (e.g.: persistence, serialisation, or UI), decomposing an object into it’s components and have generic operations performed on those seems to be quite beneficial. I am not sure, how to allow for such legitimate uses and to prevent all kinds of logic to access the state. Getters and setters are alright, if you use them responsibly. However one could also imagine a more generic access mechanism, perhaps passing in a callback, that takes the components, of the original object as parameters.