Hacker News new | ask | show | jobs
by ajkjk 3429 days ago
Is there a non-traumatizing way to debug long chains of method calls? I had a lot of trouble with this when I last used Java, a year or so ago.
3 comments

No sure what you mean exactly, but IntelliJ will show ever-expanding expression list to choose from when setting a breakpoint even when they are chained and on a single line as well as displaying return value from last method call. In my experience debugging such method chain is no different to any other debugging bar variables names.
- Don't chain multiple methods in a line. One call per line. IDEs will usually let you set breakpoints per line.

- You can still use intermediate variables for readability

e.g. instead of

    nums.filter((n) => n % 2 == 0).map((n) => n + 2).foreach((n) => print(n))
do:

    nums.filter((n) => n % 2 == 0)
        .map((n) => n + 2)
        .foreach((n) => print(n))
or:

    List<Integer> evens = nums.filter((n) => n % 2 == 0)
    evens.map((n) => n + 2)
        .foreach((n) => print(n))
I think java's problem here is how annoying it is to split these up. For example your example completely split up in java vs haskell:

Java

  IntPredicate even = i -> i % 2 == 0;
  IntUnaryOperator add2 = i -> i + 2;
  UnaryOperator<IntStream> process = s -> s.filter(even).map(add2);
  for (int i in process.apply(numbers)) {
      System.out.println(String.valueOf(i));
  }
Haskell:

  printProcessed  = mapM_ print . process
    where process = map (+2) . filter even
It's even more concise in APL, assuming you know how to read APL.
Good points. I just feel that this is something IDEs really need to solve, without involving work from me. And it might be a limitation of the JDK debugging system (though I imagine it could be shimmed into IDEs either way).

Basically I want to see a "skip to next chained method" button alongside "step" and "step into" and "step over". And maybe another that lets me step to the next iteration of a given chained method as well.

Set a breakpoint in first expression in the function that is being mapped unto?
That's the traumatizing way. Not bad if you have one mapped function. Terrible if you have dozens. Stepping through code should not require setting more than one breakpoint - but if I have to find where a set of chained method calls goes wrong I have to breakpoint-binary-search to the problem.

When you have "if" statements, you can press "next" repeatedly in Eclipse/IntelliJ/whatever and step through the code. When you use chained method calls you're constantly going into and out of function calls, and all the local variables become return values that you don't ever necessarily get to see in a stack frame, and sometimes you have to step through loads of boilerplate to see the next interesting line of code, even when you're doing something totally simple.

I feel your pain. Having to manually unwind chained calls just to see which one caused the NPE or whatever is obnoxious and kind of defeats the purpose of this style of coding. IDE's really need support for this.
Intellij can drop breakpoints on the Either::map, or in the lambda contained therein. It's really not much different than debugging the if version.
The problem isn't breakpoints so much as stepping through them. You either step through the whole chained method at once, or have to set a breakpoint inside of it. Whereas with loops you can step through loop iterations easily with no additional work.
Honestly, this hasn't been a problem. If I get a bad result I merely figure out where I went from a left to a right (and there will only be one spot where that happened), and debug that function only. I've never had to debug the entire chain from top to bottom, ever.

But if you're really worried, set a breakpoint in each lambda (trivial in IntelliJ) and use continue instead of step over.

Please remove your downvote. You shouldn't use it to disagree with a viable suggestion. Your comment made your argument nicely!

Ok, I agree with you. Someone needs to patch Java and other IDEs to allow breakpoints on periods. Double clicking a dot to set a breakpoint sounds like awesome UX. Why hasn't this been done?

I didn't downvote you.

Breakpoints on periods and the ability to step through them. Honestly if I have to use more than one breakpoint to find a problem because stepping doesn't work, I'm unhappy.