It's one of the stereotypical failure cases of dynamically-typed languages. I cite this not to bury them in general, but because it's something that people programming in dynamic languages need to be aware of. If object oriented languages seem to frequently end up with "God Objects" dynamically-typed languages end up with "God Functions", where Just One More Parameter at a time, a core function grows slowly and steadily until it is a monstrosity of several dozen parameters and there is simply no conceivable way to document how they all interact with each other, test all the combinations, conceptualize all the combinations, etc. It's very dangerous because it happens often just one parameter, or even fractions of a parameter ("let's make this string also able to be an array of strings") at a time, each step seeming sensible at the time but the totality becoming a nightmare.
Statically typed can incrementally end up with too many parameters too, but the static typing generally helps reduce the complexity and there is generally more incentives to start binding the parameters up into meaningful other structs. Dynamically typed languages on the other hand have the tendency to start widening what types each parameter can take which makes the problems even worse. Is "targetURL" a string, an array of strings that will automatically turn the return into an array of results, an object that implements ".toURL()", a function that will be automatically called with some magic parameters, a None which will then invoke other magic to get the URL from somewhere else, etc.?
(Don't worry, dynamic typing fans, static languages have their own characteristic failures, like the aforementioned God Object.)
Dynamically typed code bases are not doomed to end up this way. It can be avoided with discipline, which starts with the awareness that it is a problem at all. And it's a very good idea to learn to avoid them, because they're terribly difficult to tear back apart once constructed. I've worked in a code base that darned near had a "JustDoEverythingWeCanPossibleDo(...)" function, where (...) doesn't represent the true horror because there were rather a lot of global variables getting set that had huge impacts on the process as well. Trying to pull that apart to do any real work was, ah, an experience.
Statically typed can incrementally end up with too many parameters too, but the static typing generally helps reduce the complexity and there is generally more incentives to start binding the parameters up into meaningful other structs. Dynamically typed languages on the other hand have the tendency to start widening what types each parameter can take which makes the problems even worse. Is "targetURL" a string, an array of strings that will automatically turn the return into an array of results, an object that implements ".toURL()", a function that will be automatically called with some magic parameters, a None which will then invoke other magic to get the URL from somewhere else, etc.?
(Don't worry, dynamic typing fans, static languages have their own characteristic failures, like the aforementioned God Object.)
Dynamically typed code bases are not doomed to end up this way. It can be avoided with discipline, which starts with the awareness that it is a problem at all. And it's a very good idea to learn to avoid them, because they're terribly difficult to tear back apart once constructed. I've worked in a code base that darned near had a "JustDoEverythingWeCanPossibleDo(...)" function, where (...) doesn't represent the true horror because there were rather a lot of global variables getting set that had huge impacts on the process as well. Trying to pull that apart to do any real work was, ah, an experience.