Hacker News new | ask | show | jobs
by mtzet 1911 days ago
These discussions tend to boil down to OOP vs FP. That's a false dichotomy. The alternative to OOP is not FP, it's pre-OOP imperative programming with various techniques a la carte.

Should data and functions be together? That's a choice you can make on a case-by-case basis. It makes total sense that a HashMap has an insert() method. On the other hand, maybe your Player object is just some data which is interpreted by a PhysicsSystem and MovementSystem etc. Maybe it's clearer that all the physics calculations are in a common PhysicsSystem rather than being spread out into several implementing classes.

Should you use a switch-statement or a polymorphic interface? If you're traversing a graph with a fixed set of nodes, or you need to change all systems when new nodes arrives, the (exhaustive) switch may be preferable. I'd certainly prefer it to the visitor pattern.

If you can extract a calculation into a pure function, then that's great. If you're doing something inherently stateful, FP techniques are probably not too great. Maybe you can afford a high-level functional interface, but keep the implementation stateful.

The problem with OOP, FP, etc. is not that the techniqures are BAD, it's that all techniques are trade-offs. We're very good at talking about the advantages of some technique, but seem always forget the costs associated with it.

8 comments

My problem with object oriented programming it's not the object part, it's the oriented part. In object oriented programming, there is, usually, no trade-off. It's objects all the way down.

The problem is that not many things actually need to be an object. But when something needs to be one, there is no distinction. No way to tell whether somebody made a thing an object, because it makes sense or just because that's the only way he could make it. So you have all those User/DateFormatter/Encoding objects for no reason, but language limitation. And then, on top of that, when you want an actual object, something that does its thing, have internal state and an interface to communicate (not a method call), you are on your own.

Not necessarily: C#, for example, has a lot of FP like moments. Its not particularly relevant how are those internally implemented.
Not op, but I think you missed his / her point.

Let's take static void main as example. It's a series of operation called at the beginning (at least during my era), does not need to be in a class. The very reason we put it on class (let's say) Start, feels like language limitation.

The same with class Math, such as Math.floor and Math.ceil. Is Math a class or is it more suitable as a namespace? Since no object instantiated from Math is required (and maybe the same with static class).

However I don't think OOP is bad or limited language, beside the static void main part.

> The same with class Math, such as Math.floor and Math.ceil.

I still want to group them somehow and this "somehow" better have name "Math" so other people would see what it is.

Why are people so attached to name "class". Call it "namespace with state capabilities" if you're annoyed by "class" so much. Or just use namespaces like in C#. You still want namespaces, that's the point.

And speaking about your example. More often than not, we've got quite a bit of functionality attached to program startup and I'd rather have it focused in one single module "Start"/"Application"/"Runner" whatever you want to call it but I want it to be _focused_ and easily searchable, not floating in a see of function.

And by the way, same argument can be made about functions, why do I have to create "main()" at all, why not just start writing instructions like in bash script or python?

> Why are people so attached to name "class". Call it "namespace with state capabilities" if you're annoyed by "class" so much.

The central, first-class “namespace with state capabilities” in OOP is an object. A class is a namespace with state capabilities that may (or may not, because pure static classes are a thing) be an object factory, may or may not be an object or first class entity, and, probably, if the language has static types, is also a type.

And all of that is also true of objects, except the last, and objects are always first class in OOP. So, aside from static typing, classes are superfluous, unless they are just a name for objects with certain common feature.

There are now Top level statements in C# 9.

- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tut...

> Top-level statements enable you to avoid the extra ceremony required by placing your program's entry point in a static method in a class.

Yes. Records in Java are another example. But that only fuels my suspicion, that oriented part is the problem.
I love this take. Programming techniques are that, tools on our belt. One should neither fall in love with a particular one, nor try to use it exclusively. Either it fits, meaning it provides advantages that outweigh the added complexity, or it doesn't.
Python balances this well. You are never forced into an OO hierarchy for your own code.
On the other hand Python often nudges you towards OOP, because its FP features are a bit lacking.
An entire generation of programmers were brought up on languages which took an orthodox view on this (Java, C#, though they're both better at it now).

Add to this all the books and seminars or OOP, patterns, etc. and in some circles it's impossible not to code in the strict "break everything apart" OOP style

The meaningful alternative to OOP is modular, object-based programming based on composition instead of inheritance. That encompasses both "pre-OOP" and "post-OOP", mainly functional-based idioms. Simple imperative programming does not really scale to larger software systems, modularity and compositional thinking are essential.
Your statement seems to imply that imperative programming does not have modularity. In my experience, I have worked on programs written before OOP was in vogue, in imperative languages, that I consider to have had good modular design. These programs had millions of lines of code and I felt they were easy to understand and modify.

What do you mean when you say that imperative programs lacked modularity?

Modularity in imperative programming is ad hoc. It's not part of the paradigm itself like in modern functional programming, or object-based programming with interfaces and composition.
> These discussions tend to boil down to OOP vs FP. That's a false dichotomy. The alternative to OOP is not FP, it's pre-OOP imperative.

Thank you for raising this oft ignored fact. I remember graduating from C to C++ in order to hack on SGI’s OpenGL in 1991. Possibly graphics and scene-graphs are a sweet spot for OOP, but I found the approach very elegant and quite effective.

OOP, as a paradigm (it is not a “tool”), is one of the handful of viable approaches for organizing and writing code. Given that these are paradigms, it is natural that there are those who have a natural mental affinity for one and abhorrence for another. In my view, the only merit in these comparative critiques is when contextualized within a specific, e.g. UI development, problem space.

(Also, Joe (RIP) is indeed wrong. OOP doesn’t suck, it bloows. /g)

A paricular point people don't get is that Java joined functional programming instead of beating it.

The Hotspot compiler was based on a research runtime for a functional language. Type inference is basically the same as ML family languages. With heavy use of Lambdas and higher-order functions some of my Java looks like ML. If i want to have functions like

   maybe(x, f1, f2, ...)
that works (emphasis) like the maybe monad my codegen writes the boilerplate out to arity 30. (Funny the codegen lets you write Java in a Java DSL that looks like typed S-expressions.)
This frustrates me though.

My POV ("Writing functional stuff in Java is a headache") gets lost between the much larger camps of "Functional bad, Java good" and "Java is functional and therefore good". Or worse "Java is better because it's both OO and FP".

I want to type inference to work as well as ML. I don't think it ever will.

I want to be free of nulls. I don't think I ever will be.

I want the language to just let me implement `interface Monad<A>` and not need to generate code to arity 30.

Wasn't HotSpot based on tech developed for Smalltalk, Strongtalk and Self? None of which are FP languages.
>The alternative to OOP is not FP, it's pre-OOP imperative programming with various techniques a la carte.

The alternative to an object is an abstract data type; both are data abstraction techniques that hides the data under a set of operations. The main difference is that an object includes an interface while an ADT does not. Nothing prevent an object interface to be functional nor an ADT set of operations to be procedural.

The eternal conflict between the "single consistent idea" and the "Swiss army knife" approach to tools.