Design – Architectural Differences Between Dynamic and Static Languages

Architecturedesigndynamic-typingstatic-typing

Are there any major architectural differences when designing applications that will be built on static languages (such as C# or Java) and dynamic languages (such as Ruby or Python)?

Which are the design possibilities that might be a good choice for one type that's a bad one for the other? Are there any useful features achievable with one type that's not with the other (in design and architecture, of course)?

Also, are there any dynamic-specific design patterns?

Best Answer

Let's get a few things straight:

  1. Interactive scripting and static languages aren't mutually exclusive. F# and Haskell both have REPL interfaces.
  2. Dynamic languages and high performance aren't mutually exclusive, though some optimizations are. JavaScript runs pretty damn fast on most browsers nowadays.
  3. Even in dynamic languages, you still need to document, remember and think about types.
  4. Due to the increasing popularity of type inference, a lot of static languages don't have to notate types very often anymore. In static languages with strong type inference, the compiler figures out what the types are from your code so that most of the time, and tells you if you ever do something that violates the type definitions. As far as syntax is concerned, this provides the best of both worlds.
  5. OOP and dynamic languages aren't mutually exclusive. PHP now supports classes and even inheritance.

All those surprising similarities aside, there are some practical differences that do influence the development process:

  1. Dynamic languages allow for interesting ways of passing data around in the small.
  2. Static languages allow you to reduce the amount of testing you have to do by making many kinds of bugs impossible.
  3. In that same vein, static languages allow interesting validation and automatic conversion features, like units of measure in F#.
  4. Taken to the extreme, static languages allow for code contracts and formal verification, which can document and flat out prevent things like potential divide-by-zeros, infinite loops, null references, invalid list sizes or indices, range errors and other logically invalid state that you might define.
  5. Taking that extreme even further, CPU optimizations can be made based on these static constraints, which yields even better performance.

There is also one type of program that could never have been made without static typing: Singularity, an OS without hardware process boundaries. It's written in a small amount of C, some C#, and a dialect of C# called Spec#, which supports code contracts.

Despite being written in a garbage-collected language, multitasking and interprocess communication performance on this OS is in fact better than anything else out there, due to the fact that all the processes run in one memory space, and due to the formal verification optimizations I mentioned above. You couldn't do this without static typing, because in order for programs not to be able to compromise the rest of the system, the communication objects need to be statically verifiable.

Most of the time, though, architectures should look very much the same. Static languages may make programs easier to reason about in many cases because the types are well-defined, but a well-written dynamic language program would also have types that are, at the very least, well-defined in the developers' minds.

Related Topic