4 ms·
That'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 devel
by keyle 7y ago
That'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 forgot that it's about telling the computer to do something, as clearly as possible.
- seanmcdirmid 7y agoThe onion is useful when thinking through a problem while writing code (add an abstraction layer as you try to eliminate pieces of complexity in layers), it usually doesn’t appear for aesthetic reasons. As understanding solidifies, the layers should probably be eliminated, and all that complexity should be smashed into one layer...or maybe not.
- KayEss 7y ago> they forgot that it's about telling the computer to do something, as clearly as possible Or alternatively, it's to explain to the next reader of the code, as clearly as possible, how the problem was solved (in such a way that it can also be executed by the computer).
- keyle 7y agoYes I meant "as clearly as possible" <for the next guy>.
- tsumnia 7y agoWhile 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 they can pull back a little. Outright avoiding indirection (I don't believe) does that. [1] http://www.cs.kent.edu/~jmaletic/Prog-Comp/Papers/fix-1993.pdf http://www.cs.kent.edu/~jmaletic/Prog-Comp/Papers/fix-1993.p...
- kenhwang 7y agoMy 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.
- Double_a_92 7y agoAbstraction is not mainly about avoiding repetition though. It's about (well...) creating abstraction. Imagine if you have to check permission to do something, and that check is really complex and long code. If would be better to have code like: if (hasPermissionToEdit(myUser)){ ... Than a ton of ANDs and ORs in that if, that nobody would quickly recognize as a permission check... even if it's just there once. As a minimum I'd put that in a properly named variable first, if I really wanted to avoid an extra function.
- psychoslave 7y agoKeeping 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.
- keyle 7y agoAgreed, I don't preach writing code like a caveman either!
- ElonMuskrat 7y agoDuring review and debugging I need to understand what the code is actually doing. I would prefer not to chase through a linked-list of function to uncloak something as trivial as string comparison. There seems to be this insidious notion that engineers never need to understand implementation details, and therefore should aspire to bury program semantics through layers of abstraction that [often poorly] express the author's intent. This is a recipe to write systems that are insecure, and operationally un-maintainable.
- ubertaco 7y agoIndirection is a tool, and there are both good reasons and bad reasons to use it (as with most tools). 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.