Does breaking encapsulation indicate the wrong type of hammer?
I've had the pleasure of exchanging several emails with Dave Rolsky, author of a new OO tutorial on the subject of whether to introduce treating objects as the underlying hash reference.
He says he won't include even one example because "it really doesn't send the right message. My revisions to perlobj will explain how to implement accessors using the object as a hash reference."
I was shocked, because I find I need to visualize my object's data structures. Also, in several cases, reading or writing attributes directly allows me to implement some needed functionality.
I gave one example of this in a previous post..
Dave suggested the reason I needed to break encapsulation this way is that
I haven't designed my objects properly or
I haven't taken advantage of a full OO framework.
He concludes that I'm using the same coarse hammer to solve all my programming problems, because I'm simply not aware of better solutions.
Those are interesting criticisms.
The second point is absolutely right: I began my OO experiment with Object::Tiny, adding a setter and other facilities as I needed them. In fact, I am proud of this incremental approach, admittedly chosen for my own learning.
Regarding the first point, "design smarts" for me is an extremely limited resource. So I substitute an iterative process of problem-solving and refactoring.
Is it acceptable to use standard Perl tools for this, or should I be reaching higher, tapping more advanced tools? Suppose I had used Moose. Could I have solved my problems easier, more elegantly, with less stumbling?
Well, for one I would have had to ask for help in the Moose community, whereas with hand-rolled OO, I can understand the entire codebase, even if it doesn't meet certain standards of tidiness, design or even hygiene.
On the other hand, I do want my code to be beautiful, for various aesthic reasons, for ease of testing and maintenance, and also to have a code base that will be sufficiently attractive to other people to hack on.
With the aim of exploring whether I can achieve something better using Moose, Mouse, Moo or other advanced framework, in my next post, I'll give an example of some of my more advanced needs, and the naive, if not neolithic ways I implemented them.
Sometimes breaking encapsulation like that is outright-essential. Consider local in:
That simply cannot be done without breaking the encapsulation. There are many occasions in my code I've found the neatest solution to a problem is to localise a member value in an object.
While "encapsulation" is generally a good idea, remember that it's also a dogma, so people will start from the assumption that you shouldn't have broken it, and work backwards to come up with reasons. I wouldn't worry about it. If you run into a situation in the future where lack of encapsulation gives you a problem that's hard to fix, figure out why that happened and avoid making the same mistake again.
I've said this elsewhere, but it's worth repeating: We need to keep in mind the differences between tutorials and reference materials.
Tutorials are not for teaching the reader a solution to every possible scenario they might encounter. Rather, they're for arming the reader with just enough tools that they feel confident handling common scenarios, and the wisdom to know when diving into more detailed docs is required.
In your linked earlier post, you said "We should avoid absolutist language, especially in tutorials." I advocate the exact opposite approach: Absolutist language is forgivable, and perhaps desired in tutorials.. whereas we should avoid it in reference materials.
We teach the rules first. Only when you know the rules can you effectively decide when to break them.
You, Joel, obviously know the rules. You are not the target audience of a Perl OO tutorial. ;)
When I studied the Feldenkrais Method, our teachers explicitly told us that they would be oversimplifying for pedagogical purposes during the first year of training. At times they would say, "this explanation is a first approximation."
While understanding that, when I began exploring Perl OO, I needed an answer to the question "what is an object?" The answer is "a reference to a perl data structure with special behavior accessible via the $object->method(@args) syntax." And that answer goes with demonstrating $object->{key}. I have no problem with absolutist language, but I believe that people are not able to visualize what their code signifies until they appreciate the underlying reality.
Do I know the rules? I guess that adding a 'set' method to Object::Tiny shows that I did. I was certainly not new to programming.
That's a useful example.
@Joel: You say "I believe that people are not able to visualize what their code signifies until they appreciate the underlying reality."
So you weren't able to understand Perl object until you understood hash refs, but you weren't able to understand hash refs until you understood the HV* data structure in the Perl, and you couldn't understand that until you understood the hash bucket algorithm, and you couldn't understand any of it until you understood the assembly generated for the processor, which you couldn't understand until you understood how processors work, which you could understand until you understood the underlying physics.
I think the main factor governing how much of the underlying substrate you need to understand depends on how leaky the higher-level abstraction is.
Traditionally, Perl objects have been extremely leaky. With something like Moose, most of the leaks are plugged.
Woops, I was referring to Leonerd's example. You're right that our coding shouldn't be dictated by dogma. Some of the dogma derives from the experience of people coding for robust large-scale systems with multiple programmers. While informative, it
I was impressed with the bare-bones OO in Miyagawa's cpanminus. He used the simplest possible code to get the behaviors he wanted.
My next post will be the most complicated bit of OO I've done, some AUTOLOAD magic that does proxying, and controls overriding among attributes and method with the same names. I'll be interested to see there is a Right Way(tm) to do this in Mooseland.
You make a good point; the turtles go down a long way.
Seeing below OO level to the underlying objects happens a lot more in perl programming than from the hash variable interface to the underlying structure. In my limited experience, I've never encountered a situation that my code was adversely affected by the character of perl's hash function.
Dave Rolsky maintains that with a proper OO framework, there would be much less need to access the underlying structure. That's a reason for me to learn about Moose, and the benefits of jumping on the Moose-wagon.