79

Explaining the difference between strictness of languages and paradigms to a colleague of mine, I ended up asserting that:

  • Tolerant languages, such as dynamic and interpreted languages, are used best for prototypes and small projects or medium-size web applications. When choosing elegant dynamic languages such as Python or JavaScript with Node.js, the benefits are:

    1. Fast development,

    2. Reduced boilerplate code,

    3. Ability to attract young, creative programmers who flee “corporate languages”  like Java.

  • Statically typed/compiled languages are best for applications which require higher strictness such as business-critical apps or apps for medium to large-size apps.

    1. Well-known paradigms and patterns developed for decades,

    2. Ease of static checking,

    3. Ability to find many professional developers with decades of experience.

  • Strict languages such as Haskell, Ada or techniques such as Code contracts in C# are better for systems which favor safety over flexibility (even if Haskell can be extremely flexible), such as life critical systems and systems which are expected to be extremely stable. The benefits are:

    1. Ability to catch as many bugs as possible at compile time,

    2. Ease of static checking,

    3. Ease of formal proofs.

However, by looking at the languages and technologies used for large-scale projects by large corporations, it seems that my assertion is wrong. For example, Python is successfully used for large systems such as YouTube or other Google applications which require an important amount of strictness.

Is there still a correlation between the scale of the project and the strictness of the language/paradigm which should be used?

Is there a third factor that I've forgotten to take in account?

Where am I wrong?

6
  • 12
    Strict type checking and static type checking aren't the same thing. Python is dynamically typed, but is more strict than C. The advantage of static type checking isn't strictness per se but that types are checked at build time, not run time. I've dealt with many C/C++ issues in my career because of implicit casting. Aug 24, 2013 at 17:24
  • 6
    There's probably something to be said about lifecycle: software that starts in your first category can evolve into the others, "dragging" the language with it.
    – Mat
    Aug 24, 2013 at 17:24
  • 11
    The only thing elegant about javascript is it runs in most browsers.
    – JeffO
    Jun 30, 2014 at 20:26
  • 1
    @StevenBurnap: I couldn't agree more regarding the difference between static and strict. Java is another point on the spectrum, being static and too strict. Developers often berate static typing using Java as example, but much of that criticism should actually be directed at Java's overly-strict compiler, not static typing in general. Just look at Scala on the same JVM, which is statically typed, but has much less verbose code due to the fantastic compiler's type-inferencing abilities. Mar 25, 2015 at 10:17
  • 2
    "Python is successfully used for large systems" - what is the definition of "success" here? That it mostly runs and produces some result? Is the amount of testing and workforce required included? What about maintainability?
    – Den
    Mar 25, 2015 at 13:33

5 Answers 5

44

An interesting case study on the matters of scaling projects that use dynamic and interpreted language can be found in Beginning Scala by David Pollak.

I started searching for a way to express the code in my brain in a simpler, more direct way. I found Ruby and Rails. I felt liberated. Ruby allowed me to express concepts in far fewer lines of code. Rails was so much easier to use than Spring MVC, Hibernate, and the other “streamlined” Java web frameworks. With Ruby and Rails, I got to express a lot more of what was in my head in a shorter period of time. It was similar to the liberation I felt when I moved from C++ to Java...

As my Ruby and Rails projects grew beyond a few thousand lines of code and as I added team members to my projects, the challenges of dynamic languages became apparent.

We were spending more than half our coding time writing tests, and much of the productivity gains we saw were lost in test writing. Most of the tests would have been unnecessary in Java because most of them were geared toward making sure that we’d updated the callers when we refactored code by changing method names or parameter counts. Also, I found that working on teams where there were mind melds between two to four team members, things went well in Ruby, but as we tried to bring new members onto the team, the mental connections were hard to transmit to new team members.

I went looking for a new language and development environment. I was looking for a language that was as expressive as Ruby but as safe and high-performance as Java...

As you can see, major challenges in project scaling for author turned out to be in test development and knowledge transfer.

In particular, author goes into more details in explaining the differences in test writing between dynamically and statically typed languages in Chapter 7. In section "Poignantly Killing Bunnies: Dwemthy’s Stairs" author discusses Scala port of a particular Ruby example:

