This is fantastic and surprisingly close to how I tended to explain computer science to students and graduates:
In Computer Science, there are 3 kinds of problems:
1. The problems that Math gives you: algorithms, data structures. These are the problems you think you're going to solve and sometimes you do, but often we just need a few really smart programmers to solve this and the rest of us can just use those solutions.
2. The problems that Physics gives you: hardware, device drivers, network latency. Sometimes you do systems programming and work close to the hardware. But once again, once one engineer has solved this, most of the time we can just use those solutions.
3. The problems that other engineers give you.
And that is where you're likely to spend most of your time: gluing APIs together, reading code and documentation, and arguing about code formatting.
This is why in so many ways computer science is a social science. Certainly "software engineering" is. Everything you do is going to be about communication. When you write code, you're not just communicating with the compiler and the machine, you're communicating with other engineers. You're going have to craft smart documents, emails and collaborate. Any nontrivial solution will require these skills, so you better start investing in them.
I'm continually surprised at how quickly non-technical problems come to dominate my time on a software project. E.g. my code doesn't work because two business stakeholders have slightly different, irreconcilable notions of what a "customer" is and it has to satisfy both.
Or things as mundane as discover that a third of your coworkers (even seniors) are so much emotion driven that may as well go back to high school in order to learn how to socialize and be professional avoiding jealousy, envy, unnecessary competence or just plainly learn how to work in team and how to follow some sort of structure in an organization.
What I speak is about individuals trying to compete against its own team to defeat them in some unnecessary priority rather than collaborate and play all together.
Makers who don’t understand 1 or 2 often create slow or insecure code that often results in clear user impact.
For example, I’ve seen diffing / recomputation code operating in O(n^3) or O(n^2) where O(n) or O(1) is possible and necessary for reasonable performance. I’ve also seen extremely poor use of network requests (multiple serial requests) that happen because the developer doesn’t understand network latency and networking performance (in this case with a single data center in the world).
In practice, a great engineer should be relatively well balanced in all 3 aspects and know when to favour one over another (such as the time sensitive case where performance in the code execution is more important than writing something that the next engineer can easily understand).
The number of times I’ve seen this sentiment end in a project being late or never ship is easily 10x more than the number of times a project became crippled later because of performance issues.
Improving performance isn't the only way you can make something "better". A system could be architected in a fragile or rigid way that makes extending it or adding new features extremely difficult without a rewrite.
I can't tell you how many times I've seen people "make it work" and create a mess that has to be rewritten later with much greater difficulty than if even the slightest amount of forethought had been given before hand.
I like to remind largely junior engineers I work with that we're basically Dell. We're system integrators. We take the bits that other people have made and glue them together in a fancy box. If they start doing computer science they need to stop for a second and ask themselves if they're really sure they should be doing computer science in case someone else already has and they can just leverage what they've done.
The focus for me is really building appropriate abstractions over the work I do so that people can focus on improving only the vertical slice they need to.
I like this. It's in the same vein as the blog post, but it addresses the only aspect I was truly uncomfortable with: the word "tribe" implies exclusivity, whereas I tend to think of myself and other devs as points in the triangle whose vertices are these tribes.
Computer science and math is useful beyond just algorithms and data structures. Understanding the mathematics behind program construction would allow more programmers to write composable code and more general, re-usable, less ad-hoc APIs; and do a better job of gluing existing components together.
I agree with your three problems, but only if problems means hard roadblocks to achieving your goal.
Much of programming is encoding what you want to computer to achieve and is therefore a rather long process, but not necessarily hard. Precisely specifying how a GUI should look has a substantial amount of necessary complexity, and writing that out doesn't fall into 1, 2 or 3.
You could also argue that that is a separate thing from programming. I don't at all mean to be to be snobbish here, just that it's useful to draw the line somewhere between there. Modeling is not programming. Architecture is not really, either, even if the process can involve programming.
I'm totally stealing this for teaching to my grad students, it's a much better way of stating what I try to stumble through each semester talking about "programming as communication"!
I'm not sure where this fits into your three problems but I spend most of my time thinking about problems that business gives me. Of course, this still underscores your point about social science.
In Computer Science, there are 3 kinds of problems:
1. The problems that Math gives you: algorithms, data structures. These are the problems you think you're going to solve and sometimes you do, but often we just need a few really smart programmers to solve this and the rest of us can just use those solutions.
2. The problems that Physics gives you: hardware, device drivers, network latency. Sometimes you do systems programming and work close to the hardware. But once again, once one engineer has solved this, most of the time we can just use those solutions.
3. The problems that other engineers give you.
And that is where you're likely to spend most of your time: gluing APIs together, reading code and documentation, and arguing about code formatting.
This is why in so many ways computer science is a social science. Certainly "software engineering" is. Everything you do is going to be about communication. When you write code, you're not just communicating with the compiler and the machine, you're communicating with other engineers. You're going have to craft smart documents, emails and collaborate. Any nontrivial solution will require these skills, so you better start investing in them.