The article's just claiming that the modules of dynamic languages can be compiled independently; not that it will be correct.
Just my thoughts: There's a bigger question here about types, though. I think the argument is that the ceremony of types gets in the way more than it helps, and it requires up-front design. Many people like dynamic languages for their flexibility; and when you get bugs, you have to fix them anyway. There's an assumption in typed languages that we can design our types well enough upfront to help solve the problem.
It's interesting how types create a dependency on the interface (i.e. if you use a type, you depend on it). One of the ideas of Abstract Data Types was to reduce dependency on the internal implementation details; but you're still dependent on the external interface. If you change the interface, it creates problems (e.g. unit testing claims to give you confidence to refactor, but if you change interfaces, you also have to change the tests...). EDIT added "claims to"
This seems intrinsic to modularity, and I can't really see any solution to this; except for ways to make it easier to cope with interface change. Some insights may come from webapp API's, where the dependency is more explicit (you have to send and receive serialized messages).
Maybe you got me closer to the answer, and you certainly seem to have more experience on this subject than I do. I am still missing some part of the picture, so let me ask:
Types: You think about the problem up-front to the best you can. Most likely you later change the interface. The compiler now breaks the code and forces you to fix it.
Dynamic: You are flexible, which means you can start your work without having to think up-front (Q1: How is this good?). Later when you change the interface (which may exist only in your mind, but it does as far as the modules are to interact with each other in some way at all), the code still breaks but the compiler won't tell you.
In either case, as you said "you have to fix them anyway". So Q2: How is compiler not being able to complain about broken code (and possibly unit tests finding it) helping?
One comment here cited an example where one can get away without introducing errors while still changing the type ("f(g(x)"). But that is readily achieved with statically typed languages like C++ as well.
Q1, you're assuming you can design upfront; that is, that you understand the problem, you have enough information to solve the problem, the world won't change and so on.
Q2, the ceremony of types itself has a cost. You have to think about it, type it - and you may need to change it. When types ripple through layers of calls, the changes do too.
Note: I don't know the answer. I notice that dynamic languages seem to be becoming more popular (are they? or are they just more publicized?) In a rapidly changing world, it's more important to adapt now than perfect. There's a general trend, that because computers get faster but humans don't, more and more of the work will be transfered to the computer. Dynamic languages do this in the sense that they are less efficient than static languages - on the assumption that speed is the main benefit of static languages. Certainly, the coder has less work to do. Another benefit is that it makes coding accessible to less skilled people (and more skilled people who have less time to devote to a particular task).
There are trade-offs. The first thing is to note what the trade-offs are. The second thing is to note what groups of people use programming languages and for what tasks. The third thing is to ask how those people value those trade-offs, for those specific tasks. e.g. Perhaps sometimes, a crappy, hard-to-maintain, only partially correct solution now is better than a high-quality, clear, correct solution too late?
Web APIs often have explicit versioning. Perhaps that approach could be adopted for programming, where you have the option to specify the version of a function you are using. This would enable gradual migration and adoption of new features.
> If you change the interface, it creates problems (e.g. unit testing gives you confidence to refactor, but if you change interfaces, you also have to change the tests...).
Could you elaborate on this point? If you change the behavior of a dynamic module A, i.e. its implicit interface, you'd have to change its unit tests to reflect these changes anyway...
Yes, that's correct. I was addressing the selling point of unit tests, that they give you a safety net to ensure your changes don't introduce new bugs. The claim fails when the interface changes.
In my experience, interface changes happen quite often. When you prevent them from changing, you end up with back-compatibility hell, that popular platforms like x86, Windows and Java have to maintain - and that's just for external, public interfaces.
Just my thoughts: There's a bigger question here about types, though. I think the argument is that the ceremony of types gets in the way more than it helps, and it requires up-front design. Many people like dynamic languages for their flexibility; and when you get bugs, you have to fix them anyway. There's an assumption in typed languages that we can design our types well enough upfront to help solve the problem.
It's interesting how types create a dependency on the interface (i.e. if you use a type, you depend on it). One of the ideas of Abstract Data Types was to reduce dependency on the internal implementation details; but you're still dependent on the external interface. If you change the interface, it creates problems (e.g. unit testing claims to give you confidence to refactor, but if you change interfaces, you also have to change the tests...). EDIT added "claims to"
This seems intrinsic to modularity, and I can't really see any solution to this; except for ways to make it easier to cope with interface change. Some insights may come from webapp API's, where the dependency is more explicit (you have to send and receive serialized messages).