2

This is a question that perplexes me about object oriented programming. In some OOP languages (e.g. C++) a member function can access private variables of the class without restriction. That means one can define methods that take no arguments and change the private variables. Isn't this considered bad programming practice? Lots of thought has gone into how function arguments can be passed by value or reference, and what that implies about program complexity.

I would like to make this question less about opinion and more about facts. Let's consider the goto statement. The goto statement has been deprecated as bad programming practice in favor of structured programming. Did any objective data go into that decision? It appears to be intuitive that goto is problematic, but is there a factual basis for the deprecation? Were programs studied, surveys conducted, etc.?

Getting back to my question about member functions, is there an objective basis for answering this question? Should member functions of a class be allowed to manipulate variables not in the argument list? Has there been research to determine this question? Is there a branch of computer science research that attempts to determine best practices in language design based on objective criteria?

Thank you.

closed as primarily opinion-based by Scant Roger, Kilian Foth, GlenH7 Nov 23 '15 at 18:50

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Well, each member function gets a this pointer passed, though only implicitly. – 5gon12eder Nov 22 '15 at 5:21
  • Recognize that, first, C++ was required to maintain backwards compatibility with C, and, second, C++ had to look ATTRACTIVE to the flying code monkeys who collectively believe that C is a good language, while simultaneously dragging them kicking and screaming into the light. Stroustrup's first goal for C++ was adding strong typing to C, the feature that caused the flying code monkeys to scream from the rooftops when they encountered it in PASCAL and Ada. His SECOND goal was to port the Simula-67 class concept, which became OOP. – John R. Strohm Nov 22 '15 at 8:01
  • Thank you. I thought C was strongly typed, so I need to learn more. OOP was invented for a specific purpose, as you say. OPP then became an over-arching programming paradigm. It is not suitable for such a central role. Other ideas more closely tied to economic benefit should determine language design and use. What I mean is: programs are part of organizations with diverse staff. To achieve maximum productivity for the entire organization, such factors as training time and code maintainability should be considered. What language delivers the most back per buck? – Anthony Mannucci Nov 22 '15 at 8:48
  • 1
    I see one big problem in your proposition: If code outside the class doesn't know about the private members and the code inside the class can't access them unless they are passed as a parameter, who is going to pass those private members as parameters? – Bart van Ingen Schenau Nov 22 '15 at 9:11
  • @Bart sorry if I was not clear. The private variables are passed to the functions within the class. E.g. in a C program, one can define a variable in main(). That variable can be passed to a function that is called within main(). However, that function has no access to the variable in main(). Access is restricted to what is passed in the function's argument. I am suggesting that methods within the class have to work a little harder to have access to private members of the class. – Anthony Mannucci Nov 22 '15 at 12:57
3

There are a few important differences between private members of a class and global variables.

Global variables are accessible by any part of the code, as long as the author of the code knows the name of the global variable. Private members are only accessible to member functions of the same class.
Furthermore, in most OO languages, member variables are by default instance members and the member functions can only access instance members of objects that are passed into the function (either implicitly by calling the member on an object or explicitly).

This means that effectively, your proposal is already part of most OO languages, except that the private members aren't passed in individually, but rather en-bloc (by means of the this or self pointer/reference).

  • Yes, it's the "en-bloc" aspect that is confusing. It means that every function could modify every private variable. One cannot tell what is happening to the object state either from the function arg list, or what the function returns. This is detrimental to understanding and reading code. It's just a less-worse example of global variables. Similar in spirit but not in degree. I am surprised the authors of OOP languages had no problem with this. (I speak from how I was trained as a programmer of numerical codes). – Anthony Mannucci Nov 22 '15 at 19:35
  • @AnthonyMannucci Just knowing which variables can be modified won't tell you that much about what is happening to the object state. If you need to know that, you either need to look at the code of the function or use something like design by contract. – svick Nov 22 '15 at 23:19
  • @AnthonyMannucci: Designers of OO languages did not have a problem with it, because from the outside an object is regarded as a single unit, not as a collection of private members. To take another example, if you do a matrix multiplication, would you rather just specify the two matrices or all the individual elements that are touched by the multiplication? – Bart van Ingen Schenau Nov 23 '15 at 7:32
  • @svick My assumption is that I will have to look at the code. I am suggesting that having functions arguments helps that process of looking at and understanding the code. – Anthony Mannucci Nov 25 '15 at 22:03
  • @bart In looking at the code of the object, I'd want to know how the code is organized and how that affects the matrices. Functions that pass in the matrices as arguments (by reference) will potentially change the matrices. Functions that do not will not. That knowledge is helpful for reading the code. Perhaps what I am proposing is called "structured programming", and that is not a priority in OOP. – Anthony Mannucci Nov 25 '15 at 22:06
0
  • Despite being over-hyped by the industry, object-oriented programming's saving grace has been that it tends to to encourage programmers to write code that is easier to follow for other programmers, with fewer comments.

  • In terms of code reuse and code simplicity, OOP unfortunately tends to provide limited advantages, and perversely ends up usually resulting in more lines of code. One of the biggest advantages of OOP is reducing the reliance on long, redundant, picky argument lists for functions. When you have a function with 8 arguments, 6 of them shared with a dozen other functions, that's when this advantage appears.

  • The drawback of trying to track mutable state or global-like variables is one that continues to dog OOP. For these sorts of reasons, Functional Programming languages like Haskell, Erlang, F#, and Scala have continued to garner press and use in recent years. We also see Functional Programming features, like treating functions as first-class citizens, making their way into OOP languages in recent years.

  • In terms of best practices, most OOP theorists would probably say that class properties should be used sparingly, that functions should be kept small, and class properties should only be writable from within the class (aside from being passed at instantiation). While this addresses the disadvantages, it doesn't enforce best practices. The result of this and other controversial features in OOP (like inheritance) is that there can be a lot of debate and confusion about how best to implement OOP.

  • Thank you. I have a completely different view of OOP. It makes code harder to follow. The reasons are: constructors can run all sorts of code on declaration of an object, and what is occurring is not at all clear from the declaration. Methods can change the object state in unclear ways (this is the issue I raised here). It's hard to read the code and see how the object states are going to change in time. I find OOP code very hard to follow (at least the example I am working with). I agree with many of your points above. – Anthony Mannucci Nov 22 '15 at 19:47
  • Personally, I agree with you that OOP code can be very hard to follow. I see a lot of developers overusing OOP, overthinking or underthinking things, creating a murky maze of relationships among overly-numerous, semi-meaningless objects. I agree that old-fashioned structured programming is so much more clean and tight. Unfortunately, OOP has become almost a universal religion in the industry today. So we ignore it at our peril. Do you work in FORTRAN or C or a language like that? If so, I think that's cool. – John Doe Nov 22 '15 at 20:06
  • I mostly program in python these days, but we have codes in C++ and FORTRAN. The FORTRAN code is much easier to follow. (These are numeric scientific codes). For my python, I use objects when it makes sense to me. Python uses objects well in my opinion. Note that the language itself is written in C. For our work, relationships between objects is much less important than what happens to data structures or objects as time evolves. For that, the OOP paradigm can really obscure things. – Anthony Mannucci Nov 22 '15 at 20:34
  • OOP also uses more memory and can hurt performance. I think you said it best; we should use OOP selectively and cautiously, where it helps more than hurts. – John Doe Nov 22 '15 at 20:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.