I use subroutines in all by AB programs.
The main program is just a list of calls for the subs.
I group code by subroutine for easy trouble shooting later.
ie. all code for machine 1 is in a subroutine for machine 1
all code for machine 2 in in a subroutine for machine 2
You can also have each subroutine index a counter upon completion, then the counter value will help you know where you are at in the program if problems occur.
You may want to consider using subroutines to minimise duplication of code. You can call the subroutine multiple time is one scan. Coupled with indirect addressing it can vastly reduce the amount of ladder but be careful it can be a nightmare to debug!
We also use subroutines to minimize the duplication of code and for operation specific. They can be very useful for putting certain operations aside from the rest of the code.
ex. Each station watches for a fault. When a fault is encountered a subroutine is executed. The subroutine sorts out the fault possibly using an offset for station identification for display on a panelview.
Remember that on fixed and SLC 5/01's you can only nest 4 subs deep and on 5/02, 03, 04's you can nest 8 subs deep. (Unsure about 5/05)
Ex. main prog (file 2) executes #1 sub and it executes #2 sub and it executes #3 sub etc. You must return in the same order. Returning = #3 to #2 to #1 and back to file 2 (main prog).
As you see it can become very difficult. But if used properly the Subroutine can be a great asset.