For me, the biggest difference between subprograms and external subroutines is the external subroutine shares the global data are with the calling module, whereas the subprogram has its own global data space.
Additionally, subprograms must be called using a CALLNAT statement, limiting the way it is referenced in code to 8 characters whereas the external subroutine and function can be more characters (I believe 32). I tend to use functions when I want to use results directly within commands. For example, I have a large number of functions that allow passing of parameters and returning an XML string. I can use this function as:
WRITE WORK FILE 1 VARIABLE
FN#XMLROW(<#PARAMETERS>)
FN#XMLCELL(<#PARAMETERS>)
FN#XMLROW(<#PARAMETERS>)
Whereas with a subprogram or external subroutine, I would need to do something like the following
CALLNAT 'XMLROW' #PARAMETERS #RESULTS
WRITE WORK FILE 1 VARIABLE #RESULTS
CALLNAT 'XMLCELL' #PARAMETERS #RESULTS
WRITE WORK FILE 1 VARIABLE #RESULTS
CALLNAT 'XMLROW' #PARAMETERS #RESULTS
WRITE WORK FILE 1 VARIABLE #RESULTS