There is absolutely a place for PR reviews, and I don't think the person you were replying to was against that, just that PR reviews would be better by actually judging things like readability directly rather than relying on measures that estimate those qualities.
I can think of many times arbitrary rules like linting or Clean Code-esque standards resulted in a "solution" of making my code less readable.
It's very hard to make a function you need to scroll back and forth to understand readable. Break it into smaller ideas that are more easily reasoned about. We love to think we are too clever, but we are not and we always need to keep an eye on cognitive load - having epifanies when you finally understand how something works is a great feeling, but relying on epifanies coming to you when you are trying to figure out how something works because it's not working now, is a terrible practice.
"Functions should be 5 lines or less" is a measure that approximates that rule, but isn't exactly the same thing - I hope you agree we could both come up with 4 line functions that are impossibly complex or 6 line functions that are easily reasoned about.
I think with Clean Code (and a lot of these kinds of things - Design Patterns is a great old example of this), people can get too dogmatic about applying these sort of approximated rules, when it would make a lot more sense for someone else (i.e. not the code writer) to use their best judgement and just directly answer the question "is this function easy to reason about?" rather than using the approximate measure.
This can’t really be a serious guideline unless you are writing APL, in which 5 lines can already be daunting to grasp. This guidance depends on the language. For Python, once you get over 50 lines it starts to look like you don’t actually know what you are doing anymore.
In any case, the point stands - there are 19 line functions that are too sense, and 21 line functions that are sensible.
Here’s a 150 line long function I wrote which I think is quite beautiful:
https://github.com/josephg/diamond-types/blob/e143890a596aaf...
This function traverses a DAG given 2 points in the dag, A and B. It breaks the dag into 4 regions - the nodes which are (transitively) only in the parent subgraph of A, B, in both or - implicitly - in neither. It runs in O(n log n) time.
How would you improve this function? It could use a better doc comment. But do you honestly think it would be better if it were broken into a lot of small functions, each called once? How would you do it?
Lines or code is an indicator, not a goal. If you write long-winded functions, your code is bug prone and harder to test and verify. If you refactor it, it gets shorter. Where do you draw the line?
The same goes for how many characters you accept between two line breaks. Some go for 76. Some for 130 or more. There is no difference if your line has 129 or 131 chatacters, but if you spew a comment with 999 characters in a single line then your feedback is actionable if you say "hey man, don't be that guy. Rewrite your comment and make it readable."
> (...) PR reviews would be better by actually judging things like readability directly rather than relying on measures that estimate those qualities.
Not really. Calling out basic things like "this function is far too long" is clear, objective, and actionable feedback. That is a good PR comment.
Dismissing clear and actionable feedback as some guys whims is a red flag, and a telltale sign of someone who has no interest to improve their output and address issues.
I think the issue that originally launched this thread of the discussion is people who take the specific rules to a dogmatic level and apply rules blindly, and transform "functions should not be long" to "functions should be less than 20 lines no matter what". 20 lines (or whatever standard you land on) should be a guideline and not an inviolable law of the universe, and if reducing a method below 20 lines harms comprehensibility and readability, you're letting the guideline get in the way of the actual goal.
A function with too many lines is, most likely, doing more than one thing. Functions should do one thing, be easy to test (with few or no external dependencies whenever possible), be deterministic (unless required not to be), and so on. Excessive mocking is another code smell I look for - it often betrays poorly designed functions that can't be easily tested.
It was a complete failure. That branch was abandoned and development continued off the spaghetti.
There is a reason bioinformatics has its own set of viz charts that only they use.
That's my anecdote anyway, it led me to the conclusion that sometimes things are continuous spaghetti and other than some small organizational changes, attempts to exhaustively discretize the code are a fools errand.
The biggest benefits most projects like that are likely to see are performance and debugging improvements accomplished by factoring out recursion.
Mapping to terrain is always the real effort in my opinion.
It was considered too hard, most likely because the present state of the code already degenerated beyond recovery. It might be difficult, but it's never impossible.
> Mapping to terrain is always the real effort in my opinion.
Yes. The domain might be complex, and it might be possible that there are no simple ways to work within that domain. Irreducible complexity is, after all, a thing.
TDD, OOP, Clean Code, etc are an attempt to solve very real problems. They are then applied as dogma to places where these problems are not evident. That's the issue. Of course these rules have their place, but always with a caveat and never applied over all possible places where they might fit. Very often, a better solution exists, as well.