Some programmers actually hate OOP languages? WHAT?!

Started by
91 comments, last by Washu 9 years, 3 months ago

Ravyne, for returning multiple values from a function or method I generally use std::pair and similar. This isn't the most efficient though as it obviously has to be copied, or allocated in the function and freed outside of it which has always felt wrong to me...

The C++ standard allows the compiler to skip the copy constructor that should in theory be invoked when returning an object by value. Compilers have taken advantage of this for a decade, so in most situations, returning a large object from a function is completely free.

e.g. if you write:
struct Widget { int a,b,c,d; }
Widget Foo() { Widget temp = {1,2,3,4}; return temp; }
void Test() {
  Widget w = Foo();
}
The compiler can automatically transform it into:
struct Widget { int a,b,c,d; }
void Foo(Widget* result) { *result = Widget{1,2,3,4}; }
void Test() {
  Widget w;
  Foo(&w);
}

This could also be used as an illustration of how bad a language C++ is for being overly-complex though laugh.png Most programmers aren't aware of the subtle rules that dictate when their compiler will and won't make use of this optimization, so it's non-obvious whether a large return value is free or expensive...
Advertisement

This could also be used as an illustration of how bad a language C++ is for being overly-complex though :lol: Most programmers aren't aware of the subtle rules that dictate when their compiler will and won't make use of this optimization, so it's non-obvious whether a large return value is free or expensive...


Yeah, the NRVO was always kinda confusing. Last time I checked compilers were allowed to implement it but not required? Makes portable code hard to write.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

This could also be used as an illustration of how bad a language C++ is for being overly-complex though laugh.png Most programmers aren't aware of the subtle rules that dictate when their compiler will and won't make use of this optimization, so it's non-obvious whether a large return value is free or expensive...


Yeah, the NRVO was always kinda confusing. Last time I checked compilers were allowed to implement it but not required? Makes portable code hard to write.


In my experience it's better to just return a local stack variable by value and let the compiler utilize move semantics and RVO to eliminate the cost. Heck, it wouldn't surprise me if you combined std::tuple and std::tie (which is a brilliant function btw) to do multiple return values if the compiler can even figure that out and eliminate all the extra work.

Then, if your profiler tells you it is too slow (and ONLY then!) do you try to jump through hoops to make things faster.

Just to feed this tr.. topic, I recently had to do some reverse engineering on a game's codebase in C#, strongly OO. It was a real nightmare...

However, understanding a large C (well-written) codebase, even without documentation is a piece of cake.

Just to feed this tr.. topic, I recently had to do some reverse engineering on a game's codebase in C#, strongly OO. It was a real nightmare...

However, understanding a large C (well-written) codebase, even without documentation is a piece of cake.


Well-written code is easy to understand, regardless of the language or paradigms used.

(Well, except maybe C++ template meta-programming... that stuff gets fun fast! tongue.png )

One other thing that should be mentioned is that OOP has changed quite a bit over its existence. Inheritance for example is generally seen as something to avoid these days. Mutable state in objects is generally seen as something to avoid these days.

Why? Because programmers used them and found out that in many cases they suck. Some programmers said "let's make this better". Some programmers said "screw it, I'm going back to my cave" and haven't seen the practical improvements made in OOP technique over the decades. If all people know of OO is old style inheritance heavy, side-effect heavy code - they are completely right that it is bad.

Likewise, many of the other commenters are correct that C++ is a pretty terrible language to make OO code in. Java is a pretty terrible language to make pragmatic OO code in. Universities were horrible at teaching OO throughout the 90's and early 00's (and are still largely terrible). If all you see is horrible OO code, it's not a terribly improper leap to assume that it is terrible, or it makes it too hard to write not-terrible code.

Another thing to consider is personal experience. Like others have mentioned, OO is a tool and like any tool is good at some things and bad at others. If my experiences tell me that most problems are these sort (that OO happens to solve well) or that these sorts of things cause me pain (which OO prevents) then I'm going to think OO is awesome. Some people's experience simply tells them that the verbosity of most OO languages provides no benefit, or the object focused approach yields inferior solutions for the sort of problems they commonly encounter.

Something I still haven't got is the difference between OOP and simply using objects.

I get that Object-Oriented Programming is clearly intended to pay a lot more attention to objects and use them as the core concept of the software's architecture, but I find it hard to imagine any kind of even somewhat blurry line that demarcates proper OOP and something like using a lot of structs in C, which appears to be very much regarded as definitely not a language that supports real OOP.

It's something that interests me, because I too sometimes wonder about the necessity and practicality of all this supposed "best practice" you often feel you "should" implement when coding in C++ even though sometimes you feel it's a bit tedious and verbose. Maybe it's the fear that later on I'll be glad I made X or Y into its own class (with its own .h and .cpp files... grrr) when it grows in complexity that makes me just along with it most of the time.

Also that I know games were developed quite differently in the past, and while I don't particularly have the interest to actually start learning how to code for obsolete platforms, I do have a certain curiosity and desire inside to know more about how they might have approached things at least from an architectural point of view. I guess most games 20+ years ago would have been developed in some form of assembly, but even then the actual thought process that went on in order to organize and keep track of things without the kind of OOP I know from C++ is both intriguing and confusing to me.

