Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^4: Why encapsulation matters

by Ovid (Cardinal)
on May 19, 2008 at 08:20 UTC ( #687304=note: print w/ replies, xml ) Need Help??


in reply to Re^3: Make everything an object?
in thread Make everything an object?

The problem I generally have with OO is that most people don't know it and then they get frustrated (and rightly so). This is because it's not being taught very well and I certainly had painful experiences with it when I started. That being said, I can't say I disagree with your post, but I can't agree with it, either, because I don't understand what you're trying to say. I guess I work better with examples :)

My argument goes like this: expose nothing.

Pretty simple, eh? If the class should be responsible for something, others should not know or care how the class does it. This is even more important if exposing those details allows code outside the class to put an instance (or worse, the class itself) into an invalid state. By pulling logic outside of the class, this risk increases. For example:

my $auth = Authentication::Manager->new( { store => $store } ); if ( $auth->authenticate($username, $password) ) { delete_the_data_store($store); } else { throw_some_exception "invalid credentials"; }

That if/else is a bug waiting to bite. It only takes one absent-minded programmer to forget an if/else block there and then life becomes pain for everyone.

The authenticate method should probably be throwing its own exception and the calling code, if it cares, should catch it. By not doing this, it's much easier for the calling code to forget to check the return status of that method. Forcing the consumer of a module to write extra code is a recipe for bugs. Here's a somewhat better way:

my $auth = Authentication::Manager->new( { store => $store } ); $auth->authenticate($username, $password); delete_the_data_store($store);

Because authenticate throws its own exception, you can't reach the offending code unless you authenticate (i.e., forgetting an if/else block doesn't matter) and the code is easier to read. You can't forget to check the return code (unless you explicitly have a block eval and don't check $@).

So the point I am making is not "shove everything inside of the class". It's "expose nothing until you know you need to expose it". I've found that this has worked very, very well in managing larger code bases.

Cheers,
Ovid

New address of my CGI Course.


