Live data from Hacker News

Avoid Else, Return Early (2013)

blog.timoxley.com

511–520 of 601 posts

Re: Avoid Else, Return Early (2013)

#511
post #252

Earlier quoted context omitted.

I used Python enough that braces are completely meaningless to me in languages with them (ie, everyone else). Indentation is my mental delineation of code blocks. I just have to write these {} things all over the place because every other language is a gramatically bloated mess. The advent of automatic code formatting (and Python pioneered this in many ways with pep8, but even huge C++ projects are realizing the valu…

> I just have to write these {} things all over the place because every other language is a gramatically bloated mess. In what way are context-free languages "a grammatically bloated mess?" Whitespace delimited languages like Python have context-sensitive grammars. Now that is a mess.

Most bracket languages aren't strictly context-free either (the Dangling else problem [1] alone somewhat guarantees that most programming languages are not strict, unambiguous CFGs in a mathematic sense). There's no right/wrong/superiority in context-free versus context-sensitive, they are tools in the toolbox and not really "levels in a superiority hierarchy".

[1] https://en.wikipedia.org/wiki/Dangling_else

Re: Avoid Else, Return Early (2013)

#512
post #106

Programmers with lots of hours of maintaining code eventually evolve to return early, sorting exit conditions at top and meat of the methods at the bottom. Same way you evolve out of one liners. Same way comments are extra weight that should only be in public or algorithm/need to know areas. Same way braces go on the end of the method/class name to reduce LOC. Same way you move on from heavy OO to dicts/lists. Same w…

> Same way braces go on the end of the method/class name to reduce LOC. Screw that. I've been writing code for 15 years, and Allman style braces make it so much easier to mentally parse code into blocks that they're worth every single LOC. I can't speak for anyone else but I'm not working on an 80x24 terminal anymore.

NoooOoooooOOOooooOOOooo! I hate Allman braces! My hatred burns with the fire of a thousand suns!

Re: Avoid Else, Return Early (2013)

#513
post #106

Programmers with lots of hours of maintaining code eventually evolve to return early, sorting exit conditions at top and meat of the methods at the bottom. Same way you evolve out of one liners. Same way comments are extra weight that should only be in public or algorithm/need to know areas. Same way braces go on the end of the method/class name to reduce LOC. Same way you move on from heavy OO to dicts/lists. Same w…

> Same way braces go on the end of the method/class name to reduce LOC. Screw that. I've been writing code for 15 years, and Allman style braces make it so much easier to mentally parse code into blocks that they're worth every single LOC. I can't speak for anyone else but I'm not working on an 80x24 terminal anymore.

> I'm not working on an 80x24 terminal anymore.

Even with 80x24 (don't ask), I fully agree with Allman style braces.

Re: Avoid Else, Return Early (2013)

#514

Earlier quoted context omitted.

And the create code is spilled over the codebase, just as well :-). It's not where actual work is done. This approach of encapsulating functionality in a class may work in some instances such as std::vector but more often than not it's just a lot of (typical OOP) boilerplate for things that you do only once in a codebase anyway. Giving one-off things a type and a name and decoupling them from normal control flow (rip…

I mean, having global resource managers is orthogonal to generating the events that cause resource destruction. And you're not 'ripping them out of context's, since the guard objects are still there where you would be doing the resource management manually. EDIT: and I was the lead for a high availability C++ RTOS. I know that not all patterns fit for writing quality, available code. This fits remarkably well though.…

> And you're not 'ripping them out of context's, since the guard objects are still there where you would be doing the resource management manually.

The guard object is there (e.g. "on the stack") but the destructor is not defined in-line but in a separate class method definition. Classes have always that implicit ideal of being "isolated". This is wishful thinking, of course. In the end all the parts of the code need to contribute to the program. That's why OOP codebases often end up as a terrible mess. Classes can't decide if they want to be isolated or involved. The compromise is all this terrible implicit state. (do you know the quote by Joe Armstrong about the banana, monkey and jungle?)

Re: Avoid Else, Return Early (2013)

#515
post #389

Earlier quoted context omitted.

In last 20+ years I've changed the coding style many times, usually to fit the current team style. And in my experience it takes a few weeks for the brain to rewire to the new style. First you hate it, and then you get used to it, and then you're like: wow it's great. Then you switch the standards for a new project and again, the same steps. It's just a matter of habit...

Just give me an opinionated ${LANG}fmt utility to do it for me so I don't have to care and don't have to waste time arguing with other zealots. Let the tool be the zealot.

> Just give me an opinionated ${LANG}fmt utility to do it for me so I don't have to care and don't have to waste time arguing with other zealots. Let the tool be the zealot.

So totally this. I despise indenting with tabs with a passion, but when I heard gofmt did that I was actually pleased. There's no arguing with the official formatting utility: https://golang.org/doc/effective_go.html#formatting

Re: Avoid Else, Return Early (2013)

#516
post #389

Earlier quoted context omitted.

In last 20+ years I've changed the coding style many times, usually to fit the current team style. And in my experience it takes a few weeks for the brain to rewire to the new style. First you hate it, and then you get used to it, and then you're like: wow it's great. Then you switch the standards for a new project and again, the same steps. It's just a matter of habit...

Just give me an opinionated ${LANG}fmt utility to do it for me so I don't have to care and don't have to waste time arguing with other zealots. Let the tool be the zealot.

This is exactly how I feel, as someone who has been coding for 22 years (professionally, closer to 32 if you count when I started hacking in BASIC and 6510 assembly on the C64).

I just defer to the code formatter. That way everything is consistent looking internally, which is all I care about. I couldn't care less whether the braces are on the same or a different line or other things like that outside of the fact that I do like internal consistency within projects.

All that aside, as soon as I saw the OP title I knew (via years of exposure to bikeshedding programmers) that this thread would end up having a ton of comments on it and wasn't surprised to see it was up to 500-something and still rapidly climbing.

Re: Avoid Else, Return Early (2013)

#517
post #482

Earlier quoted context omitted.

This is my favorite research quote from a Civilization game (Civ IV, narrated by Leonard Nimoy). I use this as my mantra for all design-oriented aspects of my life now. Or... I try to. Sometimes it's hard not to want to add more haha.

FYI that quote is from Antoine de Saint-Exupry, author (and pilot) famous for "The Little Prince".

Do you know what the context of that quote is? I have used it as a sort of mantra specifically when programming, but I'm guessing it probably was intended for writing.

Re: Avoid Else, Return Early (2013)

#518

Earlier quoted context omitted.

Sure, but allocating resources on the stack is not good for maintainability. Software is easier to understand if its state is not hidden in semi-permanent call stack frames.

In general I agree with you, but that seems orthogonal to the subject at hand.

Parent's statement was that early returns are hard because you need to cleanup allocated resources. I don't think so, because there shouldn't (usually) be resources "on the stack".

Re: Avoid Else, Return Early (2013)

#519
post #338

Earlier quoted context omitted.

`finally`/RAII doesn’t depend on checked exceptions. It always runs (short of something that aborts the program without unwinding the call stack; and in those cases single-exit won’t save you).

Mixing finally and RAII into the same category doesn't really make sense here. And I'm not saying that finally depends on checked exceptions, I'm saying that pattern is very brittle. You change lower code to throw a new exception, and you change the above code to catch it like you're supposed to, but now the middle code has no idea that there's this new exception and leaks resources. So you end up either having britt…

I find it a good rule of thumb to allocate and deallocate a resource at the same level in my design, and to maintain any associated handle at that level as well. I have encountered few situations where this didn’t work well, and almost all of them arose because an external module introduced some form of unavoidable asymmetry at its interface.

If you’re able to follow that pattern then safe handling of unusual control flows tends to follow naturally. You just adopt whatever mechanism your language provides for scheduling the code to clean up and release resources at the same time as you allocate those resources. Almost all mainstream languages at a higher level than C provide a suitable mechanism today: RAII, some variation of `with` or `using` block, try-finally, Lispy macros, Haskelly monad infrastructure, etc.

That way, the only places you need to write any extra logic are the layers where you allocate/deallocate and possibly lower layers that manage side effects on those resources in the unusual case that they require a specific form of recovery beyond the default behaviour in the event of aborting early.

Hopefully if you do have to work at low level like C or assembly language and you’re using forms of control flow that could bypass clean-up logic then you already have at least some coding standards established for how to manage resources safely as well.

Re: Avoid Else, Return Early (2013)

#520

Earlier quoted context omitted.

I mean, having global resource managers is orthogonal to generating the events that cause resource destruction. And you're not 'ripping them out of context's, since the guard objects are still there where you would be doing the resource management manually. EDIT: and I was the lead for a high availability C++ RTOS. I know that not all patterns fit for writing quality, available code. This fits remarkably well though.…

> And you're not 'ripping them out of context's, since the guard objects are still there where you would be doing the resource management manually. The guard object is there (e.g. "on the stack") but the destructor is not defined in-line but in a separate class method definition. Classes have always that implicit ideal of being "isolated". This is wishful thinking, of course. In the end all the parts of the code need…

Guard objects dont have to be on the stack. They work beautifully inside a context object that's registered with global manager if you're in an async codebase. std::move is a glourious thing.
Post reply on HN