Then the likes of Populous on the Amiga was coded in C I know, which brings things much closer to what I actually know from experience, and techniques that could be actually used in C++, in theory at least.

How ARE games developed procedurally compared to OOP? Are there any good articles/examples explaining the differences in approach? I assume the lack of access modifiers is a huge difference...

Somehow I almost feel like trying to make a game procedurally would be a breath of fresh air and feel freeing after so much OOP-style enforced organization, but then I'm not really sure what it's like...

...actually, might it be sorta close to the style of programming you might see in a Ludum Dare game? I've often quite liked the very "efficient" style of coding it forces them to adopt; no annoying getters and setters that you "should" make for every encapsulated variable that needs to be externally read/modified, no worrying about thinking ahead making sure it can be easily modified later or reused, and the functionality gets up and running much sooner.

Would be a nightmare to rush things like they do in LD for a large project, I'm sure, but maybe some experience with procedural programming would help me find a happier medium sometimes.


Even if you're going to stick with a language like C++, it's immensely beneficial to learn many languages of different styles, with their own paradigms and idioms.

Just to be clear because taken out of context my previous posts could read as my being an OOP-with-C++ cheerleader, I'm quoting this for emphasis. In my own programs I freely mix OOP, Procedural, Functional, and other influences. Its important for people to remember that C++ is *not* an OOP language in the same sense that the first several version of C# were, and Java almost entirely is even today. C++ has support for multiple paradigms and their mixing of techniques and design influences are visible in the C++ standard libraries even from early days. I have difficulty thinking of even one programming language who's practice is not made better by adapting techniques outside its primary paradigm/s. Sometimes a language that does one paradigm incredibly well is a very powerful tool to have, but it just isn't suitable to every programming problem. As such, my yardstick for programming languages tends to measure how much easily the language lets me solve problems in the way I see fit without its agenda getting in my way, and thus my preference for languages that give me more discretion as a programmer (note that a language that puts some principled restriction/burden on the programmer is acceptable if the benefit is worthwhile. I think Rust is an interesting language, though it remains to be seen how practical it is for the kind of low-level programming in games and such. I've just begun experimenting with it myself.)

throw table_exception("(? ???)? ? ???");

How ARE games developed procedurally compared to OOP? Are there any good articles/examples explaining the differences in approach? I assume the lack of access modifiers is a huge difference...
Somehow I almost feel like trying to make a game procedurally would be a breath of fresh air and feel freeing after so much OOP-style enforced organization, but then I'm not really sure what it's like...

...actually, might it be sorta close to the style of programming you might see in a Ludum Dare game? I've often quite liked the very "efficient" style of coding it forces them to adopt; no annoying getters and setters that you "should" make for every encapsulated variable that needs to be externally read/modified, no worrying about thinking ahead making sure it can be easily modified later or reused, and the functionality gets up and running much sooner.
Would be a nightmare to rush things like they do in LD for a large project, I'm sure, but maybe some experience with procedural programming would help me find a happier medium sometimes.


"OOP" - as reflected by languages like Java and C# is an "everything is an object, and probably inherits from an 'object' base class" concept. This is generally considered an abuse of the principles these days.

In my personal experience, modern programming has kind of settled onto two abstractions - the object, and the function. Both of these exist in all languages, though what you can do with each varies.

Objects store data, and expose some kind of interface that determines what operations are legal on that data. In some cases, they will involve some form of virtual dispatch, messaging system, or templating system to allow the operations to be customized without involving large if chains or switch statements. Note that basic types like "int" and "bool" are objects in this example, because they define a set of data (a certain number of bits) and operations that can be done on that data (addition, subtraction, negation, etc). You could say that their encapsulation makes sure that you can never have an invalid integer or bool, should you follow the language rules (floats can stretch this definition with the severan NaN representations).

Functions are operations performed on data. These can be classified as "pure" - not modifying data, but returning a result - and "non-pure" - which modify the data given to them. Pure functions are ideal for threading, but may consume more memory and cycles as they may have to make copies of data (smart compilers, especially when dealing with a 'functional' language, can almost eliminate these issues).

So in the end, an "ideally coded" video game will look a lot like any other "ideally coded" piece of software. It will use objects where invariants and encapsulation are important. It will use functions to group together repeated operations, with "pure" functions being preferred where immutability is important or required, and "impure" functions where "pure" functions are impractical. And then it will take advantage of special language features to reduce the amount of coding required to produce the desired result and minimize errors. (Example: Templates)

Where you will frequently run into "bad" code is where someone has fixated on a particular tool and used it everywhere, even where it is not suited or has a distinct disadvantage. Like a house builder who uses a hammer for everything and you wonder why there are no straight edges, only rough scalloped edges where he used his hammer to split the wood apart.


Something I still haven't got is the difference between OOP and simply using objects.

It's blurry, since different people consider OOP different things. Generally though, Object Oriented Programming isn't programming, it is design.

When you go to break your problem into managable chunks, do you think "what parts make this up?" (OO), "what steps do I need to take?" (procedural), or "what operations make this up?" (functional).

This topic is closed to new replies.

Advertisement