Hacker News new | ask | show | jobs
by pjmlp 382 days ago
One caveat though, you need to pair those with static analysis tooling, if you want to ensure developers don't forget to make use of them.
2 comments

I agree, this is a real benefit of RAII compared to defer. That said, there are disadvantages of making the resource freeing part invisible. Not having to debug destructors that do network IO (e.g. closing a buffered writer that writes to the other side of the world) or expensive computation (e.g. buffered IO writing to a compressor) is a define plus. Don’t get me started on error handling…
> I agree, this is a real benefit of RAII compared to defer. That said, there are disadvantages of making the resource freeing part invisible.

RAII doesn't make resource freeing invisible. It makes it obvious, deterministic, and predictable. The runtime guarantees that, barring an abnormal program termination that's not handled well, your resource deallocation will take place. This behavior is not optional, or requires specifying ad-hoc blocks or sections.

How does RAII solve that? Developers can "forget" to use RAII, right? Or are you saying that it's easier to spot because RAII requires quite a bunch of boilerplate (whereas a one-liner like "defer" is easier to forget)?

Not criticising, really trying to understand :-).

RAII when supported natively by the language, is done at the implementation level, not the usage point.

So in languages like Rust, D, Ada, Swift, C++, the compiler will do the rest unless you go out of your way to avoid the call to take place, like placing a value type on the heap using plain pointers.

With the other approach, even if you implement IDisposable, AutoCloseable, ContextManager and similar, you have to remember to manually write the code pattern that takes care of calling close(), or whatever the method/function happens to be called.

In languages with good support for FP patterns, like trailing lambdas, currying and such, there is another pattern, that is much safer, in case you don't want a static analysis tool to track resource usage, the with pattern.

You do something like withDBConnection connection (fun db -> all related db operations).

Assuming the lambda doesn't do naughty things to have db parameter escape the scope, the withDBConnection function will take care of handling the whole connection lifecycle.