What I do is feed the card/module I/O tags into different AOIs at the controller scope that are named after the print tags into a IO buffering task, organized by type of module (local, remote, drives, valve banks, etc) and then instance (communication module, singular drive, etc). These handle on/off delays, device interlocks, manual modes, forces, simulation, scaling/signal conditioning if necessary, etc, and of course also buffer the I/O.
Then I alias the AOI to a program tag with a descriptive name (ie. TankOutletPump in program Tank100). I link the alias tags to the HMI and not the base buffering AOI, so I don't have to hunt around the program to remember which valve number is where and does what.
This way, you have descriptive names for the aliased tags and can also cross-reference with the electrical prints if necessary using the base tag. I can also use an Excel macro to generate the first layer and when reusing programs I just have to reassign the aliased tags to new I/O.
Also, if an I/O point does fail, you can just change the I/O tag inside the AOI. No download is necessary in the immediate. You can even rename the AOI tag online and the alias address on the alias tag follows, so no download may be necessary ever, but I'd have to check if you can still do that when an HMI is actively RWing into the alias tag.
It's a bit heavyset but works for me.