16

Functional programming vs object oriented programming.

I don't believe one can replace the other I just want to know some other people's opinions.

Comments
  • 2
  • 7
    functional is better, object oriented is easier they both produce instructions for cpu
  • 4
    What I find baffling: chess is clearly all about computation of a result, namely of the best move to make. Unlike behaviour-oriented computing, this seems like a match for FP, especially with multicores.

    Yet still, there are no top league FP engines at all. What you find is some POC toy engines, but the actual implementation seems to be so incredibly awkward that even actual FP programmers (and who else would make a chess engine with FP?) quickly give up.
  • 12
    Functional programming makes it harder to make mistakes. But it also increases maintenance costs, and if you're going for pure functions, you lose a ton of performance due to a lot of memory copying.

    Do neither. Do what's best for the situation - which is the situation where you have to write it now, maintain it 1 year later maybe, or someone else (possibly more stupid). If something is done better with pure functions - do it like that. If something can be described well and easily with objects - use them.

    They are tools, like screwdrivers or hammers. You don't use exclusively small or big nails just because you need to use a single, small or big hammer.
  • 3
    It all depends on what you make. I don't see a game like factorio being created in a not OOP way.

    At the same time I don't see the classic snake being created in OOP.
  • 7
    This FP trend has at least the merit to provide us with good designs in order to avoid many of bad practices and misconceptions of OOP, starting from big inheritance trees and too much states in different places.
    For the rest, is a tool.

    I like it mostly because it makes code easily testable and its behaviour strictly predictable, but modeling everithing the FP can be a nightmare sometimes.

    (with the juniors I supervise I'm already nazi enough with FP... poor guys, graduated with years of OOP presented as the ultimate holy grail. It's hard to show approaches other than the bullshit of Animals>Mammals>Feline>Cat )
  • 0
    I thought FP === multithreading, solving the concurrency and data sharing issues by making everything immutable?
  • 1
    @AndSoWeCode it actually decreases maintainance costs as the code is easier to reason about because it is generally shorter and free of side effects. You don't lose performance too much, the compiler is able to do a ton of optimization. Memory copying is not an issue.

    If you need the full controll and have something like a microprocessor, then an procedural language is better suited. But for large applications you don't gain any performance from non-functional code. There might be certain hotspots you want to manualy optimize, but you wouldn't do that with OOP
  • 1
    Use them together. Nothing wrong with having pure functions operate on complex data structures. Within the same app, some problems are better solved leaning on OO patterns and others on functional patterns. Hell, persistence is a side effect and most things need databases. Build config, CI/CD, ETL, and IAC are often varying degrees of declarative programming. Logging, transactions, validation, and dependency injection are often well-served by aspect-oriented programming. This battle seems somewhat moot to me because we're kidding ourselves if we think we're not using them all.
  • 2
    @host127001 for my case, working with a huge tree structure that was roughly 40GB in size, all in memory. Trust me, if I did pure functions here, I'd be fuuuuuuuuucked.

    As for maintenance - with OOP you can just change a class inner workings without changing the header of every single function that operates with it. That's why I mentioned lower maintenance.
  • 1
    @AndSoWeCode functional languages share memory a lot. I mean there can be cases where mutable data is notably faster, but these make up a very low percentage.

    With FP you can change the inner workings of a function, I don't see how OOP helps here
  • 2
    @AndSoWeCode the problem with OOP is: who is really responsible for an object's state? Either nobody, in which case you end up with a confusing web and the banana-gorilla-jungle problem.

    Or each object is responsible for the state of its direct children only. But if A needs to talk with B, that has to go up to a common ancestor and down again, which nobody does because it's too much work when requirements change. People just shortcut and live with the confusing web.

    But even IF they really keep such an object tree AND maintain it, the result is all those nebulous pseudo-entities (manager, driver, handler, controller, factory in every combination and permutation) just to artificially create the common ancestor nodes. These things don't have any relation to the actual problem domain and are also confusing.

    Dispersing and hiding state doesn't solve the problem. That's what FP tries to address via the "no state" approach. No state, no responsibility issues.
  • 0
    @Fast-Nop what's wrong with more parts of the code having the power to modify state? It doesn't mean that it Will be modified everywhere. Why limit power and performance? If you get there, simply isolate modules, not every single function scope.
  • 0
    @host127001 in OOP you deal with containers of information and functionality. A method can access its object members without having to declare that in its header, which is not true of FP. As for shared memory - that's exactly what FP is trying to avoid.
  • 1
    @AndSoWeCode it's basically the same thing that is wrong with globals. Encapsulating access creates the illusion something has changed, but that's not the case because the scattered responsibility is still there. That's why OOP doesn't solve the state problem.
  • 2
    @Fast-Nop debugging is easy. Modifying existing code is hard. As I said before, carrying huge loads of data around is bad for performance, and makes it difficult to write code.

    That's why I'm strongly against following strictly a single paradigm or design pattern.
  • 1
    @AndSoWeCode I really don't understand what you mean with headers. In FP and OOP you expose some Api to other Modules and Classes and the internals are not exposed.
    And for memory sharing: it's not what FP wants to avoid, FP makes YOU not have to deal with memory. The compiled binary uses as much mutable state as it pleases but YOU don't have to think about mutable state.
  • 0
    @AndSoWeCode carrying data around is bad practice independently from FP.
    You keep data in one place (because FP or not, in real wolrd we need states) and inject transformations via functions/messages/whatever from the outside. Then, eventually, if you really have to, you can broadcast the mutation to whoever may care, but that's it.

    Normally there's no data to carry around, it's only a complication, it can break, it wastes memory and cycles.
    You don't inject data into functions, you inject functions into your source of truth.
  • 1
    @host127001 the function declaration:

    foo(param1, param2, param3, param4)

    and then:

    oh fuck, in the chain foo->bar->baz I have to carry around another variable. Go ahead and modify everything.

    or

    Oh fuck, I need to write another function that needs the same data, and I have to write a long function header for this.

    or

    Oh fuck, I have to call this function again. Let me gather all the variables i need for this.

    As opposed to OOP:

    foo()

    Bam! Most of what you need is in the object. And in the function body you can use whatever member you want, without adding it to the function calls and function definition. And it's not like global variables because the scope is the object only.

    There are benefits to both sides. But when you've chosen one side, and it's getting ridiculous at some point - don't be stubborn and just write code that's easy to write, read and understand, regardless of whether you use several patterns and paradigms.
  • 0
    @thatsnotnice I'm really curious how this would look.

    Like I said before, imagine a tree of a few million nodes. Each node is composed of large arrays of data structures that are composed of several values. Like I said, around 40GB in RAM for one instance.

    The code has to apply several millions of changes to the values in the arrays in the nodes, and each change should be propagated through the tree according to rules that depend on the shape of that tree (how many siblings for the node, how many descendants, what are the aggregate values on the leafs of the descendants, etc).

    With OOP it's easy: One single structure, each node is an object, that exposes a method that accepts the definition of a transformation, and enacts it, by propagating multiple changes to other nodes (like a recursive function, except it's not the same function because it's on a different object).

    The entire code responsible for just this stuff is around 100-200 lines.
  • 0
    @thatsnotnice ... in that algorithm, no data is copied in memory. Just references to data. The memory footprint doesn't go up much. Methods are small (2-3 lines of code), that basically measure the relevant tree characteristics (ex. nr. of descendants), or ~10 lines of code for the function that propagates the changes. It's really simple to understand and debug.

    Right now it's in Python, which is very bad because of the GIL, I can't make this processing in parallel unless I clone that huge ass tree for every process. But I've done some scribbles, and a simplified prototype (no code for creating the tree or writing the results) works well in a true multi-threaded, parallelized environment, with absolutely no issues or difficulties. No race conditions, it's easy to see what is modified and where.

    Beat that with FP. I'm really open to ideas. If it's something promising, I'll play around with it after I get back from my vacation.
  • 2
    @AndSoWeCode you have literally the same problems in OOP. In foo.bar() the new data does not magically appear, you have to somehow get it into the class. And if you don't pass them in OOP they have to be fields. I hope you are none of those that force parameters into fields, just to not pass them as a parameter, because that is a hell to maintain.

    "fuck, I need a function with the same data" if that data is 4 random parameters then you fucked up. FP does have structural data types. Interface design does not become harder in FP. The reason I like FP is because of better maintainability and simpler code.

    Yeah, use the right paradigm for the Job. And imo imperative/procedural code (not OOP) is best for when you need the absolute control and performance.
    If you have a bigger application and need fast to write, easy to maintain code, then a declarative approach (like FP) is best suited.
    I really don't see a reason in production code for OOP, but it is the best paradigm for learning.
  • 0
    @host127001 "the new data does not magically appear, you have to somehow get it into the class" - yes. It's 2 scalars - the index in the array, and the modification value. But I don't pass in the whole node, or tree, which would be required from a functional paradigm, from pure functions, without a side effect.

    Otherwise the only difference is that in OOP it's methods associated with an object, that has data in that object, and in FP you have to pass in the reference to the object to a global function. The function has pretty much the same body.

    What am I getting wrong?
  • 0
    @AndSoWeCode but that is exactly what I said. The interface in OOP is not simpler than in FP. I need to pass the exact same amount of parameters.

    foo.insertAt(2, "bar")
    insertAt foo 2 "bar"

    Requires the same parameters and same amount of changes when you alter the interface
  • 0
    @host127001 except in this case the functions have global scope. Other than that they're identical. Oh and in some languages you lose some features when doing that, and makes the syntax clunkier.
    If it's already expressing things like that, why not make it proper OOP already? You won't lose anything with that.
    I don't think that's what functional programming is.
  • 2
    @host127001 one reason for OOP in production is when you actually have objects. I don't mean the usual OOP shoehorning, but for real.

    That's mostly GUI programming and simulations (games included). That's also where OOP came from.

    FP is not really suited here because what you want is all about side effects and behaviour, and procedural GUI programming is a hell of its own.
  • 1
    @Fast-Nop for gui you can do quite well with FP (Elm, React+Redux, ...). For games you usually don't do FP, that's true. But you also often don't do OOP.
  • 0
    @host127001 I don't mean GUI programming as in "put in tons of OOP layers so that you finally can put an FP/declarative layer on top of it and claim FP programming".

    I mean GUI programming as in what the native applications do. With window handling, event messages and all that. And without browser.
  • 0
    @Fast-Nop if you go down to window handling you have procedural code, as the interface to your OS is usually written in C. From there you can take any paradigm you want. And functional GUI handling does not "put in tons of OOP", what do you even mean with that?
  • 0
    @host127001 of course it throws in tons of OOP. Having an OOP browser just to be able to use a declarative framework is exactly that.

    And no, GUI applications themselves are not written procedurally because that totally sucks, which is why OOP quickly took over for that one. Back at the time, job ads frequently read "OOP/GUI programming", so close was the connotation.
  • 0
    @Fast-Nop what is an OOP browser? Where does Redux put in OOP?

    Of course that would suck. And many people use OOP for this. But you can do it in FP too and be fine. There is nothing intrinsic OOP about GUI.
  • 0
    @host127001 an OOP browser is a browser that is implemented using OOP technology. So, pretty much all of them. React is just irrelevant as any other web framework at that point.

    So, if GUI programming can be done in FP, show me an example. No, browser frameworks don't count because they need the browser, see point 1. That example would mean you can use FP GUI only if you put all the nasty stuff that FP can't do into another layer and stop thinking about it.
  • 0
    @Fast-Nop why does GUI programming in a browser not count? That makes absolutely no sense. Why is native GUI programming more important than web GUI?

    What about React native?
  • 1
    what you want in GUI programming, like everywhere else, is decoupling components.
    an old school pub/sub pattern, some reactive coding and that's it.
    you can write the hell you want with events and aspects without even declare a single class. state typically limited to funcion scope, or, eventually to an external store as source of truth (redux-style, yeah, perfectly suitable for backends too when you have tons of data and DTO-like objects jumping here and there)

    i write this way, i like it, i find it easier to reason, more testable and i can happily leave it uncommented without feeling guilty.
    we know that under this declarative and funcional hood there is still old school procedural implementation. i mean, i know that behind a map() there's a bunch of for loops, but unless i have to deal with single-cpu-cycle-level-optimisation, i simply prefer to work at higher declarative level.
    i have code in prod moving kind of big heterogeneous environments, nobody complains for now :)
  • 0
    @host127001 you're trying hard to ignore layers. No dice here. Your FP GUI programming needs a browser or a comparable framework. Software like Notepad++ simply doesn't.

    1) That adds more bloat.
    2) It is slower. Show me one text editor that even can come close to compete with Notepad++ when done with FP and tons of underlying bloat.
    3) It has more vulnerabilities because it has more bloat. What's more, the underlying additional bloat is implemented in OOP, which FP devs say is less secure.
    4) I could as well claim that GUI programming in Brainfuck is nice and easy if I defer all the heavy lifting away from the Brainfuck line of code.
  • 0
    @Fast-Nop Why would FP need a browser? Web development needs a browser, it doesn't matter what paradigm you use. And you use frameworks for the same reason in OOP as you use them in FP.

    1) I argue that FP has less bloat
    2) There are text editors written in functional languages and they're not slower
    3) Who says OOP is less secure? Why would it need more bload? Why would that bloat be in OOP?
    4) what? What heavy lifting?
  • 0
    @host127001 ok, then I require proof. Show me the FP GUI application that doesn't need a browser or a heavy framework. Show me the graphic (!) text editor that is done with FP and can compete with Notepad++. Browser apps don't count.

    1) no, it has more because it needs a whole layer more. Browser or React framework. It's not about what you code, it's about the required stack.
    2) see above, I call proof.
    3) FP devs say so. Obviously, because FP is about avoiding state in order to reduce bugs. Why the bloat would be in OOP, see postings above. I have explained that several times now, please take the time to actually READ.
    4) the actual GUI operation, as I have explained several times already.
  • 0
    @Fast-Nop what about Yi?
    You never explained what those layers are FP needs but OOP doesn't.
    And which OOP gui application is written without any framework?
    And what does the browser do for you, that makes those applications not count?

    1) so that's why FP programs tend to be much shorter, because they require more bloat.
    "It's not about what you code..." what?
    3) never heard anyone say something about security. Sure, less bugs, better maintainability, but security has nothing to do with that.
    4) what is a GUI operation? Do you mean rendering?
  • 1
    I don't really get what we're arguing about anymore. Everything compile down to assembly, 1 and 0s... The only real difference is which tool you want to use to think about it. If the problem more easily expressed as recursive functions with base cases, FP is better because the compiler knows how to optimize so you don't get a Stack overflow or need to create huge deeply nested loops.

    If your dealing with objects that get passed around and hold their own state, OOP is easier to think about.
  • 1
    @host127001 I did explain that. Several times. Sorry, but you simply don't get it because you have never been doing actual GUI programming, and the comment section of a rant is not the right format for teaching you the basics. I'm out.
Add Comment