You place the cursor at 'getScore' and press F12. This problem (calling functions defined god-knows-where) is not unique to OOP as opposed to FP.
> How do you know which part of your code is responsible for the number of this.rockets and how many methods in how many classes can change it?
You place the cursor at 'rockets' and press Shift+F12. This problem (modifying/passing data around god-knows-where and what parts) is not unique to OOP as opposed to FP.
> How do you find out which part of your code is going to call the launchRockets method,
See above.
> and whether this will even be this class's method or one of its children's?
Well, there is Ctrl+F12 that shows you different (re)implementations of the method.
> How many hops across your codebase do you need to make to figure all this stuff out?
About three to four. Again, this problem is not unique to OOP as opposed to FP: with FP, when your 'foo' function gets a 'frob' function passed to it as a parameter, it's anyone's guess what actual function it may be. To find all possible cases requires you to find all call sites of your 'foo' function, but that's non-trivial since it is most likely has also been passed around as an argument under different names.
Well, part of that problem is solved by explicitly importing functions from individual modules, at which point you know where exactly your function is coming from.
> when your 'foo' function gets a 'frob' function passed to it as a parameter, it's anyone's guess what actual function it may be
Part of it is probably solved by static typing. The other part is that it shouldn't pose a problem, much like you probably don't have a problem passing all sorts of frobs to your map-s, and your filter-s, and your forEach-es, and your then-s
Do you really never need to see what a passed-in function actually does in your FP code? Never need to see what type an argument is in our fancy Haskell or Hindley-Milner-typed language?
In FP, I tend to look at implementations to understand what they'll produce
In OO, I do this, but I also need to know _how_ since they might be changing the current context I'm working in. It's not enough to know that X method produces Y, I also need to remember that calling X implicitly modifies Z when I'm referencing Z
In an FP environment X can't modify Z outside of his context, so I don't have to care about how he produces Y. The cost of this is that someone needs to own Z and functions need to additionally return the new Z, but I think that explicit hierarchy helps in guiding towards a more understandable architecture
I'm hesitant to say always, but I can say:
- in imperative code I never feel comfortable without inspecting the passed in function
- in pure functional code, I rarely feel uncomfortable taking a pure function at it's word
How is OOP easier to understand exactly?
If you are debugging the code that looks something like this:
How do you know which part of your code contains implementation of this.getScore method? How do you know which part of your code is responsible for the number of this.rockets and how many methods in how many classes can change it? How do you find out which part of your code is going to call the launchRockets method, and whether this will even be this class's method or one of its children's? How many hops across your codebase do you need to make to figure all this stuff out?How is this style any simpler than functional?