For example, Python's lack of variable declarations sometimes leads to bugs involving scoping. (I've run into this a couple of times myself). Does this quirk become more of an issue in heavily functional code? Are there other language quirks that become troublesome in heavily OO code? In what circumstances might one style be preferred over another?
Write More Classes
141–150 of 150 posts
Re: Write More Classes
#142Earlier quoted context omitted.
> good OO for me usually suggests nullary constructors I'm curious, could you please elaborate on this point? If a class has any dependency, i usually find it better to require that dependency to be passed in the constructor, so the constructed instance can always be in a valid initialized state. Why do you find nullary constructors to be good OO?
I came off too heavy-handed there. My intention was more to just say that variables shouldn't be put in constructors if they don't have to be. So, just railing more against the pattern that Java seems to have popularized where every private variable automatically has a getter/setter and can be set through the constructor. Certainly if an object requires some initial state that can never change, passing the value in t…
About the nullary constructor + init() method for deserializing purposes, i don't have any strong opinion really, as long as consistency is kept throughout the code base/module that relies on that. Using Java's reflection API though, you can extract all necessary type information from non-nullary constructors in order to call them with the required dependencies, which is not essentially more complicated than instantiating the class and then setting its properties thought setter methods.
Re: Write More Classes
#143Earlier quoted context omitted.
> This is not a problem with using classes or overriding methods, its a problem either with either failure to document behavior on the part of the library author or failure to read documentation on the part of the library consumer. Missing or poor documentation is a sad reality of programming in the real world. And is the normal state when working on a active project with other developers. This would be mitigated if…
> This would be mitigated if programmers were very careful about declaring methods to be final if it's not perfectly safe to override them Its always perfectly safe to override a method if you maintain its required features. Its rarely, if ever, perfectly safe to do so if you don't. The issue is correctly documenting the required features.
I'm not sure where the disconnect here is. First of all, "correct documentation" might exist in an ideal world, but it rarely exists in the real world. Given this imperfect world, it seems prudent to use technologies and idioms that mitigate the consequences of this imperfection to the best that we are able. Of course no solution is going to be able to eliminate such consequences completely, but that's no reason not to use solutions that offer some benefit.
Secondly, the OP claimed that OO design is generally superior to functional design because it's easier to support overriding of behavior and it's easier to override behavior. Neither of these claims is true. In both cases, attention to detail is required.
Furthermore, in the OO case programmers using a class often fall into the attractive nuisance pit of thinking that just because a method is there, they can and should override it, and programmers implementing a class often neglect to even consider what might happen if a subclass overrides some methods. It's not just a matter of documentation; it's a matter of not even considering the consequences of providing this flexibility by default.
Additionally, when you do parameterize behavior using OO idioms such as template methods, the fact that parameterization is occurring has been obscured, while doing so using the typical functional programming idioms represents paramaterization as, well paramaterization. Who could argue that representing something as what it is is not a good thing?
Re: Write More Classes
#144People don't talk about this anymore for some reason, but I think both Jack and Armin are really just approaching API design in 2 different ways - top-down and bottom-up. The problem is, most people stick with the same approach through out and end up ignoring that programmers are mere mortals too, and they have human needs. Expanding on Armin's dichotomy, top-down designs like Python's open() or jquery plugins start…
IME Ronacher follows this dictum very well. I'd suggest that anyone who wants to see this try his Flask and Werkzeug packages.
As for storing extra state, about which many here have complained, I've found it really helpful that I can set werkzeug.http._accept_re to my own RE when I want to do something weird with media types. That is state that the vast number of users won't need to touch, yet the fact that it exists makes life better for someone who does need it. I'm sure there are numerous other examples I haven't had to bother with yet. Would we really be better off if this RE had to be passed in every time we handled a request? (Although I would understand if you argued this value should be stored in an object not in a module. I haven't needed that yet.)
On the other hand, routing to and handling resources with these packages is typically done with functions and decorators only, although the route decorators are methods of the application object. So Ronacher is not any sort of hardass about classes; he just does what works.
Re: Write More Classes
#145Earlier quoted context omitted.
Well it does not really help that Python lacks tail call elimination (last I checked), which is fairly important to (practical) functional programming.
Meh, you'd use fold, map or filter 99% of the time in a functional language like scala or haskell. TCO is great, but you can still write a lot of idiomatic functional stuff even without it.
TCO is an under-the-hood behaviour that the programmer would count on for practical performance. There's no reason that under-the-hood magic can't be in the implementation of fold/map/filter as primitive control ops.
It's just an accident of history that the [mp]atriarch functional programming language is Lisp, a language that was created in the name of proving a point about recursion. Recursion as the solution-to-all-problems is not essential to functional thinking. The essential ideas are first-class functions, higher-order functions, and referential transparency.
I think this mistake is comparable to thinking that classes are essential to object-orientation. I think many people are confused by university professors who love Scheme (for reasonable reasons), and who like to pretend that Lisps are the only alternatives to Fortran (arguably true in the '60s).
Re: Write More Classes
#146Earlier quoted context omitted.
being googleable and knowing what he is talking about doesnt mean that his this quote is relavant in this context. What he said is a good piece of advice, but only when looked through larger window of programming. When we are talking about only python and choices of coding style in python, his quote looks like santa on valentines day!
That's fine. Armstrong may be wrong in this case, but he doesn't deserve the ad hominem attack.
Re: Write More Classes
#147Earlier quoted context omitted.
> - Why do I need a class for streaming JSON - Python's got a perfectly good `yield` for returning tokens in such situations. See the msgpack-cli example at the bottom. Say you have a function that returns a generator for tokens in Python. You would need another function that builds objects out of them. How do you customize how objects are being built? A class makes that simpler because each of the methods are extens…
I think > A class makes that simpler because each of the methods are extension points you can override. is a strong argument in favour of classes. They're more extensible even if the author doesn't consider it. However - as soon as your class has an implementation like def to_json(str) JSONParser.parse(str) # JSONParser is not streamed end then you're in trouble. Unless your language supports dynamic lookup of consta…
use 5.016;
use warnings;
package JSONParser {
sub parse {
my ($self, $str) = @_;
"JSONParser::parse $str";
}
}
package Foo {
sub new { my $class = shift; bless {}, $class }
sub to_json {
my ($self, $str) = @_;
JSONParser->parse($str);
}
}
my $foo = Foo->new;
say $foo->to_json("foo");
{
# OK... I want to amend that JSONParser->parser behaviour
# but just in this scope!
no warnings 'redefine';
local *JSONParser::parse = sub {
my ($self, $str) = @_;
"No Longer JSONParser::parser! $str";
};
say $foo->to_json("bar");
}
say $foo->to_json("baz");
This outputs... JSONParser::parse foo
No Longer JSONParser::parser! bar
JSONParser::parse bazRe: Write More Classes
#148Earlier quoted context omitted.
> This would be mitigated if programmers were very careful about declaring methods to be final if it's not perfectly safe to override them Its always perfectly safe to override a method if you maintain its required features. Its rarely, if ever, perfectly safe to do so if you don't. The issue is correctly documenting the required features.
> The issue is correctly documenting the required features. I'm not sure where the disconnect here is. First of all, "correct documentation" might exist in an ideal world, but it rarely exists in the real world. Given this imperfect world, it seems prudent to use technologies and idioms that mitigate the consequences of this imperfection to the best that we are able. Of course no solution is going to be able to elimi…
Assuming that methods which actually mitigate those consequences exist, and all other things being equal, this is true. In the use cases for which class-based object-oriented design is well-suited, all other things are not equal between class-based object-oriented design to support providing base functionality with overriding in subclasses and using functions that take functions as optional parameters to provide base functionality with per-call overrides, even before considering whether, when used for that purpose, the functions-as-parameters approach actually mitigates anything.
Particularly, they are not equal in that the class-based approach avoids repetition and makes it clear the unit the behavior is attached to, while the functional approach does not. The functional approach is obviously cleaner and clearer for per-function-call parameterization, while the OO based approach is cleaner and clearer (unsurprisingly) for per-object or per-class parameterization.
> Secondly, the OP claimed that OO design is generally superior to functional design because it's easier to support overriding of behavior and it's easier to override behavior.
I haven't been defending OPs claim, I've been criticizing your response which argued that functions-as-parameters was not merely as good but actually categorically superior to OO design for this purpose.
> Neither of these claims is true. In both cases, attention to detail is required.
"Attention to detail is required in both cases" does not, if taken as true (which I have no problem with), refute the claim that these things are generally easier to support in OO.
> Additionally, when you do parameterize behavior using OO idioms such as template methods, the fact that parameterization is occurring has been obscured
No, its not. Inheritance is categorical rather than per-call parameterization, and so using it presents what is being done as exactly that. Using functional idioms for categorical parameterization either involves recreating class-oriented structures or conceals (and makes less DRY) the categorical nature of the parameterization behind per-call overrides.
Re: Write More Classes
#149Earlier quoted context omitted.
To attack the quote itself by simply assuming the author is inexperienced in OO just silly. No one is assuming anything about his OO skills, they are reading the words written and assuming the author isn't lying.
Erm, really? Love it when people write about OO without OO experience.
[Edit] It's the same when people quote Linus on GUIs. He might be an excellent kernel hacker, with a great understanding of large scale open source development, but his opinion on GUI is as good as everyone else. Or how people quote Wozniak on everything. This is not science but a guru cult. I'm proposing that we move our industry to facts and experiments and end the pop culture and guru cults. I'm not with Raganwald that we should embrace this pop culture. This is the reason that I vehemently disagree when people cite Joe Armstrong as an expert on classes or when Joe Armstrong tries to stir up people my bashing OO.
Re: Write More Classes
#150Earlier quoted context omitted.
> The issue is correctly documenting the required features. I'm not sure where the disconnect here is. First of all, "correct documentation" might exist in an ideal world, but it rarely exists in the real world. Given this imperfect world, it seems prudent to use technologies and idioms that mitigate the consequences of this imperfection to the best that we are able. Of course no solution is going to be able to elimi…
> Given this imperfect world, it seems prudent to use technologies and idioms that mitigate the consequences of this imperfection to the best that we are able. Assuming that methods which actually mitigate those consequences exist, and all other things being equal, this is true. In the use cases for which class-based object-oriented design is well-suited, all other things are not equal between class-based object-orie…
Having programmed heavily in both functional and OO styles, I personally find the opposite to be true. I find the functional approach to be cleaner and clearer in general.
I particularly find template methods to be egregious because when you override a callback method, it's not immediately clear that what is being overridden is even a callback. Additionally, in programming languages that don't require an "override" declaration to override a method, it's not immediately clear that a method is being overridden, rather than just a new method being defined. And with multiple inheritance, this is even worse, because you might have to look in a zillion different other places to even determine this.
> Using functional idioms for categorical parameterization either involves recreating class-oriented structures or conceals (and makes less DRY) the categorical nature of the parameterization behind per-call overrides.
Recreating class-oriented structures? There's no work to do this, and there's nothing non-DRY about it. E.g., see the book JavaScript the good parts. It shows you how to define objects using either JavaScript's OO-based mechanism or using a Scheme-like functional approach. The functional approach is elegant and popular.