So OOP is crap?

I just read this
http://mollyrocket.com/casey/stream_0019.html

Casey says using Object Oriented Programming is horseshit.

I learnt BASIC, then 68000 assembly on an Amiga, then tried to force myself to learn C++ with Teach Yourself C++ by Herbert Schildt, then forced myself to learn Java....This was all about 20 years ago and looking back now, I remember those two later languages were probably responsible for putting me off programming until slowly getting back into it now.

But...

Does C++ and OOP really not have a use for modern game making and the huge worlds that are being built now?

Playing GTA V on my Xbox 360, I was thinking I can see how the OOP methodology could work there...Say two dozen base classes with a huge number of derived classes.

So of course this could be done in C, but does using the OOP paradigm make code for these huge open world games more manageable?

I intend to make small 80s 90s arcade style games so the above will not apply to me, but I just wanted a bit more clarity on why Casey says OOP is bad when (I would presume) most commercial games make use of it.
So, I'm not an experienced game programmer, but I've been trying to parse the answers to this very question over some months now, and I can list at least a few of the salient points I've heard from different voices.

1) Inheritence is a poor model for reuse. Often in games you want to compose your objects from different behaviors, and do so dynamically. It's better to allow your entities to be mixed together, and for each system (physics, collision, rendering, sound) to control the relevant state. Because:

2) Cache coherence is a big deal. If you have a list of 1000 integers, and you want to insert one in the middle, is it faster if that list is an array or a linked list? The answer might surprise you. The time "complexity" we were taught is valid, but it can lead to bad intuitions because it turns out constant factors matter quite a bit. OOP encourages linked structures and pointer chasing all over the heap. However, in fairness, you can totally do a cache coherent data layout with classes, too. You just have to ignore a lot of features.

3) Virtual dispatch is slow. For similar reasons: pointer chasing.

4) RAII sucks. It sucks worse for memory than for less used resources. But it provides less value in those places because they are less used. There are simpler patterns available. But most OOP literature will push you towards RAII (or GC) because

5) Exceptions suck. They force you to spread error handling (and cleanup) across your codebase. You should work to limits the surface areas of your api that can raise error conditions.

6) There are simpler, easier ways.

I'm sure there are more and better points than these, but as a person a couple of steps down the road, this is what I've been able to wrap my head around.
I did not read the whole post but he starts talking about OOP using a payroll system as an example, other than being software, a payroll system and a game have next to nothing in common.

Jumping head first into programming anything is great for learning (case in point: Handmade Hero) but awful for actual results, careful planning and taking your time to choose the right tools for the job (be it OOP, or design patterns, or even a game engine) goes a long way into improving your development time.

In summary, you could develop an OOP game just as easily as you could develop the same game without OOP (chess for example) play.elevatorsaga.com perfect example of an OOP game that can be solved using non-OOP code.
But which code base would be easier to manage and improve as it got larger?

Say using the GTA V example again, would that code base be manageable if written in pure C?

My thinking is, computers are so powerful these days, that the performance penalty of making human friendly code probably outweighs that of working more for the benefit of the machine.

I think the bottom line is that you can go too far in either direction, and a good programmer knows balance.
OOP is crap in terms of design flexibility as well as performance, so it's not really about tradeoffs. OOP is one of the few things that I think is just a complete lose across the board, offering no benefits and saddling the code with many downsides.

But, that is certainly not a universal opinion among game developers, although it does seem to be a growing consensus compared to where it was a few years ago.

- Casey
The only OOP system I've ever enjoyed working in is Cocoa and ObjC. However, that system does OOP very different than most other systems.

In many places, very deep, nested type hierarchies are not only common, but encouraged. This is extremely problematic. There are so many design patterns around fixing OOP issues that it's quite silly.

Go research the fragile base class problem as just one example.

Can you build great apps using OOP, sure. But that's because the programmer built a great app in spite of the tools provided.
owensd
The only OOP system I've ever enjoyed working in is Cocoa and ObjC. However, that system does OOP very different than most other systems.

Yes. The dispatch performance is even worse than that of C++.

owensd
In many places, very deep, nested type hierarchies are not only common, but encouraged.

Leaving performance aside, and just considering data modelling, this can work if and only if you got the hierarchy correct the first time. To quote ESR:

One reason that OO has succeeded most where it has (GUIs, simulation, graphics) may be because it's relatively difficult to get the ontology of types wrong in those domains. In GUIs and graphics, for example, there is generally a rather natural mapping between manipulable visual objects and classes. If you find yourself proliferating classes that have no obvious mapping to what goes on in the display, it is correspondingly easy to notice that the glue has gotten too thick.

