I've heard that "back in the day", the exit codes actually meant something. They were used to indicate whether or not a program had run successfully, or something like that.
The exit codes now seem a bit meaningless. Who cares if main() returns 0, 1, or 100? I can tell my program's working/not working just by running it. Further, if - while debugging - my program is forced to abort, I get a SIGABRT message and my IDE jumps to the point where my program aborts, allowing me to figure out what caused the abort.
Programs are often called by scripts, and that's where it matters.
Part of the UNIX philosophy is to create programs that do just one thing, then chain them together to do more useful stuff.
You're probably thinking of a monolithic program that does everything, and doesn't need to interact with the rest of the system beyond making library calls and doing some I/O.
The return value is still relevant when writing makefiles. A non-zero return value indicates that an error happened, and causes the build process to stop (i.e. the commands that follow are not executed).
If "back in the day" means right now, right here, then, yes, that return code did mean something back in the day.
It's incredibly naive of you to think that every possibly use of a computer program is one where a human being is watching to observe the behaviour of the program in real time. On your computer right now, there will be dozens - if not hundreds - of processes running that you know nothing about. How does the OS (or whatever else invoked those processes) know whether they've succeeded or failed? Yes, that's right - the exit code.
Do you honestly think the entirely of software usage, all over the world, is people watching programs looking for them to abort? What do you think people use computers for?