I'm going to say that the bigger problem in dynamic languages isn't that they are dynamic. It's that they have weak, nonexistant, or very undeveloped mechanisms for creating strong communication protocols that you can depend on as safe or reliable.<p>Take the classic case of SQL injection. You have string input into your system that turns into string input into a SQL query that turns into string input to a database. That is dangerous because if you don't check on what the input string contains, it might contain nothing, or a semicolon, or it might not be a string at all!<p>We understand that putting a string direct into a SQL statement is dangerous at this point, but we have yet to fix its root cause - nonexistant protocols or boundaries in most code we write.<p>What a static language changes in that regard is compiler checked type signatures on your code. That generally stops you from say passing an Integer into something that needs a String. That solves a certain class of problems for sure, and the complier does it for you every time you change your code, so there is a convenience there.<p>What static typing doesn't give you is actual data correctness. Things like buffer overflows or SQL injection can still happen with static typing. You could use a language like Scala or Haskell to have stronger/more complex types that would have more distinct notion of value correctness and at that point the complier would be doing most of the work to ensure your program is correct.<p>Leaning on a type system in that regard is basically turning your types into the protocols that determine correctness in your system.<p>It is also possible to lean on stronger protocols that check messages in a dynamic languages to achieve largely the same thing.<p>In the end, to write safe, high quality software, you need to define the communication protocols between methods/functions/routines/services and enforce them much as you would with an externally facing REST api.<p>The difference between a dynamic system with dynamic protocol checking vs a static system with compiler type checking is the mechanism you are using to enforce the protocol and how easy it is to interact with it.<p>Dynamic systems might be easier to interface with externally because you don't have to understand a complex type, just pass a Hash/Dictionary sort of like a JSON API, vs a static system where you need to use the right types and so on, similar to a SOAP/WSDL API.<p>Performance is also a consideration, but really when you compare static vs dynamic, it is important to understand that at the end of the day you can write Ruby/Python/PHP that is functionally equivalent to C/C++/Java. They are all ultimately going to be able to do the same kinds of things.<p>The tradeoff is in how they solve the problem and how well that fits with the team writing the software.