Earlier quoted context omitted.
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.
Avoid Indirection in Code
121–130 of 220 posts
Re: Avoid Indirection in Code
#122It'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…
Re: Avoid Indirection in Code
#123Earlier quoted context omitted.
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 g…
Even though we're unlikely to need this construction more than once:
def is_prime(x): return x in primes(x)
This one (or one just like it) appears quite common: def is_in_set(x,y): return x in y
But Guido already noticed that! That's why he made an "in" operator in the first place! As soon as our routines become too generic, we're just making APL without arrays, and that's why taste matters so very much.> That promise is the same as "code-hiding".
If I can see the implementation at the same time as its usage, then the code is not hidden. Ipso facto.
But to expand more on what I mean by this, consider that close() is hiding code: You get all of the bugs in the C library; in the Kernel; all in code you cannot see either because it is locked/compiled, or because it's in a different file you didn't bother to read. And so on. And yet the world didn't stop spinning, and many people use close() every day without knowing or dealing with a myriad of bugs and weird corner cases[1]. So it is that even if code hiding is sometimes bad, it is sometimes less bad than other things we could be doing.
[1]: Ha ha, only serious. http://geocar.sdf1.org/close.html
Re: Avoid Indirection in Code
#124The server at www.matthewrocklin.com is taking too long to respond.
too many HN readers perhaps?
Re: Avoid Indirection in Code
#125While 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…
Only people who've never used a good type system think this. Your function example demonstrates this pretty nicely: use a proper interval type for the two intervals and a proper return type rather than int, and then the answers to all your questions become obvious.
Re: Avoid Indirection in Code
#126Ok, to take a real world example instead: if (url.startsWith('http://')) { vs. if (isAbsoluteUrl(url)) { If the next developer comes by in 2 months to fix the case for https:// urls (and protocol relative ones in 6 months), they'll immediately be able to spot the intention of the code and can easily fix it in the abstraction layer that's already in place. Moreover, the fix will be applied every other place this fault…
Re: Avoid Indirection in Code
#127That's a pet peeve of mine; I see it all the time when I work with lesser experienced developers, only I didn't know how to call it. I call it onion skin development, where the developer keeps hiding stuff in more layers of the onion, making my eyes water as I have to dig deeper and deeper to essentially find `a.foo(b)` under 12 layers of abstraction. They're so focussed on making everything look so purrty, they forg…
A good reason would be to clarify the why or the what by "glossing over" the how:
# Unclear:
list_range = range(0, len(movies))
for i in list_range:
j = randint(list_range[0], list_range[-1])
movies[i], movies[j] = movies[j], movies[i]
# Clear:
movies = shuffle(movies)
Yes, you're "hiding" the actual steps (the "how"), but in doing so, you're elevating your intent (the "why"/"what") to the forefront, and so you're making it clear what your code is supposed to be doing. This makes it easier to understand overall, and makes it easier to determine when your implementation and your expectations don't match (because your expectations are clearly described).A bad reason for indirection is one that's super-common in Java: namely, "we might need to make this swappable at some undetermined point in the future". It's the kind of thing that leads to
public interface UserLookupService {
// ...
}
public class UserLookupServiceImpl implements UserLookupService {
// ...
}
That's just repetition for reasons that are at best forced by technical limitations, and at worst by paranoid decision-making.A mark of skill at coding (in particular, as a part of software development) is the ability to clearly convey intent to the reader. Sometimes, that means bringing a new concept into code that makes the problem easier to understand and talk about (to borrow an example from elsewhere in the comments here, introducing a DateInterval type can make common operations on two dates clearer). Sometimes, that means recognizing when the details get in the way of the point.
We often do the same things when we write prose for humans to read. When writing prose for humans, it may help to introduce new clarifying terms like "time complexity" and "memory usage" so that we're not constantly explaining that when we say "performance" this time we mean "performance specifically in terms of how much RAM is used" and that time we mean "performance in terms of how much time is required to for the function to complete". It certainly often helps to edit down overly-detailed explanations that distract from the main point (possibly putting the fuller explanation into a footnote); if someone asks where you've been, how helpful is it to tell someone that you opened your garage door, got into your car, started your car, shifted gears into "drive" (or 1st gear), drove down your driveway, turned left....etc, as opposed to telling them that you went to the store to buy milk?
The point I'm getting at here is that telling someone "avoid indirection" is a bit like telling someone "avoid summarizing." Sometimes, a full account is needed, sure -- like if you're on a witness stand -- but most of the time, summary is one of many useful tools to convey information clearly.
Likewise, sometimes it's necessary to see every single explicit step being performed -- when doing in-depth performance optimization, for example -- but most of the time, indirection (especially by functionalization) is one of many useful tools to convey information clearly.
Indeed, indirection in code is actually "safer" than summarization in writing. In code, you can always "go to definition", where in writing you may not have that option.
Re: Avoid Indirection in Code
#128Earlier quoted context omitted.
At this point you might also consider a `try: treat(x); catch unauthorized: fallbackly_treat(x)` pattern.
Disagree. Someone attempting to do something while unauthorized is oftentimes not an exceptional state and regular business logic depending on how access is given to different endpoints. Do not use exceptions, which are "heavy" (capturing call-stack etcetera), for something that commonly occurs.
Re: Avoid Indirection in Code
#129Today, I try to do big functions, multiple returns and const where I can. I still use code-blocks sometimes to scope variables.
I sometimes end up with a few hundred lines of code per function, but I can usally scroll over it and find what I need without jumping around.
Especially in JavaScript the addition of const and async/await helped much with this.
Re: Avoid Indirection in Code
#130Earlier quoted context omitted.
Disagree. Someone attempting to do something while unauthorized is oftentimes not an exceptional state and regular business logic depending on how access is given to different endpoints. Do not use exceptions, which are "heavy" (capturing call-stack etcetera), for something that commonly occurs.
Put another way: exceptions are exceptions to the normal program flow. They should not be used to communicate expected errors. I think of them as analogous to the `if (do() != 0) { goto out; }` paradigm of C.