I have been making it standard practice for some time to always block read, parse the input table to variables, then do the logic to the output internal variables, load the output tables, then block write outputs to the racks. Of course depending on the strategy, you can do all this with tables alone and still keep the strategy clean and easy read.
Another way to deal with getting and writing the IO is to do write by exception. I just came up with this method:
block read the inputs and outputs to an input table, then parse all the inputs to "like" named input variables (not to the outputs), then write to "like" named output variables in the logic as the logic requires. At the end of your logic do this for each output you need to write:
if(Rack1_fTable <> OutputVar0_dout)then
Rack1_fTable = OutputVar0_do;
The idea is since you haven't written to the input table in the logic, it still has the latest states of the output IO points, therefore you can use it to reference whether or not you need to write to that point. You do still have to create all these output variables, but you can also use a separate table for the outputs and use a table to table copy for the output variables if you wish. This way your logic isn't cluttered up with additional statements through the logic, you can just write to the internal output variables, then at the end, all in one place, you do the exception writes to the rack.
As most of you know, in most strategies the outputs are not actually required to written because they rarely change relative to the number of times they get read. As a result, the strategy may well run faster than doing block writes.
Also, not to be overlooked, one problem with output block writes, is the fact that you cannot use output features because it will get overwritten by the block writes. This method allows you to use output features.