Scripting vs. Engineering

By: on June 29, 2016

I’ve come to the conclusion that the terms like “programming”, “coding” etc. have become horribly ambiguous which has enabled:

  • organisations to offer courses on html/css editing as “coding”
  • people to make claims like “nodejs is more productive than java” (which is a nonsense statement either way)
  • various arguments along the lines of “is X a PROPER programming language”.

I think it’s more helpful to think in terms of “scripting” vs. “engineering”:

  • Scripting is geared towards the short-term, small team or solo, quick prototyping.
  • Engineering is geared towards the long-term, larger teams, maintainability(i.e. readability), refactorability and extensibility.

It’s probably impossible to agree on whether a language is “scripting” or “engineering”, but obviously I have personal opinions about some characteristics of each:

  • In the long term, the time taken writing software is 90% reading what’s already there. Languages that don’t support readability (or IDE analysis support) fall towards the Scripting end. IMHO the reason nodejs has encouraged microservices is because nodejs is quickly unreadable – you don’t extend a nodejs app, you just write another service…
  • Monkey-patching automatically precludes a language from Engineering (it violates the Principle of Least Surprise) – how can anyone reason about code that can extend an object’s methods at runtime?
  • Static-typing moves the language towards Engineering by increasing correctness and readability. Completely pathological strict typing languages like Haskell may be a learning barrier though (along with Haskell programmers’ irresistible temptation to use punctuation as function names it seems – quick, quick, tell me what the difference is between foldl and foldl’)
  • If the language has static typing then good type inference cuts down on the boilerplate. These days I wouldn’t write any Java without using lombok.
  • Immutable objects are good Engineering. Likewise functional languages can aid Engineering, except that the temptation towards one-line-itis reduces readability.
  • Encapsulation and clear techniques for Dependency Injection help Engineering as it supports mocking in unit tests.
  • Automatic resource management aids Engineering.

So I can possibly come up with a completely unscientific and arrogantly self-opinionated table of languages: 5 is good, 0 is bad (if the square is blank then I haven’t formed an opinion):

Readability Least surprise Static types Type inference Immutable Functional DI Mocking Resource Management
Java with lombok 4 4 4 3 2 5 31
Kotlin 4 4 4 5 4 5
Ceylon 4 4 52 5 5
Rust 5 5
Clojure 3 33 1 3 5 5 4
Python 4 4 3
Python with Coconut 5
Javascript 3 24 0 4 05
PHP 3 26 17 0 1 3 0
Bash (just for fun) 4 38 0 0 0 0 49
  1. “try” with resources
  2. inline Union types look interesting
  3. things get turned into null at the drop of a hat
  5. everything is in a global namespace
  7. annotations for run-time checking
  8. space handling in values
  9. all resources are in pipes

Scripting vs. Engineering databases

I think we can extend this to databases too. The NoSQL/schema-less fashion of databases are definitely up the scripting end:

“The problem is that in the absence of a formal schema, the “schema” is an emergent property which is reflected in the code used to manipulate the database” – comment in Why You Should Never Use MongoDB

The “MEAN stack” – mongodb, express, angular and nodejs – is certainly for prototypes only. It should be called the WONGA stack: Write Only Node, monGo and angulAr (possibly only UK readers will get the reference). Angular and React are good for “single page application” building, though possibly vastly improved by using typescript (and flow) instead of javascript.

Responses to “static typing is bad / gets in the way”

The post “Static vs. Dynamic” Is the Wrong Question for Working Programmers, in the section”static typing benefits”, makes the correct statement “Proof that certain kinds of dynamic errors are impossible” but I’d maintain the suggested “drawbacks” are incorrect:

  • Increased verbosity or reduced expressiveness – not true if the language has good type inference, and type annotations improve readability immensely.
  • Rejection of otherwise correct programs – how can a program be correct if it has a type error? See how an uninitialised variable cost $90,000.
  • Slower programmer iteration (possibly lengthy compile/run cycles) – IDE integration and incremental builds removes this completely
  • A need for the developer to learn “static typing” language feature – I’d suggest that if you really know what your program is doing then you do know about types (unless you’re programming in the Stringly style)


  1. Tim Band says:

    Haskell has two ls.
    foldl’ is the Right One (eager evaluation of the operation you are folding over) and foldl is the Wrong One (lazy evaluation of the operation you are folding over leading to blowing the stack just when you thought you knew what your program was doing). The real problem here is the Haskell committee’s unwillingness to pull the Backwards Compatibility Dragon’s tail. But your example should perhaps have been “even supposing you know that is the application of Applicative function to an Applicative value (and even supposing you know what on earth that means) can you tell what is supposed to be?”; indeed Haskell is littered with this stuff as you rightly say.

    Anyway, nitpicking aside, would you agree that “lets you get off the ground quickly” is antithetical to “lets you maintain well in the long term”? It seems to me that the things one hates when maintaining old code are the very things one likes at the start when it’s all green fields. After all, any particular language (non-) feature has to be useful at some point or it (the feature or the language) would never be used and there would never be a problem. Therefore (non-) features that are a burden late in a program’s life must be a boon in its early days.

  2. Tim Band says:

    Oops, forgot I should have been escaping my angle brackets. Try:

    “supposing you know that <*> is the application of Applicative function to an Applicative value (blah blah) can you tell what <**> is supposed to be?”

  3. Ian Rogers says:

    That’s a good observation. But there’s no clear divide between “scripting” and “engineering”:
    1. you just know if you stepped over the line 3 months ago
    2. a lot of the “productivity” studies only cover scripting.

  4. Ian Rogers says:

    Actually, let’s try to define when it’s ok to do “scripting”. I think the basic requirement is that you can keep all the code base in your head for “all time” (i.e. for the maintenance lifetime of the project) so:

    1. it’s probably only you, or 2, in the team
    2. it’s a very simple “one function” application; will take less than a month to write, preferably less than a week.
    3. it’s a “write and forget” application; you’ll probably never extend it.

    If any of those three become untrue then it’s probably time to freeze your MVP PoC and do some engineering…

  5. Ian Rogers says:

    Reading through some python documentation blogs just for the heck of it and this paragraph caught my eye:

    “If you’re coding in Haskell the compiler’s got your back. If you’re coding in Java the compiler will usually lend a helping hand. But if you’re coding in a dynamic language like Python or Ruby you’re on your own: you don’t have a compiler to catch bugs for you.” –

    And that’s why I like types…

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>