6

I'd like to read the opinion of experts on whether compiled, strictly-typed languages help programmers write robust code easier, having their backs, checking for type mismatches, and in general, catching flaws in compile time that otherwise would be discovered in runtime ?

Has unit testing in loosely typed, interpreted languages need to be more thorough because test cases need to assess things that in a compiled languages wouldn't simply compile ?

Need the programer in compiled, strictly-typed need to write less code since he/she doesn't have to constantly check for correct types ( instance of operator ) since the compiler catches those things ( the same applying to misspelled variable names or uninitiated variables ) ?

NOTE: by strictly typed language I mean languages that force you to declare variables and assign a type to them in order to be able to use them, and once a variable is declared, you cannot change its type or assign incompatible type values.

int myInt = 0;
String myString = "";
myInt = myString; // this will not fly in a strictly typed language
myInte = 10;   // neither will this ( myInte variable doesn't exist )
Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
  • 8
    This question doesn't make sense. There is no such thing as a compiled language or an interpreted language. Compilation or interpretation are traits of, well, the compiler or the interpreter, not the language. A language is a set of abstract mathematical rules. Languages aren't compiled or interpreted, they just *are*. Every language can be implemented with a compiler, and every language can be implemented with an interpreter. The vast majority of languages have both compiled and interpreted implementations, for example there are interpreters for C and C++ and all currently existing … – Jörg W Mittag Aug 22 '12 at 01:29
  • 1
    … PHP, Perl, Python and ECMAScript implementations as well as most Ruby implementations have compilers. Also, the terms "strictly-typed" and "loosely-typed" are not defined. It's impossible to answer your question without you giving a *precise* and *unambiguous* definition of those two terms, otherwise this is just going to devolve into yet another meaningless typing flamewar. – Jörg W Mittag Aug 22 '12 at 01:31
  • C is generally compiled, as is Java. So, traditionally compiled may be better. The strict vs weak typing, is a feature of the language. Actually it may be the coarsest division of languages that make sense. – Joel Aug 22 '12 at 01:34
  • 1
    @Joel: It might be a feature of the language, but there is no definition of those two terms. You can't answer a question about whether strict typing leads to robust code if you don't know what strict typing *is*! The only thing that everybody can agree on, is that the terms "strict typing" and "loose typing" are so badly defined that they are useless. – Jörg W Mittag Aug 22 '12 at 01:37
  • 1
    The dichotomy is not between strict and loose, it's really between strict and dynamic, and those are really two ends of a continuum. C, for instance, falls somewhere in the middle because void* gives you a way around the type system – Joel Aug 22 '12 at 01:41
  • 23
    You guys are being pedantic. It's a perfectly answerable question if you don't read too much into it. – Karl Bielefeldt Aug 22 '12 at 01:46
  • 1
    @Joel: please read the edit by the OP. He appears to be using a *completely different* definition of "strict" than you do. Which is why I asked him to provide his definition. His definition seems to be "strictly = explicitly" and "loosely = implicitly", although I don't quite get why he needs to introduce two undefined terms when two well-defined ones already exist. For example, according to the OP's definition, Haskell is *loosely* typed, whereas C is *strictly* typed, whereas most people would probably disagree. Oh, and BTW: the opposite end of *dynamic* is *static*. – Jörg W Mittag Aug 22 '12 at 01:47
  • @JörgWMittag C _is_ strictly typed (except for workarounds like casting), isn't it? PHP is an example of a loosely-typed language, with how it converts between strings and numbers all willy-nilly. That's how I always learned the terms... – Izkata Aug 22 '12 at 02:41
  • 4
    @Izkata: again, *there is no definition* of loosely-typed or strictly-typed. If you want to know whether C is strictly-typed, then you have to first tell me what strictly-typed *means*. There are about 20 different definitions of those terms floating around, most of them contradict each other, some are even opposites of each other. In serious literature written by people who actually understand something about type systems, those terms aren't used *at all* because they are completely and utterly worthless, since they don't have a agreed-upon definition. Just in this very discussion thread … – Jörg W Mittag Aug 22 '12 at 03:01
  • 2
    … I count at least three different incompatible definitions. – Jörg W Mittag Aug 22 '12 at 03:02
  • @JörgWMittag Aha. I must have just missed it in your previous comment, but that last one does clear it up for me even after rereading the other ones. – Izkata Aug 22 '12 at 03:05
  • It seems that the OPs definition is very language specific. For example, by that definition, Scala is neither strictly typed or loosely typed - it has implicit typing, but you can't change the type once you've assigned it. It is "not strict". But Scala is going to have very different behavior than JavaScript when it comes to throwing type errors, so it doesn't really fit into the question. – philosodad Aug 22 '12 at 15:41
  • Possibly relevant: http://programmers.stackexchange.com/questions/10032/dynamically-vs-statically-typed-languages-studies, which asks whether studies have been done on the subject. These studies seems to be few and far between. – Winston Ewert Aug 22 '12 at 17:26
  • flamewar! foodfight! – Paul Aug 22 '12 at 20:05