Comment on Re^4: Why encapsulation matters
Select or Download Code
Re^5: Why encapsulation matters
by BrowserUk (Pope) on May 19, 2008 at 09:30 UTC
    The problem I generally have with OO is that most people don't know it and then they get frustrated (and rightly so).

    My biggest problem with OO, is that there are a bunch of people--like you--that think they know what they are talking about, but don't.

    Re-read my post to which you responded. Follow the links. Re-evaluate your knowledge and experience in the light of the credentials of the author I quoted. Consider, just briefly, whether what you are selling is stone tablet, sermon-on-the-mount material?

    Or just your best guess as to "What's best practice"?

    Nothing in that post can be dismissed as "the ramblings of BrowserUk". Verbatim quotes back by extensive references to a known, attributed, published author.

    Are you sure, really sure, that you know better than he does?

    If you are, go argue with him.

    If you're not quite so sure of yourself as when you type that diatribe above, then think carefully before responding.

    You may think you know who I am, but you only know what I've told you. I have many persona's. At least three here at PM. (And no Tye, checking the IP logs won't help. All my IPs are dynamic and I have ISP accounts in Poland and Russia as well as the UK).

    So, whilst I may advocate (strongly), "Examine what is said, not who speaks", sometimes, it is a very revealing exercise to consider ones own experience and knowledge in the light of those with whom one takes issue. (Note: Him, not me).

    So the point I am making is not "shove everything inside of the class". It's "expose nothing until you know you need to expose it". I've found that this has worked very, very well in managing larger code bases.

    And there you go, making the typical "OO cool-aid drinkers mistake". Read the article. I'll quote, directly this time, a (multiply) published author. An "expert in his field":

    Encapsulation is a means, not an end. There's nothing inherently desirable about encapsulation. Encapsulation is useful only because it yields other things in our software that we care about.

    The assumption, that encapsulation is king, (along with "inheritance is king", "polymorphism is king") is wrong. In so many ways. Only one of the four tenants is king: "abstraction". This can be defined as

  • the process of formulating general concepts by abstracting common properties of instances.

    Which is accurate, if a little pedestrian. There is another definition which is far more important though:

  • the act of withdrawing or removing something.

    Whilst what you advocate or aspire to, complicates rather than simplifies, you are, as the saying goes, a part of the problem, rather than part of the solution.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      I've read what he's written and his primary thrust is is that syntactic inconsistencies are unavoidable because anything more than a non-trivial use of the class requires them. Since he argues(1), that classes should be both complete and minimal -- needs that are sometimes in conflict -- he asserts that it's better to embrace that up front to accept the minimalism, other wise you have an explosion of methods which can make a class harder to maintain and wind up providing a bunch of useless features that people don't really need (his "nap" function was an excellent example).

      Frankly, I agree with most of what he wrote, but avoiding the issues he describes without resorting to non-member, non-friend functions is often very easy -- but you don't want to hear it since, as you were quick to point out, he's an expert and I'm not. Thanks for making that distinction clear.

      Update: I should also point out that what he's (the author BrowserUK points to) discussing involves a very long-standing issue with OO design that is extremely well-known, but it's only in the past few years that newer techniques for resolving it have been widely explored. The problem, basically, is that you can't have a class anticipate everything as this violates the need for minimalism and you're going to get it wrong anyway. The author presents one technique for resolving this issue, using something called 'non-member, non-friend functions'. There are, of course, quite a number of other ways to address this. I can think of at least six different techniques for resolving this issue. However, though the author correctly identifies a significant problem, stating that his is "the one true way" out of quite a number of different possibilities seems a bit limiting.

      1: His "complete but minimal" argument is correct, in my opinion, and there are strong echoes of a famous paper which addresses this, but since I'm not an expert, I'm not entitled to an opinion here. Ironically, my concrete example is completely unrelated to the issues he pointed out, but somehow that appears to have been lost in the shuffle.

      Cheers,
      Ovid

      New address of my CGI Course.

      Oh, and I forgot to point out the incredible irony of your post: you take me to task for disagreeing with an article that you didn't understand. You wrote:

      Re-read my post to which you responded. Follow the links. Re-evaluate your knowledge and experience in the light of the credentials of the author I quoted.

      And later you wrote:

      The assumption, that encapsulation is king ... is wrong. In so many ways.

      You repeatedly argued that I didn't know what I was talking about, but you apparently didn't understand the article you linked to. Just look at the title:

      How Non-Member Functions Improve Encapsulation
      Scott Meyers
      When it comes to encapsulation, sometimes less is more.

      When you read closer what he writes, his "less is more" isn't referring to less encapsulation being better. He's arguing that minimal classes give you an opportunity for better encapsulation. He's arguing that "encapsulation is king" and I agree with him even though you have stated that this argument is wrong. What I don't agree with is the assertion that his "one solution" (out of at least six that I previously alluded to) is the only (or best) solution. Your "encapsulation is king ... is wrong" completely misses the point of what the author was arguing for.

      Go back and reread what he wrote. Carefully. Go back and reread what I wrote and see how my concrete example does not, in any way shape or form, conflict with what he wrote.

      Cheers,
      Ovid

      New address of my CGI Course.

        you take me to task for disagreeing with an article that you didn't understand.

        Of course I understood it. Else why would I have made such efforts to emphasis the following (re-quoted with my original emphasis intact):

        If, on the other hand, that function can be implemented as a non-member, non-friend, "free" function (sub) it won't have to change if the data format changes, so doing so increases encapsulation.

        No one, neither he not I, are arguing that encapsulation isn't important. It's all about how you achieve it. My point was and is clear. It is not necessary, or desirable, to stuff everything inside the class in order to achieve encapsulation.

        His point was that encapsulation can be maintained, and even enhanced, by keeping stuff out of the class. Contrast that approach with your "My argument goes like this: expose nothing" approach?

        You also say: He's arguing that "encapsulation is king" and I agree with him ..., but I think we must have read different articles.

        There are four tenants of OO, and if any of them are king, it has to be abstraction. The trick to effective use of OO (remember the key word in the titles of his series of books?), is to balance those four tenants.

        • Inheritance is a useful way of achieving code re-use (DRY), if used correctly.

          But it is well documented that over-use of inheritance leads to a big ball of OO spaghetti (to mix a few metaphors).

        • Polymorphism is another useful mechanism for achieving code re-use, when used correctly.

          But using it incorrectly leads to dichotomies that are unresolvable.

          Eg. Building a Point3D class on top of a Point2D class doesn't work, because a 3D-point is not a specialisation of a 2D-point. Any given 2D point will map to an infinite number of 3D-points from any given observers point of view. And that same 2D-point can be mapped to any single 3D-point, from an infinite number of planes of observation. However, a 2D-point can always be derived from a 3D-point successfully.

        • Encapsulation can yield benefits in reduced maintenance.

          But they nearly always come with an up-front cost in increased development and complexity. Balancing the needs of the (foreseeable) future against the costs of knowable now, is the trickiest decision every architect has to make.

          Done right, encapsulation minimises the costs of change by containing them, thus decreasing coupling. Done wrong--eg. stuffing everything into one big class--it increases coupling, increases the length of dependency chains, and so increases the costs of change.

          The target of encapsulation, its raison d'etre, is to simplify maintenance. Not to hide everything from everyone.

        • Abstraction yields benefits by simplification.

          Files and folders (or directories) are simpler concepts to think about and use than i-nodes, free-space chains and disk-blocks. Arrays are simpler to program than pointers and index register manipulations. CGI forms are easier to use and program than the query strings they hide. Pull-down menus, check-boxes and dialogs are easier to navigate and get right than endless streams of scrolling man pages and huge long strings of nearly meaningless option strings (What do you think the option is to disable spurious warnings of uncheckable memory bounds?).

          But even an abstraction comes with a cost. Simplicity for the user is traded against complexity for the implementor. Again, a balance must be sought.

          But the other three tenants serve only to service the needs of the abstraction. Once sight of that fact is lost, and they start to becomes ends in their own right, the very purpose of OO (simplification through abstraction) is lost also. Thence comes complexity for only the sake of dogma.

        There's a long, wordy, difficult and sometimes very repetitive, but oh so insightful document, Object Orientation Redefined I highly commend to you. It's a difficult but very well worth while read.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://687304]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2014-12-21 06:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (104 votes), past polls