tags:

views:

191

answers:

3

I try to avoid "global" statements in python and http://stackoverflow.com/questions/146557/do-you-use-the-global-statement-in-python suggests this is a common view. Values go into a function through its arguments and come out through its return statement (or reading/writing files or exceptions or probably something else I'm forgetting).

Within a class, self.variable statements are in effect global to each instance of the class. You can access the variable in any method in the class.

Do the same reasons we should avoid globals apply within classes, so that we should only use values in methods that come in through its arguments? I'm especially thinking about long classes that can be just about an entire program. Does the encapsulation inherent in a class eliminate the concern? In any case, we should make inputs, outputs and side effects clear in comments?

+1  A: 

self.variable is not global to the class, it's global to the instance. There's a big difference:

class MyClass:
    def __init__(self, a):
        self.a = a

mc1 = MyClass(1)
mc2 = MyClass(2)
assert mc1.a == 1
assert mc2.a == 2

You should definitely use self to encapsulate data in your classes.

That said, it is definitely possible to create huge overgrown classes that abuse instance variables in all the ways regular variables can be abused. This is where skill and craftsmanship come into play: properly dividing up your code into manageable chunks.

Ned Batchelder
Good point and I'll clarify the question. But there is still the issue of what could be a large section of code, with many methods, sharing a variable in ways that are not totally clear.
foosion
+1  A: 

Do the same reasons we should avoid globals apply within classes, so that we should only use values in methods that come in through its arguments? I'm especially thinking about long classes that can be just about an entire program.

Classes exist to couple behaviour with state. If you take away the state part (which is what you're suggesting) then you have no need for classes. Nothing wrong with that, of course - much good software has been written without object-orientation.

Generally, if you're following the Single Responsibility Principle when making your classes, then these variables will be typically used together by a class that needs access to most or all of them in each method. You don't pass them in explicitly because the class exclusively works with behaviour that could reasonably access the entire state.

To put it another way, if you find yourself with a class that doesn't use half of its variables in a lot of its methods, that's probably a sign that you should split it into two classes.

Kylotan
Classes ALLOW for coupling behaviour with state but that's not the only reason they exist. If you can minimize or eliminate any application state except for the client layer then you're usually better off.
Mark Cidade
Classes define instances of objects and if there is no state then there is no actual object. Thus they are there explicitly for encapsulating behaviours with the associated state. If you have related behaviour without any shared state then you don't need a class, you need a namespace. If your language lacks namespaces, then sure, feel free to abuse a class as one, because that's the best you can do.
Kylotan
A: 

Ideally, no instance-wide variables would be used and everything would be passed as a parameter and well-documented in comments. That being said, it can get very tedious to comment every little thing and method parameter lists can start to look ridiculous (unless you have a hierarchy of partially-applied methods). Pragmatically, a balance should be sought between using non-local variables and making everything excruciatingly explicit.

There is at least one case where you have to have instance- or class-level variables and that's when an implementation-specific value has to be retained between method calls.

Scalability and concurrency depend on minimization if not complete elimination of state and side effects except for the most local and exclusive of runtime scopes. OOP without objects or display classes (i.e., closures) would be procedural, yes. Languages are increasingly becoming multiparadigm, but a lot of them have a primary paradigm. C# is object oriented with functional features. F# is functional with objects.

If the data is immutable, then instance variables are always okay in my books.

Mark Cidade
-1 I think the first part of your answer is misleading, if you use no instance variables then why use objects at all? I agree in the end when you say that instance variables carry implementation specific stuff, but you make it sound like this is a corner case.
nikow
Ideally, you don't use objects at all. OOP is a pragmatic paradigm not an idealistic one, like FP.
Mark Cidade
You can still use objects to pass closures between private methods. Those have immutable state. Parallel goodness and all that.
Mark Cidade
Mark, can you explain more what you mean by "don't use objects at all" and "OOP is pragmatic" as opposed to "an idealistic one, like FP". You seem to be saying don't use OOP. What would an OOP be without objects? Which seems like an extreme statement to say the least. To stretch, and really guess at what you're saying... are you indicating that the real advantage of OOP revolves around polymorphic implementation of interfaces? Which still could be achieved without member data, while avoiding disadvantages of side effects. Of course, you could avoid this anyway by making types immutable.
Phil
But of course, there's nothing to stop an FP from being object oriented also. So, I think that's a bit of a false dichotomy. Anyway, would be interested to hear a more in depth explanation. I haven't marked you down, but presently have to agree (without further explanation) that your answer seems misleading.
Phil
If you look at Web architecture, the server isn't supposed to hold any application state. That means that there are no in-memory objects with instance variables. The reason for this is that it's usually too-hard to keep track of all side-effects. In a pure functional paradigm, there are NO side effects. In Haskell, there are side-effects but they are all EXPLICIT.OOP would be FP if it didn't have objects.
Mark Cidade
Hmmm, well specifically on web architecture, I don't think that the primary reason for avoiding application state is problems with side effects but is more to do with scalability and avoiding assumptions that the same process will handle consecutive requests since processes may be cycled, or that the same server will handle consecutive requests (e.g. load balanced server farms).
Phil
I understand that there are varying levels of purity (side effect free) from one FP language to another. As I understand it, the principal distinguishing characteristic of an FP is that it treats functions as a top level construct. To be pedantic I think an OOP without objects would usually be a procedural language since they are not normally function oriented (they don't treat them as first class constructs - with only usually limited support, e.g. type safe callbacks)
Phil
Of course, the distinguishing lines between OOP languages and FP languages are already blurry and getting blurrier, with languages such as C# gaining more FP characteristics. And does the fact that some FPs support objects (e.g. classes) make them not FP?
Phil
I guess the best question to ask, given your statement (and the fact I think we're talking at cross purposes) is: Are you saying that users of FP languages that support classes should avoid storing data in these classes (even if this data is immutable)? (To me, this is the same as your suggestion to have no instance wide variables; which I think is incorrect - but am willing to learn/be persuaded otherwise).
Phil
Scalability and concurrency depend on minimization if not complete elimination of state and side effects except for the most local and exclusive of runtime scopes. OOP without objects or display classes (i.e., closures) would be procedural, yes.Languages are increasingly becoming multiparadigm, but a lot of them have a primary paradigm. C# is object oriented with functional features. F# is functional with objects.If the data is immutable, then instance variables are okay in my books. I was just assuming mutable state!
Mark Cidade
Got you, I agree on minimizing side effects. I always design most of my (usually C#) classes to be immutable, only breaking this where really necessary/unavoidable. So, I guess we agree, though I think your answer could do with rewording to be clear that you're talking about *mutable* instance wide variables.
Phil