In Bash, when to alias, when to script, and when to write a function?
When to write a script ...
Scripts assemble software components (aka. tools, commands, processes, executables, programs) into more complex components, which may themselves be assembled into still more complex components.
Scripts are usually made executable so they can be called by name. When called, a new subprocess is spawned for the script to run in. Copies of any exported variables and/or functions are passed by value to the script. Changes to those variables do not propagate back to the parent script.
Scripts may also be loaded(sourced) as if they were part of the calling script. This is analogous to what some other languages call "import" or "include". When sourced, they execute within the existing process. No subprocess is spawned.
When to write a function ...
Functions are effectively pre-loaded shell scripts. They perform a bit better than calling a separate script, but only if it must be read from mechanical disk. Today's proliferation of flashdrives, SSDs and Linux's normal caching in unused RAM make that improvement largely unmeasurable.
Functions serve as bash's principle means of achieving modularity, encapsulation and reuse. They improve the clarity, reliability and maintainability of scripts.
The syntax rules for calling a function are identical to that of calling an executable. A function with the same name as an executable would be invoked instead of the executable.
Functions are local to the script they are in. They are invisible to the process that calls that script (e.g. commandline, another script or a program).
Functions may be exported (copied by value) so they can be used inside called scripts. Thus, functions only propagate to child processes, never parents.
Functions create reusable commands that are often assembled into libraries (a script with only function definitions) to be sourced by other scripts.