7 ms·
Temporary variables are often tedious? I have found that well named temporary variables are the only clear way to comment code without actually writing the comm
by kriz9 4y ago
Temporary variables are often tedious? I have found that well named temporary variables are the only clear way to comment code without actually writing the comment. The version with temporary variables is much easier to understand without having to read the rest of the code.
- yamtaddle 4y agoAll I can figure is the people who keep pushing this sort of stuff in JS have very different problems than I do, if they think this will improve things rather than making them worse. ... I further suspect that their problems are mostly self-inflicted, but maybe I'm wrong about that.
- vikingerik 4y agoThis. Temporary variables are the way to go for deconstructing a complex expression like this. Everything is more readable when you put the results of an expression with two to four terms in a well-named variable. Trying to put everything into one giant closed-form expression feels clever and smart, but it's really just getting in the way of the next poor sucker who needs to understand what you were doing. This works the way human cognition does, by batching. The way humans can fit more items in short-term working memory is to batch up related concepts into one item. This is how chess masters do it - they don't see a piece and look individually at each square it is attacking, they see the entire set of attacked squares as one item. This is why "correct horse battery staple" passwording works - the human doesn't remember twenty-eight individual characters, they remember four words. Temporary variables follow how human cognition works, particularly when the reader is going to be somebody else's cognition who didn't go through the process of writing it.
- scotty79 4y agoWhen there are a few they can be really great. But if you need to accurately name every single intermediate thing they can become visual noise that hides what happens.
- shadowgovt 4y agoIn general, I think that when one does that, the code smell one is smelling isn't "This language isn't expressive enough; I need a third way to describe calling a function." It's "What I'm doing is actually complicated and I need to switch to describing it with a DSL, not adding more layers of frosting on this three-layer cake."
- notdonspaulding 4y agoI struggle to think of real-world examples where I've just needed to chain and chain and chain values of different types more than a handful of times. The claimed need for the pipe operator is this construction: function bakeCake() { return separateFromPan(coolOff(bake(pour(mix(gatherIngredients(), bowl), pan), 350, 45), 30)); } The piped code looks like: function bakeCake() { return gatherIngredients() |> mix(%, bowl) |> pour(%, pan) |> bake(%, 350, 45) |> coolOff(%) |> separateFromPan(%) ; Which is... fine? It certainly looks better than the mess we started with, but adding names here only helps clarify each step. function bakeCake() { const ingredients = gatherIngredients(); const batter = mix(ingredients); const batterInPan = pour(batter, pan); const bakedCake = bake(batterInPan, 350, 45); const cooledCake = coolOff(bakedInPan); return separateFromPan(cooledCake); } Even if you consider the `const` to be visual noise, the names are useful. At any point you can understand the goal of the code on the right-hand side by looking at the name of the variable on the left-hand side. You can also visually scan the right-hand side and see the processing steps. You can also introduce new steps to the control flow at any point and understand what the data should look like both before and after your new step. I agree that the the control flow is more clearly elucidated in the pipe operator example, but it tosses away useful information about the state that the named variables contain. It also introduces two new syntactical concepts for your brain to interpret (the pipe operator and the value placeholder). I contend the cognitive load is no greater in the example with names, and the maintainability is greatly improved. If you have an example where there are dozens of steps to the control flow with no break, I'd be really curious to see it.
- notdonspaulding 4y agoExactly. As the proposal contemplates this alternative, it claims: > But there are reasons why we encounter deeply nested expressions in each other’s code all the time in the real world, rather than lines of temporary variables. And the reason it gives is: > It is often simply too tedious and wordy to write code with a long sequence of temporary, single-use variables. Sorry, but...that's the job? If naming things is too hard and tedious, you don't have to do it, I guess, but you've chosen a path of programming where you don't care about readability and maintainability of the codebase into the future. I don't think the pipe operator magically rescues the readability of code of this nature. The tedium of coming up with a name is a forcing function for the author's brain to think about what this thing really represents. It clarifies for future readers what to expect this data to be. It lets your brain forget about the implementation of the logic that came up with the variable, so as you continue reading through the rest of the code your brain has a placeholder for the idea of "the envVar string" and can reason about how to treat it. The proposal continues: > If naming is one of the most difficult tasks in programming, then programmers will inevitably avoid naming variables when they perceive their benefit to be relatively small. Programmers who perceive the benefit of naming variables to be relatively small need to be taught the value of a good name, and the danger of not having a good name, not given a new bit of syntax to help them avoid the naming process altogether. The aphorism "There are two hard problems in computer science: cache invalidation, and naming things." is not an argument to never cache and never name things. That's mostly what we software folks spend our time doing, in one way or another.
- greggman3 4y agoand yet looking through code from the place you work I see something like this let field = ve.instanceContext.replace(/(#\/)|(#)/ig, "").replace(/\//g, ".") Which you apparently claim should be const fieldWithHashMarksUnesacped = ve.instanceContext.replace(/(#\/)|(#)/ig, ""); const field = fieldWithHashMarksUnesacped.replace(/\//g, ".") https://github.com/mirusresearch/firehoser/blob/46e4b0cab9a2adf775fd438c57f217d40fef6102/firehoser.js#L205 https://github.com/mirusresearch/firehoser/blob/46e4b0cab9a2... and this return moment(input).utc().format('YYYY-MM-DD HH:mm:ss') Which apparently you believe should be const inputAsMoment = moment(input); const inputConvertedToUTC = inputAsMoment.utc() return inputConvertedToUTC.format('YYYY-MM-DD HH:mm:ss')
- elpool2 4y agoThe version with temp variables is also easier to debug.
- dgb23 4y agoMy JS code looks exactly like you describe. Just a bunch of const (rarely let) statements with descriptive, short names. It's not tedious at all, just a little verbose. But JS is already a language that is relatively compact so it doesn't really matter.
- pier25 4y agoI agree. I'm afraid these pipe operators will become like ternaries and will tend to produce "smart" lines of code which are difficult to parse at first glance. Temporary variables are great for writing obvious code which is trivial to parse when reading.
- ed_balls 4y agoQuite often I rewrite the code from ``` return validate(get_response(value)) ``` or ``` value = get_response(value) value = validate(value) return value ``` into ``` res = get_response(value) new_res = validate(res) return new_res ``` Why? Easier to read and when Sentry throws an error I have each value from the call stack. Much easer to debug. In the example 2 you can accidentally move a line and not notice the error.
- zelphirkalt 4y agoI think that depends on the context. Are all intermediate results of the application of multiple procedures relevant and need a name? Or are we only interested in the result after applying all the procedures? Why polute our namespace with names, which are never again used, except for the next step of the pipeline? Then in other cases one does need some intermediate results.
- rkagerer 4y agoThank you. I often find flow-crutches like the one described in this proposal more confusing to decipher than plain old fashioned, well thought out code. Lambda (=>) expressions in C# and closures in JavaScript are others I sometimes find myself pausing at to make sure I'm interpreting correctly. I always figured it's just because I'm an older programmer and haven't used the new language features enough for them to become intuitive. I do acknowledge there are use cases where they're a perfect fit for the pattern in which you're coding. But I feel like they're too-often taken as a shortcut to dump a bunch of operations in one place when it would be more readable to structure into well-organized functions that logically group concerns. It's not that I don't like syntactic sugar to make code more concise, I just think languages need to remain judicious about how many different ways they dole out to accomplish the same task before they start to risk 'rotting their teeth'. Gotta keep striving for elegance - as you renovate over time it can get harder to keep the bar high.