* they are part of a big enough team that individual responsibility is removed
* they're not given enough time to produce good quality code
* the design came from someone without sufficient expertise, and the programmers "just built it"
* they did the best given the time they had
* it passed testing
* programmers are generally not empowered to make go/no-go decisions
* even if they did express concern they may not have been listened to
* any internal challenges on ethical grounds were probably kept quiet and worked around
Usually with this kind of incident there are multiple process and quality failures, not just "why did the programmers not do better"
I'm just speaking from the practical experience I have.
It's just that in static languages, you write unit tests more around business functionality. In dynamic ones you end up writing unit tests essentially for typing and stuff like that. And, you know, you have tooling so you can actually perform the refactorings at scale across the code base. Like real tools, that the rest of your team know how to use, and your business can hire another person from the same hemisphere to work with after you've moved on.
The tooling around static languages is generally stronger. I've written very similar types of code in both Java and Python, and hands down, I've found it easier to develop and maintain in big code in Java.
I still script quick stuff up in python for personal use.
YMMV.