Understanding Handle
In computer programming, a handle is an abstract reference to a resource. This abstraction means there’s no specific way to define the underlying type of the reference—it could be a pointer, a reference, an array index, a string key in a hash map, or any other form. The actual type might be complex and lengthy, so it’s intentionally hidden behind a shorter alias. Libraries that utilise handles typically provide functions to interact with the resources these handles represent.
Why do you need a Handle?
If the handle is a simple abstraction, why do we need it in the first place? Can we replace it with a reference to the actual implementation? Can we expose the details of the implementation directly to the users? For most OSS applications, this implementation is accessible anyway.
In software development, the actual type of a handle and the class of the resource it references are implementation details that may change over time. If you know the exact type behind a handle, you might be tempted to perform specific or “hacky” operations. However, doing so can lead to your code breaking in the future if the implementation changes.
For example, let’s say there’s a class called File, and the true type of the handle file_handle is File* (a pointer to File), but it’s aliased as FileHandle. The File class has a method readData() that reads data from the file. There’s also a handle function provided: int read_file_data(FileHandle file_handle).
Ideally, you shouldn’t know that FileHandle is actually a File*. Even if you do, you should avoid accessing the method directly using file_handle->readData(), even though it might compile. If you rely on this direct access and later the handle’s type changes—for instance, from File* to an integer file descriptor or some other type—your code will break. This means you’d have to fix every instance where you’ve directly accessed file_handle->readData(), which could be a massive task if it’s used throughout your program.
To prevent this, always use the handle’s accompanying functions (like read_file_data) to interact with the resource. This way, your code remains stable and won’t be affected by changes in the underlying implementation.