Why the Lucky Stiff... introduces some of Ruby’s metaprogramming concepts in Dwemthy’s Array in which a rabbit battles an array of creatures. N8han14 updated the example to work in Scala...

Compared to the Ruby code, the library parts of the Scala code were more complex. We had to do a lot of work to make sure our types were correct. We had to manually rewrite Creature’s properties in the DupMonster and the CreatureCons classes. This is more work than method_missing. We also had to do a fair amount of work to support immutability in our Creatures and Weapons.

On the other hand, the result was much more powerful than the Ruby version. If we had to write tests for our Ruby code to test what the Scala compiler assures us of, we’d need a lot more lines of code. For example, we can be sure that our Rabbit could not wield an Axe. To get this assurance in Ruby, we’d have to write a test that makes sure that invoking |^ on a Rabbit fails. Our Scala version ensures that only the Weapons defined for a given Creature can be used by that Creature, something that would require a lot of runtime reflection in Ruby...


Reading above can make one think that as projects grow even larger, test writing might become prohibitively cumbersome. This reasoning would be wrong, as evidenced by examples of successful very large projects mentioned in this very question ("Python is successfully used for... YouTube").

Thing is, scaling of the projects isn't really straightforward. Very large, long-living projects can "afford" different test development process, with production quality test suites, professional test dev teams and other heavyweight stuff.

Youtube test suites or Java Compatibility Kit sure live a different life than tests in a small tutorial project like Dwemthy’s Array.

1
27

Your assertion is not wrong. You just need to dig little deeper.

Simply said, big systems use multiple languages, not just one language. There might be parts that are built using "strict" languages, and there may be parts that are built using dynamic languages.

As for your Google and YouTube example, I heard that they use Python primarily as "glue" between various systems. Only Google knows what those systems are built with, but I bet that many of Google's critical systems are built using strict and "corporate" languages like C++ or Java, or maybe something they themselves created like Go.

It is not that you can't use tolerant languages for large-scale systems. Many people say Facebook uses PHP, but they forget to mention that Facebook had to create extremely strict programming guidelines to use it efficiently on this scale.

So yes, some level of strictness is required for large-scale projects. This can come either from strictness of language or framework, or from programming guidelines and code conventions. You can't just grab few college graduates, give them Python/Ruby/JavaScript and expect them to write software that scales across millions of users.

3
  • 1
    "You can't just grab few college graduates"..."and expect them to write software that scales across millions of users." would have probably been enough.
    – dyesdyes
    Mar 25, 2015 at 15:38
  • Worth noting here that as with Google and Python, Facebook's use of PHP is largely as glue ... My understanding is that for most functions, the PHP is mostly just used as a relatively simple client onto a more complex server system that is typically implemented in a more traditional "heavyweight" language, such as Java, C++, Haskell, OCaML, etc.
    – Jules
    Jul 6, 2017 at 18:25
  • "Only Google knows what those systems are built with".. I even have some doubts about that :) In my experience, no single entity (person or otherwise) can list all the parts of a very large system. In many cases, buried in the bowls of some server is a long forgotten piece of Perl, Fortran or KSH script that performs 'Magic' .
    – mattnz
    Jul 7, 2017 at 4:36
4

My experience with large systems is that they stand or fall not by language choice, but by issues of design/architecture or test coverage. I'd rather have a talented Python team on my big enterprise project, than a mediocre Java one.

Having said that, any language that let's you write significantly less code, has to be worth looking at (e.g. Python vs Java). Perhaps the future is in clever, statically-typed languages with advanced type-inference (e.g. in the Scala mold). Or hybrid, such as C# is attempting with its dynamic qualifier...?

And let's not forget the "other" static typing benefit: proper IDE code-completion/intellisense, which in my view is an essential feature, not a nice-to-have.

