Content deleted Content added
→top: wording, link |
merge RAII discussion, clarify what is OO |
||
Line 54:
The above techniques – unwind protection (<code>finally</code>) and some form of encapsulation – are the most common approach to resource management, found in various forms in C#, [[Common Lisp]], Java, Python, Ruby, and [[Scheme (programming language)|Scheme]], among others; they date to the late 1970s in the NIL dialect of Lisp; see [[#History|history]]. There are many variations in the implementation, and there are also significantly different [[#Approaches|approaches]].
== Approaches ==
=== Unwind protection ===
The most common approach to resource management across languages is to use
An alternative, more imperative approach, is to write asynchronous code in [[direct style]]: acquire a resource, and then in the next line have a ''deferred'' release, which is called when the scope is exited – synchronous acquisition followed by asynchronous release. This originated in C++ as the ScopeGuard class, by [[Andrei Alexandrescu]] and Petru Marginean in 2000,
<ref>"[http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 Generic: Change the Way You Write Exception-Safe Code — Forever]", by [[Andrei Alexandrescu]] and Petru Marginean, December 01, 2000, ''Dr. Dobb's''</ref> with improvements by Joshua Lehrer,<ref>[http://jlehrer.privatedns.org:8000/scopeguard.html ScopeGuard 2.0], Joshua Lehrer</ref> and has direct language support in D via the <code>scope</code> keyword ([http://dlang.org/statement.html#ScopeGuardStatement ScopeGuardStatement]), where it is one approach to [[exception safety]], in addition to RAII (see below).<ref>D: [http://dlang.org/exception-safe.html Exception Safety]</ref> It has also been included in Go, as the <code>[http://golang.org/ref/spec#Defer_statements defer]</code> statement.<ref>[http://blog.golang.org/defer-panic-and-recover Defer, Panic, and Recover], Andrew Gerrand, ''The Go Blog,'' 4 August 2010</ref> This approach lacks encapsulation – one must explicitly match acquisition and release – but avoids having to create an object for each resource (code-wise, avoid writing a class for each type of resource).
=== Object-oriented programming ===
In C++, the usual approach to resource management is [[Resource Acquisition Is Initialization]] (RAII), which ties resource management to the lifetime of an object. This has the advantage that it can also be used for heap-managed resources.
The compositional properties of RAII, however, differ significantly from scope bound resources in that it allows for full [[Encapsulation (object-oriented programming)|encapsulation]] of the resources behind an abstraction. With the dispose pattern for resource management, "being a resource" becomes a property that is [[transitive relation|transitive]] to composition. That is, any object that is composed using a resource that requires resource management effectively itself becomes a resource that requires resource management.▼
This limitation is typically encountered whenever developing custom classes. Custom classes in C# and Java have to explicitly implement the <code>dispose</code> method in order to be dispose-compatible for the client code. The <code>dispose</code> method has to contain explicit closing of all child resources belonging to the class. This limitation does not exist in C++ with RAII, where the destructor of custom classes automatically destructs all child resources recursively without requiring any explicit code.▼
=== Structured programming ===
In [[structured programming]], stack resource management is done simply by nesting code sufficiently to handle all cases. This requires only a single return at the end of the code, and can result in heavily nested code if many resources must be acquired, which is considered an [[anti-pattern]] by some – the ''[http://c2.com/cgi/wiki?ArrowAntiPattern Arrow Anti Pattern],''<ref>[http://blog.codinghorror.com/flattening-arrow-code/ Flattening Arrow Code], Jeff Atwood, 10 Jan 2006</ref> due to the triangular shape from the successive nesting.
=== Cleanup clause ===
One other approach, which allows early return but consolidates cleanup in one place, is to have a single exit return of a function, preceded by cleanup code, and to use [[goto]] to jump to the cleanup before exit. This is infrequently seen in modern code, but occurs in some uses of C.
▲Many garbage-collected languages, including [[Java (programming language)|Java]], [[C Sharp (programming language)|C#]] and [[Python (programming language)|Python]], support various forms of the [[dispose pattern]] to simplify cleanup of resources. This results in simpler code and can serve as an alternative to RAII for "shallow" resources.
▲The compositional properties of RAII, however, differ significantly from scope bound resources in that it allows for full [[Encapsulation (object-oriented programming)|encapsulation]] of the resources behind an abstraction. With the dispose pattern for resource management, "being a resource" becomes a property that is [[transitive relation|transitive]] to composition. That is, any object that is composed using a resource that requires resource management effectively itself becomes a resource that requires resource management.
▲This limitation is typically encountered whenever developing custom classes. Custom classes in C# and Java have to explicitly implement the <code>dispose</code> method in order to be dispose-compatible for the client code. The <code>dispose</code> method has to contain explicit closing of all child resources belonging to the class. This limitation does not exist in C++ with RAII, where the destructor of custom classes automatically destructs all child resources recursively without requiring any explicit code.
==See also==
|