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):…
Avoid Indirection in Code
51–60 of 220 posts
Re: Avoid Indirection in Code
#52There's a lot of reasons to avoid indirection but I don't think decreasing the number of files you have to navigate is one of the better ones. I mean, who reads code linearly anyway. My hand hovers over F12 (the shortcut for go to definition in Visual Studio) half the day. Any good IDE will help with this. I feel like this person is like, I don't want to drill all these holes to build my deck. I'll use nails. And it'…
Re: Avoid Indirection in Code
#53Earlier quoted context omitted.
I'm sorry that this will come across as rude, but I feel like you're repeating something you've heard but didn't quite understand. Yes, at pretty much ANY level, you should write your function names to hide the implementation details and to describe the intention of the function. In my previous post I hinted that the name of the function should "describe what the function does", which is the same as "describe the int…
I'm sorry that this will come across as rude, but I feel like you're repeating something you've heard but didn't quite understand. You're right, it does come across as both rude and condescending, and you know it, so don't apologise. In my previous post I hinted that the name of the function should "describe what the function does", which is the same as "describe the intention of the function", because if the functio…
Yes, which is why when `is_foolike` tests that a string starts with 'foo', that's rather unexpected. If `is_foolike` actually describes the intention of the function, then the function testing for the string beginning with 'foo' is a bug, because it doesn't do what it's intended to do.
Referring to "the quality of starting with 'foo'" as "abstract quality foo" isn't hiding implementation details, it's being opaque about what a function does.
Put another way, "what a function does" isn't its implementation. "How a function does what it does" is its implementation.
> `starts_with_foo` implies an assertion a string beginning with a particular prefix
Yes, exactly. Because that is what it is intended to do, we hope, since that's what it does. That's NOT the implementation: there are plenty of different ways to implement testing whether a string starts with 'foo', and the name `starts_with_foo` isn't coupled to any of them.
> The point being that even though, in this (again) entirely fictitious example, the intention of the method is different from it's implementation
Yes. `starts_with_foo` is also different from the implementation, while still describing the intention of the method.
Could you explain to me why you think `starts_with_foo(x)` describes the implementation `x.startswith('foo')` and not some other implementation (such as `x[:3] == 'foo'`)?
Re: Avoid Indirection in Code
#54“Abstractions — or rather, indirections — are bad for for readability, but they are good in some cases.”
Umm... this can be said for pretty much anything. Over use of anything is bad. Inappropriate use of anything is bad.
> Mostly, I want authors to be aware that there is a human cost to indirection that is felt more acutely by everyone reading the code except the original author.
Sure. It’s a well known fact that abstractions have associated costs — nothing new there. However, the author seems to forget that not abstracting things can be equally costly — even when human readability is concerned.
Imagine someone trying to figure our the business logic be reading code. All they need to know is some conditions are being met for certain steps to be executed. The actual steps involved in the check are irrelevant to the business logic. The condition can be modelled separately from the business logic and can even change independently. For example:
def is_foo_condition_satisfied((self):
return self.variable.startswith(‘foo’)
In this case, it just happens that the satisfaction of a condition is implemented as prefix check. In the future, it might be changed to checking a flag or reading a database, or anything really. If you sprinkle the startswith() check all over you code, it will be hard to make the change. And it actually hurts readability. While reading a large codebase, you want to focus on specific parts of it — getting into the details of everything all at once does not make it easier.The most important thing to note is — programming is not confined to s strict set of rules. It’s not an exact science. You can’t define a strict a rules that must be followed. What makes sense somewhere is completely useless elsewhere. The Linux Kernel is full of goto statements, despite the fact that goto is considered harmful.
Dogma Driven Programming must be avoided. Even well known programming practices are guidelines at best. One must evaluate whether a given rule fits a given situation.
Coming back to the example at hand, functions are meant to divide the program by the logical tasks being performed, not by number of lines or any other metric. As I said before, it’s more art than exact science.
Is the check for foolikeness of something a logically distinct task? It depends on the context. There is no way to write a cardinal rule either way.
PS. I sincerely hope no one comes to me for code review with a monolithic function because of all the inlining — citing this article as inspiration.
Edit: Typo correction.
Re: Avoid Indirection in Code
#55It'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):…
It isn't clear whether the "check" prefix means the function returns based on whether the checking was successful or not.
Re: Avoid Indirection in Code
#56Zed Shaw puts it well: "Abstraction and indirection are very different yet cooperating concepts with two completely different purposes in software development. Abstraction is used to reduce complexity. Indirection is used to reduce coupling or dependence."
Re: Avoid Indirection in Code
#57Abstraction and indirection are very different yet cooperating concepts with two completely different purposes in software development. Abstraction is used to reduce complexity. Indirection is used to reduce coupling or dependence.
Re: Avoid Indirection in Code
#58The point made by the article (avoid using due to problems for debugging and code review etc.) does not hold much water. 'Indirection' can be invaluable while separating 'how you got it' from 'what to do with it' (it=some data), for example. 'what you do with it' can remain unaffected by changing 'how you got it'. This will not mess with code review practices but make understanding the pieces easier. It will also mak…
Abstractions are invaluable if you are dealing with a large codebase. Even the original author can’t keep everything in their head.
Indirections are invaluable if you want to be able to modify code in the future without making a gigantic mess — and potentially breaking compatibility in the process.
Re: Avoid Indirection in Code
#59The argument in the post is a bit of a strawman - for really simple examples like that indirection makes no sense. Saying "is_something_like" as an alias for "starts_with" is an unnecessary alias that does nothing for the readability or duplication of the code. Indirection really isn't necessary in this case, even if you use "starts_with" in a thousand places. It might make sense if you're trying to do a comparator,…
In Python it's json.load(file), so no indirection needed whatsoever.