4 ms·
After having this discussion in so many professional settings, I'm starting to think that this is just something that divides people. Maybe our brains are wired
by xorcist 1y ago
After having this discussion in so many professional settings, I'm starting to think that this is just something that divides people. Maybe our brains are wired differently. What's important for me is that the call graph is simple. Second most important is that data structures are easy, or at least fits the problem. The amount of lines in a function is a distant third.
It could have been me behind one of those thousand line functions. Some tings lends itself naturally to this style, such as interpreter-like loops and imperative business logic. There's always that someone that argues that splitting up the code with function calls would somehow make it more "maintainable".
I'm reluctant to do it, because the code is identical, only non-linear which means harder to understand. Combine this with global symbols and it's a recipe for accidental complexity. This is so obvious that I for a long time thought people with the opposite opinion were just cargo-culting some OOP "best practice" mess which has doomed so many projects, but maybe they're just wired differently.
- frlinook 1y ago[dead]
- endymion-light 1y agoI guess I don't really see a reason to have a 1000 line of code function that's not broken down. Although I personally despise the massive call graphs, my rule of thumb tends to be if I spend over 10 minutes trying to hold all the logic in my head, something is wrong. Especially with imperative business logic - surely it makes so much more sense to break it down into functions. If you're on call at 2am trying to solve a function with imeprative business logic that someone else has written and has over 1000 lines, you're going to hate yourself, and your coworker.
- westcoast49 1y agoI think you're right. I'm on the opposite side of it, but I have a colleague who routinely writes functions that are hundreds of lines long, with 30-40 local variables inside each function. I've come to realize that he does so because his brain allows him to do it. He has a brain that is more detail-oriented than my brain. Where I naturally see a problem as a "tree" of sub-problems with their own details, he naturally sees one large problem with 100 details. He naturally writes code to accommodate his own cognitive style, while I write code to accommodate my own cognitive style. Moreover, I've come to realize that my colleague is not adverse to using abstractions if they are well established, and if they already exist. But he is (much) less inclined to invent or write new abstractions than I am. As you have concluded, I have also concluded that this is actually a matter of cognitive style, more than it's a symptom of "slop" or "cargo-culting of best practices".
- delichon 1y agoI had a colleague who wrote long functions like that. Over time I came to think of him as an inconsiderate asshole. Unfortunately he was me a few years earlier. I gradually learned the value of organizing code in short sweet methods. When that style become old code, I and my other colleagues came to like that crusty old coder better. I also thought it was a matter of cognitive style but for me it turned out to be inexperience.
- stirfish 1y agoDo you write comments in your code? If you ever have a long function that like .... // Here's where we apply coupon codes ... It makes sense to me to break that out into it's own function, preferably one with no side effects that I can write a test for if I need to. I can give it a name related to the business logic. Inevitably there will come a new special case where, for example, where Gold Members will get to use double coupon codes on Thursday. You'll start by looking in `checkout()` where you'll see either 1000 lines of other special cases, or maybe 30 lines with function calls like `foo = applyCouponCode(shoppingCart, couponCode)`. For me, it's easier to see where to start with the latter.
- Kinrany 1y agoComments are perfectly fine on their own. It's common that a block of code can be given a higher level explanation in a comment, but wouldn't be a good standalone function because it depends on the context too much and so the function has absolutely no chance of ever being used a second time.
- stirfish 1y agoIt's okay if a function is only used once. It's worth it to separate it from the context it doesn't need. Well, twice, including the test. If a block is complex enough to warrant a high level explanation, you might as well capture that intent in a test too. Edit: in my example, `applyCouponCode` takes in a `shoppingCart` and a `couponCode`, so you know that's all you need to apply a coupon code. You'd change it to something like `applyCouponCode(shoppingCart, couponCode, user.memberStatus)` so you can tell at a glance that `memberStatus` has something to do with how coupons work. You wouldn't want to pass in the whole `user`, because giving the function more than it needs makes it hard to infer what context the function needs and, therefore, what it does.
- Kinrany 1y agoTests are code. If the function is easy to test then it's more likely to really be worth having.
- 1718627440 1y agoI think a better measure than simple LoCs is to cluster the local variables by use. If you get entirely separate clusters or large clusters that only share a few variables, then you should break them up at the cluster boundaries.