A little OO goes a long way
A little OO goes a long way
Posted May 3, 2013 13:00 UTC (Fri) by jwakely (subscriber, #60262)In reply to: A little OO goes a long way by hummassa
Parent article: Go and Rust — objects without class
Also, you'll be writing the same code everywhere you want to clean up a resource of that type. Why repeat yourself, why not associate the cleanup code with the type and make it run automatically?
I'm baffled why any self-respecting programmer would want to duplicate all that cleanup logic in every finally block or why they'd question the advantage of destructors.
Python's with statement is the right idea, the object's scope is limited and its type has some predefined cleanup code that runs automatically when the scope ends. Bingo.
Posted May 3, 2013 14:18 UTC (Fri)
by ehiggs (subscriber, #90713)
[Link] (1 responses)
It's still not as good as Python's 'with' in my opinion because you have to be explicit about the cleanup call in Go and in Python it's not cluttering up the code (aside from the indent level).
Posted May 4, 2013 5:37 UTC (Sat)
by danieldk (subscriber, #27876)
[Link]
- It puts the burden on the programmer and not the type.
Posted May 3, 2013 15:53 UTC (Fri)
by hummassa (subscriber, #307)
[Link] (4 responses)
Posted May 4, 2013 5:45 UTC (Sat)
by danieldk (subscriber, #27876)
[Link] (3 responses)
If y() throws here in C++, writeLastBuffer() is never called either. I if you always want to write something, add it to close() or ~Resource().
Also, Java 7 has a nicer try-with-resources statement, like Python's with, for classes that implement AutoClosable:
Posted May 4, 2013 10:21 UTC (Sat)
by hummassa (subscriber, #307)
[Link]
Posted May 4, 2013 10:26 UTC (Sat)
by hummassa (subscriber, #307)
[Link]
You are right, of course. But using destructors you have a lot more chances that discovering that some code belong in an destructor and putting it there because in the client code the WriteLastBuffer thing sticks out like a sore thumb. :-D
Ah, and once you wrote it, all call sites are correct from now on.
Posted May 7, 2013 14:52 UTC (Tue)
by IkeTo (subscriber, #2122)
[Link]
C++ programmers are accustomed to a concept called RAII, Resource Acquisition is Initialization. So if they always want the last buffer written, they tend to write something like: Not to say that everybody like having to define a class for every cleanup, though. But with C++0x lambda expression, the above can easily be automated.
A little OO goes a long way
A little OO goes a long way
- defer only works when leaving the scope of the function calling it. A type's destructors are called when going out of any scope in C++, e.g. when an instance of a class is used as a (non-pointer) member variable.
Oh, the duplication is the least of the problems. A bigger one would be the combination of optimization by the programmer and external changes. So, the following code:A little OO goes a long way
try {
f = open(...)
f.x()
f.y()
if( z ) f.writeCheckSumAndLastBuffer() else f.writeLastBuffer()
} finally {
f.close()
}
generates a hidden bug when f.y(), that calls a w() function from an external library, starts seen some exception and the last buffer is not written. Bonus points if the "if(z)" thing was put by another programming, in the run of the normal maintenance of the program.
I don't see how that is a problem of try/finally. Consider this C++
A little OO goes a long way
{
Resource someResource(...);
resource.x();
resource.y(); // throws
resource.writeLastBuffer();
}
try (Resource r = new Resource(...)) {
// Do something with r...
}
A little OO goes a long way
A little OO goes a long way
A little OO goes a long way
Consider this C++
{
Resource someResource(...);
resource.x();
resource.y(); // throws
resource.writeLastBuffer();
}
class LastBufferWriter {
public:
LastBufferWriter(Resource resource): resource_(resource) {}
~LastBufferWriter() { resource_.writeLastBuffer(); }
private:
Resource resource_;
};
... {
Resource resource(...);
LastBufferWriter writer(resource);
// Anything below can throw or not throw, we don't care
resource.x();
resource.y();
}