Now to be fair, he wrote that 12 years ago. It's still probably true that OO and WIMP-style GUIs still seem to be a natural fit, because they grew up together. OO is still very much used for non-realtime graphics, because other performance issues tend to overwhelm any penalty from using OO.

One thing that's important to understand is that just because a C++ programmer writes the word "class" doesn't mean they are "doing OO". Classes in C++ are used for lots of purposes, such as to enforce information hiding. If C++ had a module system, that would be one less reason to type the word "class".

The STL is a case in point. It has a lot of classes, but exactly no virtual functions anywhere.
Pseudonym73
owensd
The only OOP system I've ever enjoyed working in is Cocoa and ObjC. However, that system does OOP very different than most other systems.

Yes. The dispatch performance is even worse than that of C++.


True, but at least the cost actually brings something worthwhile to the table. I'll take the flexibility of ObjC over C++ every time. When I need raw performance, I'll either cache the selector call or write pure C code.

I will never suffer through writing another UI in C++ again. There are simply better tools for that domain.

[edit]

Also, the Cocoa API uses inheritance as a last resort (other than from NSObject). Your first choice should always be about composition. In this regard, it very much the same design pattern, it's just implemented in a language with a dynamic runtime.

And templates... yeah, nice on paper, maybe. Terrible usability for things outside of containers. It's always the junior programmers that I run into that want to use templates for everything because it can do "x" or generate code "y". All of the senior programmers are yelling at them, "NO!". Compiler support for them has historically been spotty too making cross-platform code even more fun.

Edited by David Owens II on
owensd
True, but at least the cost actually brings something worthwhile to the table. I'll take the flexibility of ObjC over C++ every time.

That's fair. ObjC is closer to a dynamic language than C or C++, and all that this implies. (Well, almost all; you still have a fairly static type system.)

owensd
Compiler support for them has historically been spotty too making cross-platform code even more fun.

I'm not going to dispute the other things you said about templates, but this isn't an issue unless you're one of the unfortunates still using VC6. If your compiler can handle Boost, it can handle your templates.
Pseudonym73

owensd
Compiler support for them has historically been spotty too making cross-platform code even more fun.

I'm not going to dispute the other things you said about templates, but this isn't an issue unless you're one of the unfortunates still using VC6. If your compiler can handle Boost, it can handle your templates.


This was a problem as little as 6-8 months ago. I work on a Mac team, the offending code was from a Windows team. They were using the latest MSVC at the time. Good times.
Can you describe the problem in general terms?

I'm curious could you possibly have been doing which was more template-hacky than Boost.
Pseudonym73
Can you describe the problem in general terms?

I'm curious could you possibly have been doing which was more template-hacky than Boost.


It was using templates to generate code. One of the specific examples was around vararg template parameters and the lack of support in MSVC for it, so this developer used a workaround that was specific to MSVC. This, of course, didn't work in Clang.

