When designing APIs, create appropriate abstractions that hide platform-specific or low-level implementation details from consuming code. Avoid exposing raw interfaces outside their designated modules and minimize unnecessary dependencies.

Good Practice:

For example, instead of binding to an unused protocol:

// AVOID: Unnecessary binding that adds dependencies
if (registryBind(
    xdg.WmDialogV1,
    registry,
    global,
)) |wm_dialog| {
    context.xdg_wm_dialog = wm_dialog;
    return;
}

Instead, simply check if the protocol is available without binding:

// BETTER: Just compare against the name and set a flag
if (isProtocolSupported(registry, global, "xdg_wm_dialog")) {
    context.has_wm_dialog_support = true;
    return;
}

Similarly, avoid using raw C interfaces outside their dedicated modules. Create proper abstractions that isolate platform-specific details, making the codebase more maintainable and portable.