Some programmers actually hate OOP languages? WHAT?!

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

...And after the master programmer, comes the lazy programmer ( me smile.png ) who just thinks about the implementation, finds a (decent) solution (mentally, of course), then starts to think that it's too much effort to write all the code for it - in any programming language.

Hm... Wouldn't that coffe maker come with a pre-built library with all the required functions already implemented that I could use, though?

Advertisement




edit: And I think it's a misconception that data-oriented programming = focus on cache performance and avoiding branching. Those are things that can come out of taking a data-oriented approach, but I don't think you need to go all the way to using bitmasks instead of conditional branching for your code to be "data-oriented". Data orientation to me just implies that your code is built around how your data is laid out and your data is laid out according to what you actually need to accomplish instead of trying to model the "real world" with abstractions in code.

I think you are confusing data driven design and data oriented design smile.png

No, not really. The two approaches mean very different (and orthogonal) things. "Data-driven" means that behaviour is driven by what data you have - in other words, that how your program behaves is determined at runtime depending on what specific data you have instead of being hardcoded. "Data-oriented" means that your program itself is structured around what form your data has and what you need to do with the data, as opposed to what the "real world problem" is. A program can be data-driven and data-oriented, or it can be just data-driven, or it can be just data-oriented. Apples and oranges, respectively, and I'm talking about oranges not apples. smile.png
Data oriented is all about performance (cache misses being a part of it), it's one of the first things it says on one of the pages of the link you posted (quoted below) smile.png.
I didn't say it wasn't about performance, I said it wasn't entirely about cache performance and bit twiddling and that it has advantages that go beyond just performance. ;)
I'd say a better definition than the one you appear to be using is the one from the book I linked, on the very first page past the introduction:
In essence, data-oriented design is the practice of designing software by developing transforms for well formed data where well formed is guided by the target hardware and the transforms that will operate on it.
If the ultimate result of an application is data, and all input can be represented by data, and it is recognised that all data transforms are not performed in a vacuum, then a software development methodology can be founded on these principles, the principles of understanding the data, and how to transform it given some knowledge of how a machine will do what it needs to do with data of this quantity, frequency, and it's statistical qualities.


in other words, many of the things people call "typical C++ bullshit" or "typical OOP bullshit" is actually "typical Java bullshit" that's been drug into C++ by recent grads or Java refuges who don't know how to write idiomatic C++ and so write idiomatic Java in C++ instead.
Now that might be just me but it sounds awfully like a "dey took our jibs!" reasoning there. Must be those filthy Java programmers, et cetera. Also you seem to assume colleges teach "idiomatic Java", I'm going to tell you they don't. They teach generic OO concepts, often badly, no matter the language they end up actually using.

I'd say that the main reason few people write "idiomatic" C++ is because C++ is an impenetrable mess rather than other languages having obviously spoiled your programmers. Moreover, "idiomatic C++" that takes advantage of all the features of the language guarantees the codebase will become an impenetrable mess. There is no such thing as "idiomatic C++", you can get as idiomatic as the subset of features your project limits itself to allows you to, doing anything else ends up in madness and despair.

Also, turns out that many of your so called "idioms" of C++ are actually beneficial for Java and for any language. Avoid heap allocations, avoid virtual function calls*, branching has a cost, pointer indirection has a cost, and so on. I agree with exceptions there, they're just annoying, then again I'd say exceptions are a big thing on "enterprisey" software, regardless of the language.

Now if these people don't even know generic beneficial idioms that would help them no matter the language, then I don't see why you would put that on Java's shoulders.

*Although this is specific to OO languages. Also there are Java-specific considerations here, JIT can inline the virtual call if it only sees one or two concrete implementations.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Additionally, exceptions and manual resource management mostly go together like oil and water -- you can't just put the two in the same container and expect it to work out, they only combine well when you take great care in the combining.


Personally, I use exceptions in c++ only for throwing errors from failed constructors. As ctors cannot return a value for obvious reasons this is the common sense way to raise an error. Anywhere else return codes are simpler and easier to work with...


Now that might be just me but it sounds awfully like a "dey took our jibs!" reasoning there. Must be those filthy Java programmers, et cetera. Also you seem to assume colleges teach "idiomatic Java", I'm going to tell you they don't. They teach generic OO concepts, often badly, no matter the language they end up actually using.

I probably should have been more careful in how I chose my words. Java's never taken my jerb, but I do think its a poor language and yes I do have a bit of a soapbox about it. When I say "idiomatic Java" or "idiomatic C++", I don't necessarily mean the things that really are best practices or what's taught in schools, I mean the things that the culture around that language broadly accepts as sacrosanct and to be revered and striven towards at all levels, not just experts. In java, the enterprise is largely what drives the culture -- Java, the language itself, was literally designed to make Java programmers interchangeable because that's attractive to big business. That's the reason Java gives so much less discretion to the programmer than C++ does, and disallows such anti-social behaviors as operator overloading and the heresy of free-standing functions. Business would prefer if all their programmers wrote the same kind of code, and Java does what it can to enforce that at a language level. Because programmers who have been weened on Java have never been afforded such freedoms, it remains difficult for them to utilize new-found freedoms in a language that affords them the privilege, and so the opportunity is ignored or distrusted by these programmers even when they are objectively a preferable solution.

