Constructing valid experiments in software development is incredibly easy. Add an assert, recompile, and see if it gets triggered.
We programmers consider it unacceptably painful if testing a hypothesis takes ten minutes.
Real life is never that clean or easy.
That's a sign something is wrong.
Even for that, though, if you define your criteria for success, it's mostly possible to measure the outcomes and learn whether your approach was successful or not. One key there is remembering that subjective metrics are valid - user happiness and developer happiness are two of the most useful ones I know of for measuring the system's overall health and effectiveness, and while they're not objective, they can still be measured reasonably quickly and regularly.
For fields like public policy, though, there are just so many confounding factors and the timeframes are so long that it becomes nightmarish, maybe even impossible, to genuinely learn anything. The subjective metrics of citizen happiness and functionary happiness that are analogous to my software ones above are worthless because of rollout times measured in years or decades and the infinite array of factors, confounding and otherwise, that go into people's satisfaction with society.
Even relatively straightforward things like farming have learning cycles measured in years for things like crop rotations.
The universe is just not a friendly learning environment.
Programming is an aberration in almost every respect, as a product of the human mind that can actually have useful impacts in the world (most friendly environments are human constructs that are not "useful" per se, like board games or musical performance or sports).
Coding is something you can learn on your own with a tool, some books or manuals, and time. The compiler provides a lot of feedback, debuggers and manuals give you a lot of information to develop your skillset. A few books on algorithms and data structures and specific domains (like graphics or network) will get you to a solid point as a programmer.
But developing systems that are high quality, multi-component, interacting with other complex systems, and sustainable is another thing altogether. It is costly, tradeoffs are sometimes non-intuitive, and you probably need to have a mentor or a good work environment to really get skilled at it, or the right kind of analytical mind. But you'll still have a lot of failures along the way and need to develop a lot of different skills.
Usually you get feedback within 1/2 a year. That complicated search system with your own fantastic DSL an absolute nightmare to modify? Kind feedback. Your system works fine with 100 users but falls over with 10,000? Kind feedback. You used a trendy new js framework that disappeared 2 years later? Kind feedback.
And better still our industry has tons of people who write lots of books or do podcasts or do conferences where they talk about how their projects went wrong, and how they fixed them. Whether it was the GoF design patterns, or Code Complete or one of the many others.
To me, all of that is clearly kind feedback.
In fact, if you choose one strongly typed language and one weakly typed to know in depth (eg Java and JS) it's really easy to move to others.
The trap that people fall into is that they focus too much on learning the ins and outs of a framework and not the important concepts. Or they are stuck in a problem domain that's very thin on CS concepts, like web dev or frontend dev. You don't learn concepts that make it easy to transition.
From my own experience, focusing on CS and math (esp. stats) and systems programming have made it really easy to move around.
Like before things like generics and lambda expressions C#/Java were quite different to Python/Ruby, and js used to be quite an abysmal language but with some nice features nothing else had (still is an awful language to an extent). I think C# 2.0 and 3.5 really changed that language for the better, Java spent a lot of time getting to the C# 3.5 level.
And I remember a time when C++ was almost incomprehensible if you'd never worked in it, but now it seems to be a lot less daunting as you've got bridging languages like Rust and Go.
I must admit I've still no interest in Haskell/F#/etc. I tried Lisp about 10 years ago and it just seemed such a pain, for me I find imperative programming so much easier to map out complex interactions in my head. I also find set based programming like SQL very easy. But functional, ugh.
For multithreading, I would take functional over imperative any day though. The multithreaded code I write in Java ends up looking like functional code by way of chaining futures, but it is still hindered by the use of shared memory and synchronization (or lack thereof).
I enjoy C++, and the additions in C++ 11 and 14 are mostly good ones. But they don't do anything to make the language more approachable IMO.