I'm mentoring a new developer at my firm. He's fresh out of college. His code works on a basic level. The things he's stubbed his toes on:
* Naming conventions. We have probably more rules about this than some, but things like branch and commit names matter because we tie them into our issue tracking process.
* Strictly reading specifications. We had a couple days rework because he used a different suggested name for something, and it ended up propagating into dozens of class names.
* Knowing when and what can be cleaned up. This I can forgive, as it normally waits towards the end of the project and he isn't quite there yet, but when we paired to work on it, there was a lot of leftover baggage.
* Bulletproofing/exhaustive coverage. I suspect there's a lot of university projects where "what if the remote server hands us HTTP 418" is answered by "the test service doesn't".
* Multiplayer and advanced Git. "The main branch is going to update without you, and eventually there's going to be merge conflicts" and you'll need to merge/rebase was a problem for him, as was dealing with a feature branch with multiple task sub-branches (keeping too many of them open at once is a huge risk for weird merge conflicts and hideous histories when they're finally resolved).
The non-tech skills of how commercial software development actually works in an actual organisation are really important, and the only way of learning them is on the job.
You sorta can.
https://missing.csail.mit.edu/
I've also met grads that basically had a dedicated software engineering class where they learned: What's a package manager, build system, how to compile C++ code (linking and compilation), makefiles, agile, waterfall and source control and a few quality metrics to look out for.