3 Answers3

11

I'd like to read the opinion of experts on whether compiled, strictly-typed languages help programmers write robust code easier, having their backs, checking for type mismatches, and in general, catching flaws in compile time that otherwise would be discovered in runtime ?

For some programs they do.
For some programs they require you to do things that are not really necessary to enable static checks that don't catch anything.

Experts have no consensus. Personally, I favor traditional statically typed languages for most things.

Has unit testing in loosely typed, interpreted languages need to be more thorough because test cases need to assess things that in a compiled languages wouldn't simply compile ?

Not necessarily. The general consensus is that unit tests are the quickest and easiest way to do that, but there is some debate if you need any more unit tests to effectively catch those errors or if the normal tests you'd write to test the functionality would catch it.

Need the programer in compiled, strictly-typed need to write less code since he/she doesn't have to constantly check for correct types ( instance of operator ) since the compiler catches those things ( the same applying to misspelled variable names or uninitiated variables ) ?

If you're doing instanceof in dynamic languages, that is a code smell (imo). So if you consider type annotations, type declarations, or variable declarations to be 'code' then yes, you'll naturally write more code to do the overhead. If not, then it is debatable.


The main thing is that it is never so clear cut. Tooling is generally easier for statically typed languages. Type annotations help readability of code (so some argue). Not having type annotations helps readability of code (so some argue). There's no good quantitative measurement to help. No consensus.

Telastyn
  • 108,850
  • 29
  • 239
  • 365
7

Yes, type-safety leads to more robust code. But at what cost?

You never find every bug in testing. The earlier you find a bug, the cheaper it is to fix (fewer people involved, less communication, etc). The cheapest way to fix a bug is to have your language or compiler prevent it from happening.

I had a client who had a standing bet for over a year, offering a free hamburger for finding an actual bug in my code. Type safety helped make that possible.

In general, compilers or languages preventing bugs is a good thing, but it can be taken to an extreme. XSLT does not allow you to update the value of a variable. As a result, you have to use recursion to make a simple loop (I'm writing this in pig-java/pig-C because XSLT has awful syntax which I fail to remember):

function sumList(x) {
    if (x.length > 1) {
        return sumList(x.tail) + x.head;
    } else {
        return x.head;
    }
}

There are benefits to this approach (few side effects), but this also forces fragmentation on the code where all kinds of things were broken off into separate little functions. It was difficult to avoid doing things multiple times, and this led to all kinds of other bugs and slow performance that were worse than accidentally changing the value of a variable.

Back to type safety. Usually, if I have a function washFabric(Fabric f) and I pass it a Cat instead of a Fabric, this is a simple error on my part. When you have this hidden in layers of function calls, such a mistake is very easy to make and hard to test for. When my code compiles in a type-safe language, I know I didn't make this kind of error. For this reason, I find type-safety a good trade-off between speed of slapping something together that works, and being sure it won't break.

Type safety does slow you down. In Ruby or perl, you can create a wash(f) method and throw a cat in the wash and either the cat comes out clean, or dead, or still dirty. But in Java, you have to create a Washable interface and painstakingly define methods like soak(), addSoap(), agitate(), spin() and rinse() and think about what it means to be washable so that someone making a Cat class can study the Washable interface and decide whether a cat should be Washable or not. That takes a lot of time and effort.

If you want a one-time use report written in an hour, then type safety will just slow you down. But if you have a bunch of programmers working on a huge system that will last for years and has to be very fault tolerant, then you can pry type safety from my cold dead hands. :-)

GlenPeterson
  • 14,890
  • 6
  • 47
  • 75
  • Using recursion instead of loops is absolutely normal in functional programming languages and the inability to change variables something their proponents consider a great advantage. The funny thing is that the same people would probably rather chew off their own arms than use XSLT. – Michael Borgwardt Aug 22 '12 at 19:21
  • Hmm... chew off my own arm or use XSLT... Tough choice... – GlenPeterson Aug 23 '12 at 12:15
  • I had to use XSLT as a general purpose language for several years. I enjoyed the challenge, but it was totally impractical. Functional programming and immutability are great things. But a local "variable" is a wonderful thing too. Scala gives you both, and I need to spend more time learning it. – GlenPeterson Aug 23 '12 at 12:23
4

Need the programer in compiled, strictly-typed need to write less code since he/she doesn't have to constantly check for correct types ( instance of operator ) since the compiler catches those things ( the same applying to misspelled variable names or uninitiated variables ) ?

I write almost exclusively in dynamically typed languages, and I almost never have to check for correct types. First, the program will throw a type or no method error if I use the wrong type somewhere, and second, I tend to use the types I intend to use where I intend to use them.

