just functions and data structs in a namespace will prevent you from entangling your code in some ways that are basically expected when using OO.
just functions and data structs in a namespace will prevent you from entangling your code in some ways that are basically expected when using OO.
For reasoning about and maintaining, you can just think of `self` as an extra parameter to the function that gets bound to the thing to the left of the dot. In some languages, like Python, this is how it actually works, so the testing argument doesn't apply either:
>>> class C:
... def __init__(self, x):
... self.x = x
... def f(self):
... print(self.x)
...
>>> c = C(3)
>>> c.f
<bound method C.f of <__main__.C object at 0x7fdb6b9b9240>>
>>> c.f()
3
>>> C.f
<function C.f at 0x7fdb6b9b1ea0>
>>> C.f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() missing 1 required positional argument: 'self'
>>> C.f(c)
3In Python it isn't implicit, but it's still shared state, and so still hard to test and maintain. You can't test the `f` in your example without having to pass in the whole big bundle of state that self tends to be, even if you do so explicitly.
cies said structs were ok, what's the difference in this regard? 'Shared state' doesn't usually refer to explicitly passing a data structure into a function as an argument; it's operating on shared state only in the same way that any function which takes for example a string or a hash does.
Small, appropriately scoped structs are ok. Passing a big "god struct" around to functions that are only going to use a couple of fields is bad.
> 'Shared state' doesn't usually refer to explicitly passing a data structure into a function as an argument; it's operating on shared state only in the same way that any function which takes for example a string or a hash does.
Passing a mutable value into a function still counts, I think.
Indeed. Structs are specific, self is "the whole shebang". And while (annoyingly) explicit in Python, it is common and OO-practice to pass self to all non-static members, thus defacto the self is mostly there. Writing member methods as static (or class methods, as called in Ruby land), is a great way to make code a bit more "functional".
At some point you simply do not use self anymore and the class is merely a namespace with some unused features.