When learning how to become a software developer, there is often an almost laser focus on learning languages and technology. Somehow, despite all the professional programmers developing ever more complex software, the way we teach those wishing to become software developers is utterly consumed by the obsession of teaching the tool rather than how to properly apply that knowledge for the purpose of developing software.
Programming languages are tools, you use them to create software and much like the tools used to create a car, they're not much use unless you know how to actually create a car. But this is how software development is often taught.
There is absolutely a recognition that teaching the tool alone is not enough and as such programming paradigms are taught alongside their applicable languages, universities often start off with Java and Object Oriented Programming, online courses do much the same, they define the features and structures of programming languages in the context of their applicable paradigms. But this is nowhere near far enough, this means very little to beginners, programming paradigms are essential but still too low level to be used as a way to teach software design and architecture. A programming paradigm teaches patterns, best practices and conventions in how to use your language (tool), but not the higher level, overall design of a piece of software.
The same can be said for many other environments, courses which teach you languages such as C# will guide you towards creating that predefined product, which aims to teach you about the tools you're using. These courses absolutely have value, but not to those they are often targeted at: new software developers.
Where do I start?
You are new to software development, you will spend many, many, many hours going through courses, tutorials and workshops learning about all these languages and technologies, either via online courses, textbooks or at a formal academic institution such as a school, college or university.
But what happens when you are left alone, what happens when you are tasked with developing software all by yourself? What happens when you have to join in a team of developers who are all working on a single piece of software? You probably won't know where to start.
Suddenly it doesn't really matter that you know how to type in the right keywords, in the right order, in the right syntax for the language of your choice because you don't properly understand how to design software and as such you also struggle to understand software other people have produced.
If someone asked you to write code doing very specific functions in particular places in the code base, following conventions and guidelines they have provided, you could probably do it, you know the tools and have seen plenty of examples and the courses you've done have helped you understand how to write code (to a degree).
But software development is about your own ability to see a problem or an objective and understand how to solve that problem or reach that objective. In my scenario above, someone else has already done that for you, they figured out the solution which needed to be developed and how it needed to be written, they just asked you to do what is essentially not much more than data entry.
You may totally understand why the code is as it is, you may understand everything about the code and its place within the overall application, but had you been simply tasked to "add x functionality to this piece of software" you may have struggled. Where do I start? How do I know I'm doing it the right way? How do I work with other people's code? How do I ensure my code can be worked with by other people?
What are we lacking?
To begin this section, I'll start with one maybe or maybe not important point: I'm not posturing as an authority on software design. I'm just another sotware engineer providing their perspective on why many people struggle with learning how to develop software and why many employers complain about the lacking skills of graduates (and new people to their industry) in software development.
With that, I'm not going to sit here and tell you how to design software. I'd probably do a poor job even if I tried. My point here is that software development education often neglects a vitally important aspect of software development. Teaching how to design software is hard, much harder than teaching someone how to write code in a particular language or environment, but that's not an excuse to avoid it.
Even when software design is attempted to be taught, often the context for many design practices and conventions is not provided and thus immediately lost to the student. Many software design practices come out of the realities of developing software in a team of people and/or developing software that may need to be maintained or developed further in the future. Good software design is not just technical, it isn't just about how secure, reliable and efficient your code is, it's about how software developers work.
Reasoning for basic conventions and practices, such as folder and file layout, code abstraction and modularisation, when it's appropriate to apply these practices and when it is appropriate to stop, they're all too often missing from software dev education. These are small things which professional, experienced developers take for granted, but are numerous enough to overwhelm new developers and results in fewer successful developers and more lower quality software.
It's widely understood in software development education that programming is heavily logic based and it's understood by all programmers that problem solving is an essential skill, but education often fails to exercise a student's problem solving skills, often fails to provide an environment or scenario to force a student to engage in true problem solving and designing solutions out of those solved problems using software design conventions.
Software design must be taught as an equal to learning languages and technology, the two go hand-in-hand when teaching someone how to become a successful software developer who develops quality software.