Regardless, even the "standards compliant" version of the templates are completely insane to attempt to debug when things go wrong. While what you can do with templates is cool in one respect, I've seldom found their cognitive cost worth it for anything but the simplest of cases. This problem is compounded exponentially in large teams and with developers that don't really understand templates and try to use them for problems where there are simpler solutions.
There are a number of very serious bugs in the MSVC compiler with respect to the new C++ standard. The truth is, as long as Microsoft is involved, I suspect fully coding to the latest C++ spec is always going to be fraught with peril :(

For example, see this lovely gem that bit Jon recently:

https://connect.microsoft.com/Vis...definitions-inside-a-nested-block

Was reported over half a year ago, and they originally marked "resolved: won't fix" (I'm not kidding), and then finally someone fixed it but they didn't bother to put it in an update, so it won't be fixed in the main branch until 2015 comes out.

The more things change, the more they stay the same.

- Casey
As far as I understand fatal error C1506 is pretty much that compiler is crashing/asserting something. But this happens not only with MSVC, but also with GCC and Clang. I have seen crashes with gcc and clang as often as MSVC. Actually on OSX/iOS I have seen crashes more often for some specific code. Or even worse - incorrectly generated machine code (good luck debugging that). Of course reporting bugs back to clang maintainers doesn't fix problem immediately. I've done that, but that had not fixed my problem immediately (you still need to provide workaround). Because first fix is available only in clang trunk, then you wait for half a year or so for clang release. Then you wait for Apple to pick up this fix in their own private clang tree, and then you wait for them to release it in Xcode. This easy takes from 1y to 2y as minimum.

Not that I'm defending MSVC, I'm waiting on clang to finish Windows support, so I can fully use it instead of MSVC. But problems happen on all compilers. Yes, you could argue that update cycle for half a year is long, but look what you will get for gcc on Linux - some distributions use ancient gcc versions for stability/security purposes. And on OSX you are in similar situation as with MSVC - no control what version of compiler to use. Yes, it may look that clang supports C++1xy.. versions better. But as I was saying above, I have seen pretty bad crashes/bugs also with it.

Edited by Mārtiņš Možeiko on
First of, I'm sorry I'm a little late to the party... also, I'm sorry if some of my English is subpar... I'm not a native English speaker and sadly have less experience expressing myself in long sections of text than I would like.


I was first about to write “Why all the hate/distaste for OOP?”, but I think I already know where you all come from.

If you are talking about strictly OOP, then I can REALLY understand the hate, but that's not what C++ is about in my opinion. In C++, OOP it's just one tool in a large set of different tools that can be powerful if used “correctly” (just like templates… oh… my distaste for boost…). It can be very useful if applied correctly, but outmost horrible if misused, like most other things as well.

I’ll try to give you at least my view on OOP, and it’s for you to judge if you want to listen to what I say and what my merits are worth (I’ve only released one commercial game as an in-house programmer, which is Clodubuilt, where we were two programmers over the course of 3 years writing the game, the engine, editors and some other tools, while starting up and managing the company and trying out marketing… I also worked on design of the game, art, and other stuff as well).

I’m a little tried on the hate on OOP and I think it’s an overgeneralization. In my opinion, if you are wiring an engine or any code with high demand on performance you must have a deep knowledge of everything you are using, no matter what it is. But as long as you have that understanding, there is no problem. Object orientation can be useful, but you should never use it blindly without considering alternatives, just like with everything else, and make sure you know what is happening under the surface.

In our engine we use a lot of objects and hierarchies, but we also use a lot of C-style code and sections where we extend base behaviors with function pointers and void pointers and such. It all depends on where in the engine or game it is, how much we intend to build upon it, or how many people we expect to get in contact with it, and what knowledge we expect those people to have and so on.

Just as a disclaimer though, our code is FAR from perfect, just like with most projects developed under tight time constraints I would say, and we definitely have things we want to work on and make better. That being said though, for the most part, the largest decisions that we regret, have been related to third party libraries we’ve used, not how we chose to structure our code/engine. (we will most likely work to remove those libraries in the future… as soon as we can as far as I’m concerned)

We have been refactoring code, restructuring huge sections, and generally rebuilding and iterating a lot throughout the development. Now that we are more or less prepared to move on from the project, we will try to get some time to look over and restructure things some more to make sure we separate the engine, game and tool code as much as possible. Along with that we will most likely also break out some of our C style sections to become more object oriented, as it will help to make it cleaner and easier to work with in the long run for us. Most of those sections are not even part of any bottle neck either. So ease of use, extendibility and maintainability is much more important in those sections.

We have with our design managed to build an engine and game that is very data driven and flexible. I’m sure that most of it would be possible without object orientation, but it would likely be much less “safe”, and much harder to extend and continue to work on in future projects. (we will see how it goes, but we might try to keep the engine fully backward compatible to still be able to run Cloudbuilt even when the next game is done).

In order to be able to do large underlying changes without affecting other code and require too large rewrites, we need to be able to abstract many things that happen underneath. We must of course make sure to not add unreasonable overhead to the things we do, but we use a lot of object orientation to achieve this.

We have yet to port the engine to any console, so we will have to see if that changes my opinion if we get around doing that, but I don’t think it would become any issue. We know where our bottlenecks are, and it’s not due to any object oriented code.

There are a lot of problems with C++, I agree, but fundamentally, objects should not be a problem as long as you use it well. (Though ,there is a fundamental problem with the fact that there is no standard for compilers… making it impossible to handle object oriented code compiled in other compilers…. that is a fundamental flaw with C++ imo)
I’m sincerely looking forward to Jonathan Blow’s new language… but that is still far away on the horizon for now and a whole other topic….


PS: talking about compilers… I’ve been waiting for constexpr to get supported in visual studio for years… I hate to rely on macros too much, especially as the compiler hats it just as much… when writing this I looked it up and it seems like it finally is available… but it took to damn long >_<… I have yet to try it though. Anyone here that have been testing it out?

Edited by Gafgar (Anders Davallius) on