Some schools, many no doubt, probably don't teach strictly from best-practices. Certainly I was exposed to ideas in my C++ courses that are not good practices for software at scale, usually as a contrived means of demonstrating one language concept within a bubble -- I recall a particular assignment that required us to use exceptions as a flow-control mechanism. But the choice of language does have an impact. In Java, you cannot teach a student that free-standing functions are preferable because the language doesn't truly allow them -- sure, you have static methods, but that starts to fall apart when the static member is equally related to two or more types: where do you put it then? In Java (and in C#) you see people creating new classes whose only purpose is to be a bucket for static methods. How silly is it that one has to pay penance to the type system to achieve such a simple request as a free-standing function? How tragic is it that for most college graduates, this is the solution that becomes their muscle-memory and is something they must unlearn to be an effective C++ programmer. That design decision has nothing to do with good OOP practice, and everything to do with the particular orthodox worldview that Java's proprietors set forth in their market analysis. To be fair, Java serves that market expertly -- it faces essentially no competition from C++ at all in that space, it competes mostly with C# there.

I think the thrust of what I wanted to get across was that to become a truly enlightened OOP practitioner, you have to be willing to be a heretic if your background is Java. It requires you to actively reject certain notions that are enshrined in the Java language. For its part, C++ is not perfect and I'm not saying that teaching C++ in colleges is the cure; I believe C++ to be better in many ways (owing mostly to its lack of far-reaching orthodoxy and its disregard of marketing strategy), but it also presents it own challenges, owing mostly to its C legacy and its incrementally accrued complexity. Its really not that C++ is the ideal expression of OOP, its not, but its the least-restrictive option we have among these three langauges (C++, Java, C#) that are widely used in industry and a broadly-marketable skill. Certainly I am also biased as C++ is the only one among them that lets me express in greatest detail how I want the machine to carry out its work (down to the level of how and when to allocate and reclaim memory, or how to organize and pack data efficiently for machine access) while also giving me the expressiveness to express solutions at a high level in the manner I choose.


Personally, I use exceptions in c++ only for throwing errors from failed constructors. As ctors cannot return a value for obvious reasons this is the common sense way to raise an error. Anywhere else return codes are simpler and easier to work with...

Exceptions, at least as popularly used, are not a laudable feature of C++ or any other language. They're particularly troublesome in C++ though because it lacks a garbage collector (technically, the C++ standard allows for one, but no one offers one I'm aware of). That's why C++ programmers have to deal with this whole business of functions being exception-unsafe, or being exception safe with the weak exception guarantee, or being exception safe with the strong exception guarantee. Return codes are viable when the issue can be dealt with immediately in the calling scope, but they start to break down otherwise -- you end up seeing solutions where the error code is simply stored in some global and a panic() function is called when the error needs to escape more than a couple stack-frames. And every level the "exception" must escape has to have its intent polluted by error handling code. That's actually the reason for exceptions to exist in the first place -- to allow for intermittent errors to be handled without manually accounting for them in the flow-control of your program. If it weren't for the difficulties that stem from the combination of manual resource management and exceptions in C++, exceptions are a fairly good solution for this problem(exceptions work much better in garbage-collected languages like Java or C#), but still always work best when used sparingly.

Also, if we are limiting ourselves to return-codes, how then do functions return other values? Any function that can fail must then use an out-parameter to return its result, which is not convenient and leads to code that can be difficult to follow. In other languages, functions can return multiple values, which alleviates some of this problem, but that's something C++ lacks a good solution for -- it doesn't have multiple return values and lacks a "value bag" type object (such as a tuple) that is both computationally and semantically light-weight (std::tuple is nice for what it is, but isn't so light you'd want to reach for it as the solution to all your essential error-handling). std::option<T> will be sufficiently lightweight I think (when its officially adopted), but its capacity to communicate an error is limited to expressing only whether there was an error or not, it can't on its own express what the nature of the error was.

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


In Java (and in C#) you see people creating new classes whose only purpose is to be a bucket for static methods. How silly is it that one has to pay penance to the type system to achieve such a simple request as a free-standing function?

Yeah, I do that all the time in C#.

I do wish they would add support for free functions, but in practice* it's no different from adding a free function to a namespace in C++, and namespaces are a Good Thing IMO.

* as long as you don't do anything stupid like depend on static state, but again you can do the exact same thing with functions and global state in C++.

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
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...

So I have been checking out F# and Rust and I have to say, looking at the syntax and semantics and seeing how it's totally different from OOP is really scary, but at the same time very exciting.

Rust and F# really opened my eyes to a new way of programming I never thought existed. I'm really excited to get my hands dirty with these two new languages.

I've also heard that Jonathan Blow is working on a functional programming language just for game developers. Will see how that turns out.

Also this wiki about types programming languages was a good read.

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.

e.g. My personal C++ style involves OOP's focus on encapsulation and invariant-enforcement, Functional's focus on immutable state, Procedural's ability to KISS with transparent data structures and Flow/DOD's focus on transform graphs. :lol:
You'll find that your idea of good code will drastically change with new experiences :D
I'm in much the same camp as Hodgman; the OOP focus tends to be towards higher systems, the functional influence I've picked up over the years informs my way of processing data without mutating state (either at all or too much, system dependent; either way I'm a 'fan' of chained processing of things and passing stuff about if possible) and the DOD aspects (which, tbh, I was doing before it got a name) make me think about how I'm going to lay out that data so that my functional processing style can work nicely with the underlying hardware.

There is no One True Way; there is only the data and how you intend to process it.

Beyond that all we have are words to try and explain how we've put things together.

This topic is closed to new replies.

Advertisement