Cover of The Pragmatic Programmer by Andrew Hunt, David Thomas - Business and Economics Book

From "The Pragmatic Programmer"

Author: Andrew Hunt, David Thomas
Publisher: Addison-Wesley Professional
Year: 1999
Category: Computers

🎧 Free Preview Complete

You've listened to your free 10-minute preview.
Sign up free to continue listening to the full summary.

🎧 Listen to Summary

Free 10-min Preview
0:00
Speed:
10:00 free remaining
Chapter 4: Pragmatic Paranoia
Key Insight 4 from this chapter

How to Balance Resources

Key Insight

Managing resources such as memory, transactions, network connections, files, and threads is a fundamental aspect of coding, typically following an allocate-use-deallocate pattern. A critical principle for consistent resource handling is 'Finish What You Start,' meaning the function or object responsible for allocating a resource should also be responsible for its deallocation. This prevents issues like resource leaks and tight coupling between different routines.

For example, in code that opens a file, reads data, updates it, and writes back, a refactoring based on 'Finish What You Start' would ensure the `update_customer` routine both opens and closes the file, passing the file reference to `read_customer` and `write_customer` as a parameter. This clearly balances resource usage. Many modern languages offer constructs like Ruby's `File.open` with a block, where the resource is automatically closed when the block exits, guaranteeing deallocation without manual intervention and reducing resource scope.

When dealing with multiple resources, deallocate them in the opposite order of allocation to prevent orphaned resources, and always allocate them in the same order across the codebase to reduce deadlock possibilities. In object-oriented languages, encapsulating resources within classes (using constructors for allocation and destructors/finalizers for deallocation) is beneficial, especially with exceptions. For exception handling, the correct pattern for deallocation is to allocate the resource *before* the `try` block, then `process` it within the `try` block, and `deallocate` it in a `finally` clause, to avoid trying to deallocate an unallocated resource if allocation itself fails. For dynamic data structures, establish semantic invariants that define responsibility for substructure deallocation (recursive deletion, or refusal to deallocate if substructures exist). Regularly checking resource balance with wrappers can confirm appropriate freeing.

📚 Continue Your Learning Journey — No Payment Required

Access the complete The Pragmatic Programmer summary with audio narration, key takeaways, and actionable insights from Andrew Hunt, David Thomas.