News for hackers. Stuff that matters.
Re:Avoid Else, Return Early (2013) by monocasa on Monday March 26, 2018 @10:20AM (#16679070)
That's one of the reasons I love RAII; all resources, memory and otherwise, are treated the same.
Re:Avoid Else, Return Early (2013) by weinzierl on Monday March 26, 2018 @10:39AM (#16679210)
That‘s what I was thinking when writing my edit. The somewhat ironic thing is that C++ people could use early exits safely, but often don’t, while Java folks typically write early exit code when they really shouldn’t.
Re:Avoid Else, Return Early (2013) by jasonmaydie on Monday March 26, 2018 @10:22AM (#16679093)
it's not just about in app resources. This could also affect external resources.. like not cleaning up temporary files because a future maintainer returned early and left some critical data behind.
Re:Avoid Else, Return Early (2013) by klmr on Monday March 26, 2018 @10:27AM (#16679132)
RAII can handle such resources, and good use of RAII does handle such resources. Languages without time-deterministic GC even tend to add extra language constructs to aid this, such as `using` in C# and Java (7?) with its new `try` block.
Re:Avoid Else, Return Early (2013) by jstimpfle on Monday March 26, 2018 @11:32AM (#16679617)
Downside is, now your cleanup code is spilled all over the codebase. And where it's implemented it lacks often the necessary context (from the location of use). So, it's often wrong or incomplete, or suffers from the type-for-single-usage syndrome.

Yes, RAII works for the casual std::vector, but it's not a maintainable solution for general resources.

Re:Avoid Else, Return Early (2013) by monocasa on Monday March 26, 2018 @11:57AM (#16679805)
It's right next to the create code, not 'spilled all over the codebase'. And if you really want different behavior on destruction (which is _really_ rare IMO), you can pass a destruction strategy at object construction. If you don't know how you want to destroy something when you construct it, you need to take a step back and reexamine your architecture.
Re:Avoid Else, Return Early (2013) by Too on Monday March 26, 2018 @12:10PM (#16679920)
True, for those who don't agree, read about rule-of-zero for some expansions on this. If you have to write the same type of clean up code in multiple destructors you are doing it wrong, wrap that resource in a class that has the responsibility of managing that type of resource and forget about the destructors elsewhere.
Re:Avoid Else, Return Early (2013) by jstimpfle on Monday March 26, 2018 @04:29PM (#16682265)
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 (ripping them out of context) makes things just harder to understand. Better just make them global data, maybe even define the initialization/cleanup routines for that global data in-line with the rest of the control flow.
Re:Avoid Else, Return Early (2013) by monocasa on Monday March 26, 2018 @04:39PM (#16682368)
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. Even though we were totally async and didn't rely on the stack for context lifetimes.

Re:Avoid Else, Return Early (2013) by jstimpfle on Monday March 26, 2018 @05:31PM (#16682818)
> 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) by monocasa on Monday March 26, 2018 @05:45PM (#16682916)
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.