Contrary to popular belief, formal education wasn't useless here. All the foundational knowledge was covered in depth in my mandatory CS undergrad networking class. So this is a neat quick guide to all the stuff CS graduates already have learned once about but might've forgotten the details or don't know the hands on code.
I think there is (or was, depending on the institution) a disconnect between the curriculum and what skills students needed. For context, I was a tutor, instructional assistant, adjunct professor, and finally a curriculum advisor for the Los Rios Community College system and the University of California Davis Extension.
First, CS programs that went 100% into Java did not age well and most of these courses were taught in a way that led students on to believe this stuff was static and won’t really improve. The concept of new languages beyond what was available in circa 2006 was unimaginable.
Another quirk that a Java-centric education brought on was that low-level courses were often taught in Java and you ended up writing all your data structures coursework in Java taught by someone with a C background. But you couldn’t use C or anything sensible for this because universities promised students would know object oriented programming. This created a lot of disconnect and meaningless ritual around a paradigm that did not fit the language.
CS programs that succeeded understood that a foundational knowledge coupled with language flexibility. They had to understand that the specific languages did not matter so much, rather it should fit the paradigm and principles of the context in which it was written. Once students are able to think in terms of computer procedures, instructors can leverage this knowledge to introduce abstractions and a grand unification principle.