I have yet to experience a dynamically typed code base in which missing types was helpful and in which you weren't required to trace multiple layers of functions to understand the argument and return types of the function you care about, even with pattern matching.
Your last paragraph is accurate regarding the tradeoffs of a statically typed language. However, it leaves off the tradeoffs of a dynamically typed language. In a statically typed language with type inference, in the main portion of the system, statically inferred types are a massive benefit and save a lot of heartache. When you call a function, you know its types. Yes, at the boundaries of a program such as I/O and sometimes message passing, things get sticky. Dynamically typed languages help at the boundaries because they loosen things up enough to be helpful. However, they throw out all the benefits in the parts of the system away from the boundaries. I view typespecs as a necessary tradeoff to accommodate static types missing from those parts of the system. In such parts in a dynamically typed language, one basically is coding like you would in a statically inferred typed language and is not taking advantage of dynamic types, so typespecs should be there. I'd argue that abuse of dynamic types away from boundaries should be considered very seriously, same as one would do with macros.
> 90% of the time the types are simply an extension of the database and enforced strictly at the database layer while everything else is just data pass through anyway (in Ruby, Python, PHP, etc). You understand the database, you understand the application data.
Case in point. In a large system, why do I or others need to understand the data at the database layer to develop something many layers above or away from that? There is almost always a transformation from a storage data structure to the in-application and domain data structures. Databases are for storage and state retention, not application logic and data structures. Your 90% of the time applies at the database interaction layer, but it is not the majority of the code.
> I really think it's just one of those areas where people come at problems differently. Some people love it and swear by it. For those people, I think the lack of static typing causes a real gap in their entire approach to programming which translates to frustration and seeing a lot of "this wouldn't have been a problem with static typing..." experiences.
You seem to put it on developers coming to dynamically typed languages from statically typed languages having a "gap" in their approach. When wanting to call a function, I do not see it as a gap in one's skills or experience in not wanting to have read the implementation of that function and the functions it calls. When calling a function, I want to know its name, its argument names and types, the return types, and documentation. I don't see why it's a gap in one's approach to want that. It's almost the first thing you learn when learning software development. I think dynamically typed developers are just used to the overhead of reading function definitions to understand how to call things or they are the ones who wrote or have significantly used the code base.
> You seem to put it on developers coming to dynamically typed languages from statically typed languages having a "gap" in their approach.
Gap was a bad choice of words. I just meant a different approach.
I've worked with both dynamic and statically typed languages, as well as Elixir which I consider the right "in between" balance.
In the environments that I've worked in, the devs who were comfortable with dynamically typed languages were extremely productive. The ones that preferred static typing who tried to work in the dynamic languages regularly complained about the lack of static typing and were typically not as productive.
The in the static typing environments, you'd see the reverse. The devs who were more comfortable with dynamic typing were regularly frustrated by the steps they saw negatively impacting their productivity while the devs who preferred the static environment typically seemed happy and complaint free.
I really think it just boils down to how people think about problems. This is entirely anecdotal of course.
Interesting stuff to hear, but I still think we're not getting down to what I've referred to as it being a necessary thing and not just a preference. When developers are working inside a dynamically typed code base, they have types in their head, do they not? The runtime system certainly does. Why not just write them down? Why are people so afraid of or unwilling to write down stuff they know or think they know?
And again, I'd wager that "productive" people in dynamically typed languages are more comfortable than productive if one considers bugs introduced by assumptions of types and the unavoidable overhead in reading code implementations to understand call uses. I have seen countless bugs that would have been prevented or at least lessened by typespecs. If that's just a "statically typed perspective", what other process is catching these very real bugs and mistakes in the code? I have paired with people seemingly comfortable with not having typespecs and when asked questions like "how do you know ___?", the answer was usually "I don't" or "I think". Once we figure out the actual types and expected values, again, why not just right them down? Why throw out that knowledge?
The way that I view things is that statically inferred types are a huge boon to the majority of a program abut can be a real pain at I/O boundaries, message passing, and other wings and edges of the software design. With dynamic types, they are a major boon to these I/O boundaries, message passing, and other wings and edges, but they are a major pain point in the rest of the program. My perspective is that whatever type of language you are using, you need to accept but account for its deficiencies.
Your last paragraph is accurate regarding the tradeoffs of a statically typed language. However, it leaves off the tradeoffs of a dynamically typed language. In a statically typed language with type inference, in the main portion of the system, statically inferred types are a massive benefit and save a lot of heartache. When you call a function, you know its types. Yes, at the boundaries of a program such as I/O and sometimes message passing, things get sticky. Dynamically typed languages help at the boundaries because they loosen things up enough to be helpful. However, they throw out all the benefits in the parts of the system away from the boundaries. I view typespecs as a necessary tradeoff to accommodate static types missing from those parts of the system. In such parts in a dynamically typed language, one basically is coding like you would in a statically inferred typed language and is not taking advantage of dynamic types, so typespecs should be there. I'd argue that abuse of dynamic types away from boundaries should be considered very seriously, same as one would do with macros.
> 90% of the time the types are simply an extension of the database and enforced strictly at the database layer while everything else is just data pass through anyway (in Ruby, Python, PHP, etc). You understand the database, you understand the application data.
Case in point. In a large system, why do I or others need to understand the data at the database layer to develop something many layers above or away from that? There is almost always a transformation from a storage data structure to the in-application and domain data structures. Databases are for storage and state retention, not application logic and data structures. Your 90% of the time applies at the database interaction layer, but it is not the majority of the code.
> I really think it's just one of those areas where people come at problems differently. Some people love it and swear by it. For those people, I think the lack of static typing causes a real gap in their entire approach to programming which translates to frustration and seeing a lot of "this wouldn't have been a problem with static typing..." experiences.
You seem to put it on developers coming to dynamically typed languages from statically typed languages having a "gap" in their approach. When wanting to call a function, I do not see it as a gap in one's skills or experience in not wanting to have read the implementation of that function and the functions it calls. When calling a function, I want to know its name, its argument names and types, the return types, and documentation. I don't see why it's a gap in one's approach to want that. It's almost the first thing you learn when learning software development. I think dynamically typed developers are just used to the overhead of reading function definitions to understand how to call things or they are the ones who wrote or have significantly used the code base.