Live data from Hacker News

Avoid Indirection in Code

matthewrocklin.com

111–120 of 220 posts

Re: Avoid Indirection in Code

#111

It's more of a problem with OOP language because the function call might hide a side-effect. So now the reader has to go and read the function definition to make sure no side-effect is happening in there. With functional languages the mutable data is available in the reader's context. The implementation might still be mysterious but hopefully the function name is good enough to give a clue about that.

I'm just being a bit grumpy, but there are non-pure languages that aren't OOP, and there is no reason why you can't write OO code that is where all objects are immutable. However, it is a good point that mutability is a major problem. It's just not correct that this has anything to do with OOP.

Yep. And it's not necessary for a language to be pure to get that benefit on a per method basis.

Rust is OOP but you define in the method signature whether or not that method mutates state. So if a method has the signature that includes `&self`, you know it doesn't mutate. Whereas `&mut self` indicates that it does (or at least could).

Re: Avoid Indirection in Code

#112
Code is like a bunch of cords. Each time you add something, it's like adding another cord, and at some point you will have "spaghetti", and you pull out every cord, unravel it, connect everything neatly and use zip-ties to hold everything in place. The problem is when you use the wrong abstraction, eg. you start zip-tie:ing before even knowing what other cables to add. So don't be afraid of using the copy/paste function. Make it easy to unravel.

Re: Avoid Indirection in Code

#113
post #95
post #40

It's not indirection , it's bad abstraction that's the real issue here. Consider the example used in the article: if x.startswith("foo"): do_something_with(x) if is_foolike(x): do_something_with(x) The problem with both of these variations is that the "if-statement" doesn't have any meaning behind it. There's no gain in the indirection presented here. Whereas the following code has meaning: if checkHasPermissions(x):…

In many cases speaking of the foolike nature of a value is not dissimilar to speaking to the primeness of an integral: Is a value prime? And now here's is an algorithm for determining whether this value is prime. The motivation for many splitting out a prime-testing function is that primality testing is hard to do efficiently, not that there are many kinds of primes or many kinds of integrals. Indeed, in some languag…

I very much enjoyed this poem.

All the same I think you may have thrown out the abstraction with the bath water.

> Does this is-prime routine even deserve a name?

Absolutely. If you saw it over and over you might start just reading it as "is-prime" instead of going through the process of mentally interpreting it each time. But what about similar-looking functions with similar functionality? You want a programmer to go and make you a promise that it has the meaning (if not the implementation) you're thinking about. That promise is the same as "code-hiding".

Re: Avoid Indirection in Code

#114
post #97

Earlier quoted context omitted.

Even better (IMO), "hasPermissions" It isn't clear whether the "check" prefix means the function returns based on whether the checking was successful or not.

I'll do you one better... if authorized(x): do_something_with(x)

At this point you might also consider a `try: treat(x); catch unauthorized: fallbackly_treat(x)` pattern.

Re: Avoid Indirection in Code

#115
post #11

Earlier quoted context omitted.

While I can agree with the sentiment, when is indirection okay vs. when does it become spaghetti code? Given [1], there needs to be a happy medium between 12 layers and all in a single method. I think with less experienced developers, the issue is diving too deep because they think they need to prove they aren't novices. However, its still a learning period for them where they just need a good mentor to tell them the…

My rule of thumb is 3 times. Whatever is abstracted away must be used at least 3 times. It's amazing how much preemptive prettification by abstraction it prevents.

Keeping a function at a given cyclomatic complexity generally also give a good indication whether a function should be refactored.

That's not completely the point of the article, but both issue are interesting metric for deciding the level of factorization.

Also one need more accurate specification when defining a call deepness alarm. Most direct call to any random API will probably already explode a limit of 3, which doesn't necessarily say that the framework is brokenly atomized.

Re: Avoid Indirection in Code

#117
post #40

It's not indirection , it's bad abstraction that's the real issue here. Consider the example used in the article: if x.startswith("foo"): do_something_with(x) if is_foolike(x): do_something_with(x) The problem with both of these variations is that the "if-statement" doesn't have any meaning behind it. There's no gain in the indirection presented here. Whereas the following code has meaning: if checkHasPermissions(x):…

Even better (IMO), "hasPermissions" It isn't clear whether the "check" prefix means the function returns based on whether the checking was successful or not.

I like the rule from the Qt API style guide that every bool member or method returning bool should have a name that starts either with Is or Has:

  if (listWidget.hasItems()) {
    isButtonEnabled = true;
  }

Re: Avoid Indirection in Code

#118
post #67

While the example in the article isn't great for making the point I actually agree with the main idea. I understand the arguments for 'Uncle Bobifying' code but I think, as the article says, there's a balance to be struck. It's highly likely the next time I see your code (or my code if I'm coming back to it a month or two later) is when I need to fix a problem with it. While it's useful to have it split up into logic…

Isnt this just 'good coding practices'? How is 'Avoid Indirection in Code' justified?

Yes, but 'good coding practices' is relative/subject to interpretation. I see this as a necessary counterpoint to the 'Clean Code to extremes' in a lot of other blog posts.

It simply calls for some consideration before moving every little thing into another method.

Granted the title is clickbaity but that's just the curse of the modern web.

Re: Avoid Indirection in Code

#119

While the example in the article isn't great for making the point I actually agree with the main idea. I understand the arguments for 'Uncle Bobifying' code but I think, as the article says, there's a balance to be struck. It's highly likely the next time I see your code (or my code if I'm coming back to it a month or two later) is when I need to fix a problem with it. While it's useful to have it split up into logic…

Agreed, although I think the example isn't too bad. I often see such "helper methods" - usually in a class called "utils" or "misc" - when (novice) programmers "try to plan ahead": how should I write this so it can be re-used? But KISS is remains a good principle. Predicting the future is hard. If in doubt, don't put in the extra indirection/abstraction. If/when the next person needs that functionality, they can refa…

The other thing you see is extraction of logic applied, particularly to business logic, prior to the actual logic being clear.

So a developer will notice two very similar bits of code and maybe include some kind of parameter to a method or even worse, build some kind of abstraction (inheritance shudder) then as the project evolves it turns out there are actually very different business requirements for each case and you're stuck in a bit of a mess.

As you say there's a cost to optimization, the wrong abstraction is far more painful than no abstraction. This quote from another blog post the other day is relevant I think:

"Future thinking is future trashing

When developers try to solve a problem, they sometimes try to find a way that will solve all the problems, including the ones that may appear in the future.

But here is the thing: The problems from the future will never come and you'll end up either having to maintain a huge behemoth of code that will never be fully used or you'll end up rewriting the whole thing 'cause there is a shitton of unused stuff.

Solve the problem you have right now. Then solve the next one. And the next one. At one point, you'll realize there is a pattern emerging from those solutions and then you'll find your "solve everything"."

These are all just re-statements of KISS and YAGNI but it's definitely the most important principle.

Re: Avoid Indirection in Code

#120

While the example in the article isn't great for making the point I actually agree with the main idea. I understand the arguments for 'Uncle Bobifying' code but I think, as the article says, there's a balance to be struck. It's highly likely the next time I see your code (or my code if I'm coming back to it a month or two later) is when I need to fix a problem with it. While it's useful to have it split up into logic…

The issue is fundamentally abstractions leak. And if the code is overly "Uncle Bobified" the abstractions will leak bugs. On the other hand if you under "Uncle Bobify" the code will be very difficult to read because you won't be able see the forest for the trees. This is one of the advantages of comments and local functions. You can inline a function an add a comment. With the comment providing the abstraction and th…

I think most of those questions could be answered with a sufficiently strong type system.
Post reply on HN