5 ms·
For me OOP is weird. I never understood what people mean when they say it is close to how they think. It feels like a way to obfuscate the flow of code and requ
by cardanome 5y ago
For me OOP is weird. I never understood what people mean when they say it is close to how they think. It feels like a way to obfuscate the flow of code and requires to make decisions about what thing should have which responsibility and relation with which other thing and building weird hierarchies that will bite you back in the long term.
Relations between Objects change, customers don't know what they want, change is always pain with OOP.
Now people say, composition over inheritance. Right, but isn't that the point of functional programming?
Functional programming maps to how I think. The most important questions is always: What data structures do I need? Get your data in order and the rest will flow naturally.
I don't use functional programming because I am a math nerd or something, I am not even good at math. I use is because it is composible and easy to understand. I can refactor without any fear of side effects.
Now is pure functional programming practical? For some tasks, sure but yeah not always. Imperative programming gets stuff done. Work with the strengths of both.
The thing you are not used to always feels weird, that is a problem with you not the thing you try to learn.
- magicalhippo 5y ago> I can refactor without any fear of side effects. Can you? Like say you changed you sum() function to only sum every other element, because for the code you're working on right now that made sense. Well now you've screwed up the other places which relied on sum() summing all the elements. Dumb example because you'd know better, but surely you can still shoot your foot off like that with FP? And yeah I know that's not the side effects you were talking about, but when I'm changing my OOP stuff, that's the kind of side effect I'm most worried about. I've never really used a proper functional language though, so it's certainly possible I'm unenlightened.
- matt_kantor 5y ago> I know that's not the side effects you were talking about, but when I'm changing my OOP stuff, that's the kind of side effect I'm most worried about. That's not a "side effect"[1] at all. It's a logical bug in the implementation that only affects the function's return value. You absolutely still have to worry about those sorts of bugs in FP, which is why you still need tests or a fancy enough type system to prove the bug cannot happen (for your example that is unlikely to be practical). "Without any fear of side effects" doesn't mean you don't have to fear anything at all, but it's one less thing to worry about. [1]: https://en.wikipedia.org/wiki/Side_effect_(computer_science) https://en.wikipedia.org/wiki/Side_effect_(computer_science)
- magicalhippo 5y ago> That's not a "side effect"[1] at all. Yes, like I said. Point is, in my imperative OOP code, I'm relatively seldom worried about actual side effects, and more worried about introducing bugs due to me not fully grasping all the interactions of the code I'm changing. Did someone somewhere make an assumption about how this code works (sums all numbers), and am I breaking that assumption when I'm making this change (summing every other number)?
- Tainnor 5y ago> I'm relatively seldom worried about actual side effects I'll give you one concrete example: In a number of ORMs, I have no idea when database calls actually happen and this can lead to a) subtle logic bugs (inconsistent state), or b) bad performance (N+1 queries). I've had such problems both with Ruby's Active Record and Hibernate, two of the most popular ORMs. I've even deployed code that had subtle bugs, even though I wrote tests, because while my tests verified that the correct state of the object was written to the DB, the updated state was not reflected in the JSON response object. I'm sure similar things happen in other frameworks as well. A PFP can prevent that sort of craziness from happening.
- magicalhippo 5y agoFair point, though I'd say such ORMs are broken by design by the sound of things.
- Tainnor 5y agoI agree that Hibernate in particular is broken by design, but it is what it is...
- Tainnor 5y agoConfidence in a program's behaviour is not an all-or-nothing proposition. You can statically verify certain properties of your program (through immutability, type systems, linters etc.) without having to write a full formal proof of your program's entire behaviour, and you can gain more confidence in the entire program working correctly. In the example you just gave (summing over a list of numbers), in almost all programming languages you'd resort to runtime verification instead, i.e. tests, just because it's so much more practical. But if you have a PFP language, you still have the confidence that the behaviour of the inputs and outputs is the only thing you have to test, since the function cannot do anything else.* Even in a non-pure FP language, you know that it cannot mutate other variables, although it might have side effects. * Ok, it might loop forever or crash, but that's comparatively rare.
- cardanome 5y ago> Can you? Like say you changed you sum() function to only sum every other element, because for the code you're working on right now that made sense. Well now you've screwed up the other places which relied on sum() summing all the elements. I would not change sum but just filter out every other element and feed that new list to the sum function. (If you need it often, write a new helper.) Your sum function should not decide which elements should or should not be added, that is the callers job. It doesn't even have the context to decide on that. So yes, I would have the guarantee that nothing would break because I did not change sum in the first place. In practice you probably wouldn't even start with that sum function but simply implement a function that takes two numbers and adds them together. Then the caller can use higher order function like fold and filter to do whatever it needs. (Of course we assume it is not literally adding two numbers but some complicated logic, otherwise don't even write a helper for it, just sum your stuff when you need it.) And yes, you can still have logic bugs in functional programming languages and it can't really protect yourself from that when refactoring but I wanted to note how keeping your design simple and having easy to understand composable functions can help avoid bugs.
- magicalhippo 5y ago> I would not change sum but just filter out every other element and feed that new list to the sum function. Of course, and I would do the same in my imperative program. A dumb example like I said. > Then the caller can use higher order function like fold and filter to do whatever it needs. Right but then at some point you have a chain of ten of these calls, and you have it _all over_, and so you figure hmm lets make a separate function out of that, code duplication is bad after all. And then you find your new function has a bug and you need to change it... Will all the users of this new function be OK with that bugfix? If you don't wrap up these chains into new functions, how do find all the places you need to change once you need to make that bugfix? > having easy to understand composable functions can help avoid bugs Sure this I get, which is why my imperative code also contains lots of "do one thing" methods that is used as Lego bricks. And I use a fair bit of functional-ish code, ala LINQ, where it makes sense. I wish I had discovered functional programming at an earlier stage, where I had more time to experiment. I think it would be very informative to make two non-trivial feature-equal programs in either style so I could compare.
- GuuD 5y agoOh man. Are you me? Thanks for that comment. For me functional programming was just like a “missing link”. Wait, I can just code like I think, not in this weird statefull way? It’s just so practical for me. I can deliver 10x the value for 0.1 the effort. It’s just not fair, I know for a fact that there are more people with the same model of thinking, I just want them to feel as liberated
- TacticalCoder 5y agoAmen! Same as you and GP. I'd add that, for me, "functional programming at the edges" is sufficient: I don't need to go full straight jacket / Haskell-style to get a huge lot of the benefits of FP. I can still use an imperative outer shell and still have lots of functional parts in my code which are easy to reason about.
- cutemonster 5y agoWhat language do you use? (that gives that nice blend)
- schwartzworld 5y agoJavaScript!
- cutemonster 5y agoOk :-) me too (typescript)
- ladyattis 5y agoI tend to mix OOP and functional together as I use objects as a way to relate functionality or steps within the process. I almost never use objects as a means to model the actual data. At most, I use objects in this instance as glorified structs. The only real benefit that OOP as implemented in most languages has is the ability to write to an interface whether you use an explicit interface type or an abstract class which concrete implementations derive from. Like Bob C Martin said in many lectures the inversion of control is really where OOP shines. Anything else most other paradigms do it better.
- Tainnor 5y agoI find that OOP languages (as long as they support FP and immutability) have the benefit of using classes as nothing more that first-class parameterised modules (without any mutable state) so I don't have to repeatedly pass arguments from one function to the next but can look them up from a shared context. Haskell doesn't really have that option, although people have told me that OCaml can do that.
- chromatin 5y agoThis is exactly how I use D!
- playing_colours 5y agoYou are describing the way I wrote in Scala, and now in Python: using class instances as that are initialised shared contexts like shared database connections, serialisers, etc.
- adverbly 5y agoThis is exactly how I roll these days! Avoid classes until I find myself doing too much argument plumbing, or having too many arguments to a function. Also love me some memoization. If I'm honest, I haven't tried aggressively using closures, but I suppose that would have been another way to do it...
- sfvisser 5y agoYes, classes as glorified Reader monads :)
- Haga 5y agoIn oo inevitably the programmer appears, disguised as manager, Händler, coordinator and Marshall er and then its all procedural again with all the procedural problems. Functional programming should life at least here. Preferably also down in the factories, were the Confighandlers are hard at lurk.
- lambdatronics 5y ago> building weird hierarchies There's a certain kind of personality that really gets into that (the 'architecture astronaut'), specifically because it is counterintuitive and they like convoluted things. I think the idea that really gets them going is "look, it knows to XYZ itself!" I do scientific programming, and most of the time, functional style makes way more sense. Doesn't stop someone with the OOP bug from turning all the logic inside out and making a brittle mess, though.
- kaba0 5y agoThere are problems (or parts of problems) that are more about behavior and others that are more about data. The latter of course is benefited by a FP mindset/language, but I wager that OOP is a better fit for the previous. What OOP gives is a way to encapsulate some given part of a program, and make it a working little building block you can later reuse. It can contain mutable state, but is promised to be correct as only that class can touch it, it can be used as a slightly different version of a common interface, etc. The two are not mutually exclusive at all.