3
  • 1
    "code-completion/intellisense" - automated refactoring is also quite important.
    – Den
    Mar 25, 2015 at 14:16
  • @Den Absolutely. Could it be that dynamic languages help you write initial versions very quickly (easier, less code to write), but get bogged down later, as it becomes increasingly difficult to assess the impact of change or do refactoring (without automated refactoring tools)? Mar 25, 2015 at 15:22
  • I don't understand this obsession with writing less lines of code. I mean if there is straight forward way to write 15 lines of code knowing exactly what needs to be write and IDE gives you nice hints and completion, is much faster than writing 3 lines of code, but you forgot what the name of attributes and have to google or read documentation May 20, 2021 at 2:49
3

There are two kind of errors to check for: type errors (concatenate an integer + list of floats) and business logic errors (transfer money to a bank account, check if the source account have money).

The "dynamic" part of a dynamic programming language is just the place where type checking takes place. In a "dynamically typed" programming language, type checking is done while executing each statement, while in a "statically typed language" type checking is done at compilation time. And you can write an interpreter for a static programming language (like emscriptem does), and you can also write an static compiler for a dynamic programming language (like gcc-python or shed-skin does).

In a dynamic programming language like Python and Javascript you need to write unit tests not only for the program business logic but also to check if your program does not have any syntax or type errors. For example, if you add "+" an integer to a list of floats (which does not makes sense and will issue an error), in a dynamic language the error will be raised at runtime while trying to execute the statement. In a static programming language like C++, Haskell and Java, this kind of type error will be caught by the compiler.

A small codebase in a dynamically checked programming language is easier to look for type errors because is easier to have a 100% coverage of source code. That's it, you execute the code by hand a few times with different values and you're done. Having a 100% coverage of source code gives you a fair hint that your program may not have type errors.

With a large codebase in a dynamically checked programming language it is harder to test every statement with every possible type combination, specially if you are careless and write a function that may return a string, list or custom object depending on its arguments.

In a statically checked programming language the compiler will catch most of the type errors at compile time. I say most because a division by zero error, or an array out of bounds error are also type errors.

More often than not the real discussion is not about programming languages but about the people using those languages. And this is true because, for example, assembly language is as powerful as any other programming language, yet we're writing code on JavaScript. Why? Because we're humans. First, we all make mistakes and its easier and less error prone to use a dedicated tool specialized for a specific task. Second, there is a resources constraint. Our time is limited, and writing webpages on assembly would take ages to finish.

1

Another consideration is the who behind writing large-scale applications. I have worked at plenty of places who want to use Ruby or Python on some big enterprise-style projects, but are consistently "shot down" by IT managers and corporate security teams precisely because of the open source nature of the projects.

I have been told, "We can't use Ruby on Rails because it is open source and someone could put hacks in there that steal critical or protected information." I'm sorry, but once someone has that mindset that open source == evil, it is nearly impossible to change it. That line of thinking is a corporate disease.

C# and Java are trusted languages with trusted platforms. Ruby and Python are not trusted languages.

5
  • 2
    I disagree with the last line. Java is at one of it's lowest trust points ever. C# is considered warily by the whole open source community. Ruby is seen as solid but slow (even though it isn't any longer) and Python is the trusted work-horse glamour child of whole industries (machine-learning and data science anyone?).
    – CodeBeard
    Aug 24, 2013 at 19:44
  • 1
    Dynamic languages are bad for security, but "open source" is not good reason. Maybe they meant "it is easy to influence one part of code from completely different part of the code". See programmers.stackexchange.com/questions/206558/…
    – Euphoric
    Aug 24, 2013 at 19:44
  • 1
    Note that indeed, "open sourceness" is one of the aspects of choice of a language. That's for example one of three reasons given by Jeff Atwood to explain why Discourse uses Ruby. Aug 24, 2013 at 19:46
  • C# is completely open-source now, yet it is still curated, planned and developed by professional devs which is nice I guess. Let's hope the "Python 3 vs 2" kind of thing will not happen here.
    – Den
    Jun 30, 2014 at 8:08
  • Bugs and security holes are introduced by programmers and not by languages, and for the record I've contributed a number of security fixes to open source projects. How many closed projects have I helped??? zero!
    – Reactgular
    Jun 30, 2014 at 19:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.