An edit on that first point based on a comment below: yes, the program will throw that error "at runtime". But since I run portions of the program easily as often as I would compile in a statically typed language (possibly more often), this isn't particularly relevant. "Runtime" doesn't mean "production", it means "when I run my unit tests". When I run my unit tests, if I am calling a method that doesn't exist on a type, I'll get a no method error.

While it is true that people make mistakes and sometimes write code that divides a char by an array, this is less common than you would think. Most code is fairly type safe by design... if it weren't mostly type consistent, it wouldn't work and wouldn't pass its unit tests.

Similarly, in my experience, unit testing doesn't need to be any more thorough in say, Ruby than it does in Java... I use unit testing to test the behavior of methods and classes, not for type checking. The type checking is implicit... type mismatches throw errors that indicate errors in my code that should be solved by better code, not by adding type checks.

A further edit based on another comment -- no, my unit testing does not have to be more extensive and I do not have to write more code to make sure I didn't misspell a variable name inside a nested conditional.

If I needed a variable to change values based on some logic branch and it doesn't because I accidentally declared a new variable, I'll catch that while unit testing behavior, not unit testing variable names and type checking. I would write the same unit test in a static-explicit language, and while I might get a compile error instead of a failed test the end result is the same: I'll see the mistake and fix the code when I run the unit test that is checking that I get the right behavior, not that I'm using the right types and variables.

If I am writing code where that kind of mistake could slip through my unit tests, my problem is not that I'm using a dynamic-implicit language, it's that I'm writing bad code with untracked side-effects. Using a static-explicit language isn't going to help me there, it's just going to give me a false sense of security about my bad code.

philosodad
  • 1,775
  • 10
  • 14
  • 2
    `First, the program will throw a type or no method error if I use the wrong type somewhere`. **At runtime**. `I tend to use the types I intend to use where I intend to use them`. **Most teamworks have several programmers, and people make errors** – Tulains Córdova Aug 22 '12 at 10:15
  • @user1598390 I tend to run programs several times before releasing them to production, so "at runtime" isn't overly relevant here. And yes, most teams have several programmers, but I can't remember ever seeing a type error in production. Type mismatches just aren't that common of a mistake in my experience. – philosodad Aug 22 '12 at 13:18
  • 3
    With at runtime **I didn't mean production**, it's just that **you have to run the code** to ( hopefuly ) find the error. Maybe type mismatches are not common, but **misspelled variable names really are**. A weak language will assume it is a new variable. This can **hide for long time** inside a nested condition, and bugs arising for this are **usually silent** and difficult to debug. **Strict languages would shout it aloud upfront.** – Tulains Córdova Aug 22 '12 at 14:36
  • @user1598390 I get the feeling that you already know what answer you want, and are not interested in different perspectives on this question. I mean, having to compile the code and having to run the code are essentially equivalent from my point of view, so that's *really* a red herring. Your question is whether you have to write more code, not whether a particular mistake is more likely to be caught. I'm not going to write a bunch of type checking code to make sure I didn't misspell something. – philosodad Aug 22 '12 at 15:27
  • 1
    @user1598390, you are conflating weak and dynamic typing. Languages like Python which are dynamic and strong will not create new variables if you misspell them, they will raise an error. – Winston Ewert Aug 22 '12 at 17:24
  • 2
    `Having to compile the code and having to run the code are essentially equivalent from my point of view`. A compiler checks every nook and crany of the code, whithout it you have to run the code with different values in order to ensure you have full coverage. – Tulains Córdova Aug 22 '12 at 17:59
  • 1
    @user1598390 `A compiler checks every nook and crany of the code` yeah except for these non-trivial things called run time errors. – pllee Aug 22 '12 at 18:20
  • Maybe runtime errors are for unit tests to catch; and typos and bad assignments, etc. are for a compiler to catch. – Tulains Córdova Aug 22 '12 at 18:30
  • @user1598390 Compilers will miss typos that are syntactically correct, and whether a language implementation is compiled or runs type checking is *not* a function of the type system. Even with compiled code in a static, strongly typed language, you can have a user interface that inserts bad values and types and need to handle such errors gracefully. I think you are confusing many issues. – philosodad Aug 22 '12 at 18:51
  • `you can have a user interface that inserts bad values` I was talking about programmer typos during the process of programming, not user typos during the process of using the application. – Tulains Córdova Aug 22 '12 at 19:00
  • I added a code sample to my question to explain it better. Sorry if I'm not using the correct terminology, but the code should be clear what I mean. – Tulains Córdova Aug 22 '12 at 19:05
  • 1
    @user1598390 I understand what you mean. I just think the answer to your question is **no**, and I've explained why: Using a dynamically typed language does not imply that you have no type checking in the pre-compiler, it doesn't require that the coder write a lot of type checking to write robust code, and it doesn't change the number or intent of unit tests. – philosodad Aug 22 '12 at 19:42
  • General note: when you vote an answer down, it is polite to explain why. – philosodad Aug 23 '12 at 04:28