I think of it in analogy to math. OOP is like topology - it's definitely useful in some cases, it's not too hard for an experienced mathematician to get the basics, and yet in a lot of situations it's irrelevant and it doesn't really belong in the first class you take.
Being able to solve fizzbuzz is like doing arithmetic. If you can't solve fizzbuzz then you aren't going to be able to really get any advanced concepts. It's like you can't be a good mathematician if you can't figure out whether 351 is an odd number - you need to learn the basics first, even if "real math isn't about arithmetic".
Sadly, you can tell if you do a lot of phone screens that many people who graduate with CS degrees still can't code fizzbuzz. Our CS education is busted right at the beginning. It needs to get the basics right, like, can you write loops, can you write functions. Today it is failing at that.
It reminds me a bit of how I was taught basic economics, where societies go from barter to currency. Apparently this is not true at all, but it's a story that is easy to teach.
They are two completely different processes.
I have experience teaching kids Lua, and with the right metaphors and a little bit of backtracking and foundation-building, even complicated ideas like emulating classes and single inheritance can be understood and even implemented by young students.
If I taught them lua reserved keywords, and a couple little math tricks here and there, they usually would all bunch up everything into a couple huge functions, and their game would (sort-of) work but be impossible to reason about, and very painful to extend.
Introducing objects as a way to represent things that they want the game to do (draw things, shoot things, eat things, etc), it becomes clear to them that there is merit in structuring programs with objects beyond "shrugger says to do it like this!"
OOP on its own doesn't make much sense. You can't teach someone to drive stick shift if they don't know what a car is. Maybe you could, but that's probably even worse.
I'd modify that to "practical programs that are nontrivial enough to benefit from OOP", just like how I advocate not teaching about functions until they become useful. IMHO the CS curriculum should start with the low-level basics and work up from there in a natural progression:
- Representation and interpretation of binary data.
- Basic straight-line computation (more like calculation), concept of instruction execution
- Flow control: decisions, loops
- Functions/procedures/subroutines
- Grouping data together: Arrays/structures/records/etc.
- Basic OOP, grouping data and code together: Objects, composition, inheritance
- Advanced OOP: virtual functions/polymorphism/etc.
I have worked with some of that type of Java-student you mention, and it is astounding how many can create huge object-oriented monstrosities (including design patterns), the bulk of which are object creation and method calls, while not understanding arrays or even basics like why datatypes have a finite range. Their code has more object creation and method calls than branches, loops, or simple computational statements. Given that sort of inverted knowledge they have, that they fail fizzbuzz is not surprising at all. It also explains a lot of the inefficiency and bloat in most software. It's somewhat like teaching calculus to students who don't know arithmetic.I've asked a few why OO is the first thing you learn - and the reasoning was two fold:
1) People that start off by learn imperative programming end up writing really really shitty OO code. They're they type of people that end up copy and pasting stuff everywhere. It's really hard to get students to not take the "short cut" of copy paste to think in objects when you have homework deadlines and other things to worry about (and the teacher never actually spend time to teach you how to use programming toolchains...)
2) it's conceptually one of the biggest stumbling blocks for people. A lot of people have trouble wrapping their heads around OO. So sure you could teach it later, but it'll never sick or sink in.
Moreover, the fact that "subclassing==subtyping is unsound" is swept under the rug. A lot of people actually grasp the latter at an intuitive level, that's why they're never comfortable with objects.
OO should be taught as abstractly as possible (I recommend Didier Remy's writings). After grasping the concepts, many people will conclude that they'll be better off with FP and modules.
Could you explain what you mean by that, and why you think it's true?
Maybe this is related to the common occurrence of people who can provide stellar answers to interview questions about inheritance hierarchies and object composition... and yet can't pass a basic fizzbuzz style test?
If every tech interviewer phone-screens by asking about multiple inheritance and red-black trees, it's really not surprising that universities might tip the curriculum towards that sort of thing at the expense of actual programming experience. After all, if you can't pass the phone screen you'll never get the opportunity to write code.
For example, AP Computer Science requires Java and tries to teach stuff like designing inheritance hierarchies to people in their first two months of programming education. And then tests it mostly using multiple-choice quizzes. It's totally inappropriate - most of these students would fail fizzbuzz.
OOP should be something you only get into after you have written some practical programs, rather than something where you can't program, but you memorize the difference between "is-a" and "has-a" inheritance so that you can pass multiple choice tests.