58

What language, in your opinion, allows the average programmer to output features with the least amount of hard-to-find bugs? This is of course, a very broad question, and I'm interested in very broad and general answers and wisdoms.

Personally I find that I spend very little time looking for strange bugs in Java and C# programs, while C++ code has its distinct set of recurring bugs, and Python/similar has its own set of common and silly bugs that would be detected by the compiler in other languages.

Also I find it hard to consider functional languages in this regard, because I've never seen a big and complex program written in entirely functional code. Your input please.

Edit: Completely arbitrary clarification of hard-to-find bug: Takes more than 15 minutes to reproduce, or more than 1 hour to find cause of and fix.

Forgive me if this is a duplicate, but I didn't find anything on this specific topic.

Magnus Wolffelt
  • 2,373
  • 2
  • 20
  • 23
  • 11
    I'd like to see some research done into this topic! Not just "my anecdotal evidence suggests that the only language I know is king" but bug rates from large projects, and so on. – Frank Shearar Dec 01 '10 at 11:00
  • @Frank .. if you had A LOT (and I do mean A LOT) of time, you could probably mine some statistics out of ohloh, provided you could identify patches that fixed bugs from thousands of code repositories. – Tim Post Dec 01 '10 at 11:47
  • The one where only comments are allowed. No other instructions :) – Victor Hurdugaci Dec 01 '10 at 12:02
  • 4
    I think "hard-to-find" needs to be clarified. Your question and most of the answers seem to define "hard-to-find" as being equivalent to "not caught by the compiler." You mention python as having silly bugs that would be detected by the compiler. Fair enough. But those silly bugs usually aren't that hard to find. Certainly, they aren't in the same category as C++ bugs deriving from say freeing memory too soon. – Winston Ewert Dec 01 '10 at 15:15
  • @Winston Agree. – Magnus Wolffelt Dec 01 '10 at 16:21
  • @Frank Shearar, is it me, or is there a remarkable lack of research done into any question regarding programmer productivity? – Winston Ewert Dec 01 '10 at 17:04
  • @Winston as far as I know (which isn't saying much), there is precious little research into the question. – Frank Shearar Dec 01 '10 at 17:57
  • @Winston Ewert: The next question is what level of quality coding we're talking about. C++ has smart pointers, and consistent use of those will prevent premature freeing (and have other consequences). – David Thornley Dec 01 '10 at 18:22
  • You got a pretty weak definition of "hard-to-find". Perhaps you will enjoy this one: http://nighthacks.com/roller/jag/entry/at_the_mercy_of_suppliers#comments –  Dec 01 '10 at 18:29
  • @David Thornley, the problem with smart pointers is that eventually you figure out that you are attempting to create a better language inside C++. At that point, you think that perhaps you should just be using a better language. – Winston Ewert Dec 01 '10 at 18:34
  • @Winston Ewert: You should always attempt to create a better language inside the one you're using, whether by library-type functions or whatever. Boost-type smart pointers were inherent in the language as first standardized, and container template classes and `std::string` were standardized. `shared_ptr` and `unique_ptr` will be part of the language as next standardized. – David Thornley Dec 01 '10 at 19:06
  • @David, the question is the amount of effort your are spending to do so. In C++ I spend a lot of effort making sure that all of my objects were held by smart pointers. If I use another language, I get all of the benefits of smart pointers without the effort. What I realized was that I was trying with smart pointers to make my C++ more like Java/C#. If I'm spending all that effort, maybe I should just use Java or C#. – Winston Ewert Dec 01 '10 at 19:46
  • @Winston: That makes sense. Of course, if I moved to Java or C# (and we aren't porting the stuff I work on any time soon), I'd be missing things from C++, such as templated container classes and RAII. Nothing's perfect. – David Thornley Dec 01 '10 at 20:32
  • @David, generics have brought the container classes to those languages. I do miss RAII though. – Winston Ewert Dec 01 '10 at 20:34
  • @Victor, quite the opposite - it is impossible write a program that conforms to any non-trivial specification -> _all_ programs will be buggy. –  Dec 02 '10 at 17:47
  • In my experience is not the language that determines how hard a bug is to find, but the domain, data and even programming style. Yes there will be exceptions, but I don't think listing them makes for a constructive question. – ChrisF Dec 28 '10 at 15:24
  • @VictorHurdugaci so you would not expect "It doesn't work" to be a hard-to-fix bug in a language allowing only comments? –  Feb 13 '12 at 10:20
  • It probably is not only a matter of programming language, but of computer science knowledge. And weird (and productive) programming languages (like Ocaml, Agda, ...) are mostly used by programmers with strong computer science skills. – Basile Starynkevitch Jun 05 '15 at 07:35

12 Answers12

63

The more powerful the type system of the language, the more bugs will be caught at the compile time itself.

The following figure compares some of the well known programming languages in terms of the power, simplicity, and safety of their type systems. [ Source ]

alt text

*Factoring in the ability to use unsafe constructs.

C# gets stuffed into the unsafe row because of the "unsafe" keyword and associated pointer machinery. But if you want to think of these as a kind of inline foreign function mechanism feel free to bump C# skyward.

I've marked Haskell '98 as pure but GHC Haskell as not pure due to the unsafe* family of functions. If you disable unsafe* then jump GHC Haskell up accordingly.

missingfaktor
  • 3,906
  • 1
  • 24
  • 31
  • 8
    This is brilliant! –  Dec 01 '10 at 13:58
  • Interesting, I would have thought that managed C# would be higher up on the safety list than that. – rjzii Dec 01 '10 at 14:09
  • 1
    @Rob: C# _allows_ pointers. Hence the position. :-) – missingfaktor Dec 01 '10 at 14:11
  • @missingfaktor - Ah, good point! I actually haven't encountered them yet outside of informative tutorials but if they are there then there must be code out in the wild that uses them. – rjzii Dec 01 '10 at 14:16
  • 1
    Where would Eiffel be in this chart? Afaik its supposed to be very safe. – Martin Wickman Dec 01 '10 at 14:17
  • @Martin: Never played with Eiffel; No idea :-( – missingfaktor Dec 01 '10 at 14:20
  • 7
    I couldn't find Common Lisp in the graphic: `(let ((itbe '())) ... )`... – duros Dec 01 '10 at 14:30
  • IIRC, the Eiffel type system is actually a bit broken. Covariant parameters (as opposed to covariant return types or contravariant parameters) I believe. – Tom Hawtin - tackline Dec 01 '10 at 15:18
  • 4
    I don't see Ada on the chart either. – Zan Lynx Dec 01 '10 at 16:30
  • 7
    What? There wasn't any space left on the left side for PHP? – pestaa Dec 01 '10 at 16:39
  • 8
    C# allows *safe* pointers: all pointer arithmetic is checked. Therefore, I believe it should be up there with Java. – Alex ten Brink Dec 01 '10 at 16:57
  • 12
    @missingfaktor: I think C# is not well positioned. C# allows and promotes safter programming styles. It should not be measured by the worst thing it allows. – back2dos Dec 01 '10 at 17:44
  • 2
    I'm with @b2d and @Alex here - C# allows pointers, but it's safer than C++ and actually rarely used, so it should be on a par with Java. Also, I'm curious to know why Agda and Epigram are considered especially powerful - what features do they have that lend them that power? (I freely admit I have no experience in those languages, I'm just curious) – JohnL Dec 01 '10 at 18:14
  • @duros: Common Lisp has a detailed type system, and is strongly typed. It has optional static typing, so it's got to be at least at "configurable safety". Hey, it's got to be at least as good as Scheme at "abstraction safe", whatever the heck that is. – David Thornley Dec 01 '10 at 18:25
  • @back2dos: You should post your suggestion under Iry's blog post I have linked in my answer. – missingfaktor Dec 01 '10 at 19:28
  • 2
    My heavens, what a wonderful chart. Now I can figure out what language to learn next. – Bob Murphy Dec 01 '10 at 20:15
  • @JohnL: The type systems are listed as powerful, not the languages. Their operational power is listed as the least on the chart (which makes sense since they're not even turing complete). What makes their type systems powerful is that they allow type-level computation and their types can be parametrized by (run-time) values. – sepp2k Dec 01 '10 at 20:42
  • Some things seem strange to me in this chart. Since when do C# and Java have second order types? Also I don't see why C++ isn't listed as higher-kinded. – sepp2k Dec 01 '10 at 20:47
  • @Bob: And what is it? :) – missingfaktor Dec 03 '10 at 11:07
  • @missingfaktor: Oh, I feel like a kid in a candy shop. As a C/C++ guy, I want to see the other side of the world. I'd been considering Lisp and Haskell, but had never even heard of Agda. Your brain stays pretty flexible if you twist it into a pretzel once in a while. – Bob Murphy Dec 03 '10 at 23:39
  • 1
    GHC Haskell jumps up to ("pure"/"higher kinded") if you disallow improper use of unsafePerformIO. – dan_waterworth Jan 12 '11 at 07:21
  • I find the chart interesting but have to give -1 because it's simply not a good answer to the question. Presence/absence of type system features is definitely *not* the major cause of hard to find bugs. – mikera Jun 15 '11 at 11:28
  • 4
    @mikera: Sorry, but that's not really true. Type systems are nothing more or less than statically-checked guarantees about program behavior, and more features let you specify more fine-grained guarantees. That said, the other axis is arguably more relevant, and many languages on the lower half of the chart have so many unsafe loopholes that type system features don't really offer much benefit. – C. A. McCann Jun 15 '11 at 14:57
  • 1
    Where's go on this list? :P – crazy2be Jun 15 '11 at 17:27
  • @camccann: Not all type systems are static. In Common Lisp, for example, any data object has full type information, but it isn't normally available at compile time. – David Thornley Jun 15 '11 at 18:00
  • 2
    @David Thornley: My apologies for lack of clarity. Formally speaking, "types" in the sense of metadata tags describing an object are a completely separate concept from the "types" in the sense I was using. The two are orthogonal--static type systems need not have all info known at compile time, and CL-style dynamic types can be implemented manually within such a system. Dynamic languages can be seen as the extreme case where an "existential-with-metadata" is the only static type, which is why the graph above labels them as "unityped". – C. A. McCann Jun 15 '11 at 18:17
  • 1
    @camcann: Thanks. The more I see discussion about type systems, the more I realize I don't know what everybody's talking about. I think I need to study types some more. – David Thornley Jun 15 '11 at 18:25
  • 2
    @David Thornley: You're very welcome, and yes, there's a lot more to type systems than is evident in what filters through to the mainstream. Just to give you some idea, at the "opposite" extreme are type systems capable of encoding arbitrary pre/post-conditions, such that a function together with its type serve simultaneously as a formal specification, an implementation of that spec, and a proof of correctness, all fully verified at compile-time. Add extreme safety to the point of giving up Turing-completeness, and that's the top-right corner of the diagram above. – C. A. McCann Jun 15 '11 at 18:56
  • It sounds to me like hard to find bug implies time wasted bug fixing. You could argue that the extra time taken to make something pure or fully type safe counts as time debugging for certain type of bugs preemptively. Which, unless you are doing critical software, might total up to more time then its worth your money. – Didier A. Jun 12 '16 at 23:44
  • Where would F# be in this chart? – Per Quested Aronsson Nov 14 '18 at 21:43
  • I realise space is at a premium, and that the title says "Static Type Properties", but it's not accurate to describe Python/JavaScript/etc as "untyped". It should really say "Untyped/dynamically typed", or perhaps "No static typing". – Max Barraclough Apr 12 '20 at 14:37
  • @MaxBarraclough, "untyped", "unityped", "typed" have well defined meaning in type theory. The terms "statically typed" and "dynamically typed" refer to the same things, but in a different context – everyday software engineering. I don't know why the person who made the graph mixed the two dialects. – missingfaktor Apr 15 '20 at 17:20
20

In my opinion Haskell helps you avoid some common sources of errors:

  • it's purely functional: functions cannot have (unintentional) side-effects and this makes multicore programming easier and less error-prone
  • it is strongly typed: you can not e.g. accidentally mix bool, char, int and float values
  • it's statically typed: many programming errors are caught at compile time
  • null is not part of value type definitions: by this you avoid the billion dollar mistake
  • there are a lot of ready-made higher-order functions which you can reuse instead of writing your own, possibly faulty, implementations
  • it has a garbage collector: memory errors are almost eliminated (except for "space leaks" due to its lazy evaluation strategy)
LennyProgrammers
  • 5,649
  • 24
  • 37
  • 11
    I won't downvote this, but I'm tempted to because it doesn't fit the criteria. It's supposed to allow "the average programmer to output features" with a minimal bug count, but the average programmer, to put it bluntly, can't make heads or tails of Haskell in the first place. – Mason Wheeler Dec 01 '10 at 12:51
  • Hm, i see your point. I am not sure whether Ada is also for this kind of "average programmer". – LennyProgrammers Dec 01 '10 at 13:04
  • 5
    Many good points, but while removing some classes of error (unintended side effects, unexpected type conversions) Haskell adds a whole new class of error: space leaks. (Also although there is no `null`, there is `undefined`, which is a member of every type.) – j_random_hacker Dec 01 '10 at 13:15
  • 5
    @Mason: If you don't write in it, you can't have bugs int it :) – Michael K Dec 01 '10 at 13:38
  • @Michael: Yes, but the OP specified producing features, not merely avoiding bugs. ;) – Mason Wheeler Dec 01 '10 at 13:51
  • 2
    I guess there's no such thing as a free lunch - you can have easy-to-find bugs, or easy-to-write code, but not both :) – Benjol Dec 02 '10 at 05:52
  • 6
    @Mason what exactly is an “average programmer”? The question begins with “what programming language...”, not “which among C, C++ and java...” ;) – Agos Dec 02 '10 at 09:19
  • 2
    @Mason Wheeler, I'd call myself an average programmer, and I started learning haskell not too long ago. It was pretty easy to read early on, and after a couple of months I can write useful programs in it, so it's certainly not beyond the grasp of the average programmer. – Cercerilla Jun 15 '11 at 15:42
  • 1
    @CodeninjaTim: Ah, but from what population are you computing that average? I suspect the comment you're replying to is setting a much lower bar for who is included among "programmers". Do you think the sort of programmer whose code ends up on The Daily WTF would be able to produce anything at all in something like Haskell? – C. A. McCann Jun 15 '11 at 17:38
  • 1
    @camccann: I doubt that a programmer whose code ends up on thedailywtf would be able to do much useful with haskell, but I wouldn't call them average – Cercerilla Jun 15 '11 at 20:51
  • 1
    @CodeninjaTim: Certainly not, but they'd certainly pull the average down! The only question is how far. – C. A. McCann Jun 15 '11 at 21:09
  • I'm just learning Haskell, but I've heard it said that its lazy evaluation is hard to reason about, especially in terms of memory usage. Am I just restating what @j_random_hacker said? – GlenPeterson Jan 22 '13 at 13:01
  • `undefined` is orders of magnitude less bad than `null`, and comparing them without explanation is just downright intellectually dishonest. `undefined` cannot be touched / expected, if you touch it your program blows up in a way that cannot be caught. `null` on the other hand can and IS used as a replacement for `Maybe` / `Nothing` which is just downright evil. On top of that EVERY turing complete language has `_|_` because a nonterminating computation is `_|_` and you cannot guarantee termination of an arbitrary function in a turing complete language. – semicolon Jul 05 '16 at 17:14
19

Traditionally the hardest to find bugs are race-conditions in multi-threaded applications as they are

  • almost impossible to reproduce
  • can be very subtle

Hence you need languages that manage the parallism for you as much and unintrusively as possible. These are not yet mainstream. Java does some, but leave you with the hard part.

To my understanding, you need a functional language since the "no sideeffects" is the thing that in the first place makes the two bullet points go away. I've seen that work is ongoing in transparently making Haskell an efficient multi-thread language, and I believe Fortress is designed from the ground up to be an efficient parallel language.


Edit: In Java Executors handle even more of the hard parts. You need to make the individual tasks conform to the Callable interface.

  • 5
    ++ Race conditions. You can say that again. – Mike Dunlavey Dec 01 '10 at 18:12
  • Yeah. Bear in mind that parallel computing in general is hard, even with language assistance. (Common Lisp macros are hard, despite a lot of language support, because what they do is very powerful. Same principal.) – David Thornley Dec 01 '10 at 18:28
  • What about Erlang? – Malfist Dec 01 '10 at 21:43
  • @Malfist, I do not know enough about Erlang to answer that. Perhaps you should open a question if you really want to know? –  Dec 01 '10 at 23:19
  • 2
    Erlang is a functional programming designed to make multithreading simple and safe. You don't share variables, you pass messages. Read it's wikipedia page. – Malfist Dec 03 '10 at 14:15
  • @Malfist, I know _that_. That does not mean I know it well enough to answer your question. –  Dec 03 '10 at 17:20
  • @Mike, Racraece c condiondittioionsns ;-) –  Feb 18 '11 at 15:59
  • @Thorbjørn: OK, I give up. What does it mean? – Mike Dunlavey Feb 18 '11 at 19:14
  • @Mike, two threads trying to print out "race conditions" on the same output unit :) –  Feb 18 '11 at 19:15
  • @Thorbjørn: and here I thought it was Latin, or Romanian, or something :) – Mike Dunlavey Feb 18 '11 at 19:27
  • Race conditions are really hard to manage in almost *all* these languages! Languages that stress immutability help you avoid creating race conditions by accident, but a design for any meaningful parallelism usually requires dealing with some race conditions. I know Scala has Akka, but Akka objects are mutable, so it is a helpful tool, but it not protection. If someone asks the Erlang question, please post a link to it here! – GlenPeterson Jan 22 '13 at 13:05
  • I just asked the question about Erlang here: http://programmers.stackexchange.com/questions/184451/in-what-meaningful-ways-does-erlang-prevent-race-conditions-in-concurrent-progra – GlenPeterson Jan 22 '13 at 13:36
14

Ada is designed so that as much as possible is caught at compile-time rather than run-time. What this means is that it often takes about 10x longer to get a program in Ada to compile than the equivalent would in Java say, but when it does compile you can be much more confident that whole classes of bugs will not manifest themselves when the program's run.

Mark Pim
  • 1,511
  • 1
  • 8
  • 9
  • 8
    +1 for noticing, correctly, that Ada catches things in the compiler that other languages ignore. -1 for the assertion that this means it takes 10x longer to get an Ada program to compile. Ada rewards the programmer who DESIGNS!!! his code, who THINKS!!! about what he is doing before he starts madly typing. My personal experience, doing production programming in Ada for defense work, was that it didn't take significantly longer to get Ada code to compile than it takes C/C++ or FORTRAN, but the Ada code had significantly less trouble later. Pratt & Whitney noticed something similar. – John R. Strohm Dec 01 '10 at 14:06
  • 1
    @john r strohm, from what I understand, he is not talking about time it takes for the compiler to compile code, rather the time to make the code compilable. – Malfist Dec 01 '10 at 21:39
  • oh agreed about getting the code compilable. I can remember quite a lot of sexist comments made by programmers learning the language about its nit picking. Usually along the lines of Well, if you do name a language after a woman... – Michael Shaw Dec 02 '10 at 12:01
  • @Ptolemy, if boats can be named after women (except apparently for US carriers) then programming languages can too. Rather have it named "Ada" than "USS Ronald Reagan" :) –  Jul 04 '11 at 09:13
  • @Malfist: Let me clarify it for you. My personal experience was that it didn't take significantly longer to get Ada code COMPILABLE than it takes C/C++ or FORTRAN. By that, I mean "It compiles without errors or warnings." – John R. Strohm Jan 22 '13 at 12:49
  • 2
    Once I got over the learning curve, I actually got pretty fast at writing Ada code -- after I had spent a good deal of time thinking through the design. Ada is most definitely NOT a hacker's language. I work in Java nowadays, and some of the stuff I'm seeing in my current projects actually makes me miss Ada a little bit (never thought I'd say that). – James Adam Jan 22 '13 at 16:13
  • @Mark Pim: Back in the day I had the same experience with C versus Pascal: once a C program compiled, I had to spend quite some time debugging. Once a Pascal program finally compiled --- the compiler was much more picky --- the program often worked immediately. – Giorgio Mar 09 '15 at 20:45
9

This is a difficult question because most bugs aren't the fault of the language itself - rather they are the fault of developers making mistakes in how they use the language.

I believe there are several aspects of language features that affect the likelihood of bugs:

  • Interactivity - dynamic languages with REPLs encourage interaction / experimentation with running programs and much smaller code/test cycles. If you believe that iteration is a good way to discover clean simple solutions and detect/eliminate bugs then this would tend to favour interactive languages.

  • Expressiveness - if code is shorter and has less boilerplate / incidental complexity then it's easier to see bugs / logic errors.

  • Type safety - the more compile time checking, the more bugs will be caught by the compiler so in general type safety is a good thing. However these usually aren't hard to find bugs - even in a fully dynamic language the wrong type in a data structure will usually cause a very obvious runtime error, and TDD almost always picks up these kind of bugs.

  • Immutability - a lot of hard bugs are due to complex interactions of mutable state. Languages that emphasise immutability (Haskell, Clojure, Erlang) have an enormous advantage by eschewing mutability

  • Functional programming - functional approaches to writing code tend to be more "provably correct" than object oriented code with complex sequences of effects / interactions. My experience is that FP helps avoid tricky bugs - I believe there is some academic research somewhere that I can't currently find that backs this up.

  • Concurrency support - concurrency problems are particular hard to detect and debug which is why this is so important. Anything that requires manual locking is ultimately doomed to fail (and this includes pretty much every object oriented approach to concurrency). Best language I know of in this regard is Clojure - it has a unique approach to managing concurrency that combines software transactional memory with immutable data structures to get a novel, reliable and composable concurrency framework. See http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey for more insights

Sridhar Sarnobat
  • 282
  • 1
  • 10
mikera
  • 20,617
  • 5
  • 75
  • 80
  • People like me who are passionate supporters of functional programming appreciate this answer. Expressiveness is your friend. – Sridhar Sarnobat Jun 05 '15 at 05:53
  • 2
    Best answer so far! I think this is backed by the following two analyses of bug frequency: http://deliberate-software.com/safety-rank-part-2/ and http://macbeth.cs.ucdavis.edu/lang_study.pdf. They both show that the purer, the more functional, the more expressive and the safer the language the less bug it has. Similarly, they both show that Clojure and Ruby escape the Safety rule, probably indicating that Interactivity has an equal impact as you pointed out. – Didier A. Jun 13 '16 at 00:02
  • 1
    @DidierA. unfortunately the ucdavis link is broken (with no wbm archive) - I think you got it from [Prem Devanbu's page](http://web.cs.ucdavis.edu/~devanbu/) which now points to an updated link: [A Large Scale Study of Programming Languages and Code Quality in Github](http://baishakhir.github.io/uploads/fse2014-lang_study.pdf) – icc97 Oct 30 '18 at 17:38
7

First a definition: a hard-to-find bug, as I understand it, is a bug that can be reproduced but the cause is hard to find.

Probably the most important aspect is what I would call narrowness, i.e. how far can a bug escape, how large is the scope a bug can potentially influence. In languages like C, a bug, e.g. a negative array index or uninitialized pointer, can affect literally everything everywhere in the whole program, so in the worst case, you have to check everything everywhere to find the source of your problem.

Good languages in that regard support access modifiers and enforce them in a way that makes it hard or impossible to bypass them. Good languages encourage you to limit the scope of your variables, instead of making it too easy to have global variables (e.g. "everything not explicitely declared is a global variable with a default type and value").

The second important aspect is concurrency. Race conditions are generally hard to reproduce and therefore hard to find. Good languages offer easy-to-use synchronisation mechanisms, and their standard libs are thread safe where necessary.

This already completes my list; other things like strong typing help to catch bugs at compile time, but those bugs probably wouldn't be hard to find later.

Considering all that, I'd say that Java and C#, and many other languages in the JVM and .net world, are suitable to avoid hard-to-find bugs.

user281377
  • 28,352
  • 5
  • 75
  • 130
  • Manual locking might look to be an "easy-to-use synchronisation mechanism" but it's really only "simple to use but you're in for fun times as you chase down that deadlock". And, well, you can do Actor-based concurrency in quite a few languages. – Frank Shearar Dec 01 '10 at 15:23
  • Frank: at least locking is simple enough so everyone can do it without spending days, figuring out which API to use etc. – user281377 Dec 01 '10 at 15:39
  • Then there's the viewpoint that a concurrency solution that's "simple enough so everyone can do it" is like giving table saws to pre-schoolers. – David Thornley Dec 01 '10 at 18:30
  • @David: I see your point, but in many cases, a simple solution is really all that it takes. For example, consider a servlet used by only a handful of users, which has to use a shared resource (e.g. the database connection). Without synchronisation, race conditions happen every now and then; but it's not exactly rocket science to put all database access operations into a synchronized(connection){} block. – user281377 Dec 01 '10 at 22:30
  • +1 For this definition "how large is the scope a bug can potentially influence". I had some very nasty bugs with dynamic languages where an object of the wrong data type got very far in the code (thanks to duck typing) before manifesting itself as a bug. – Giorgio Mar 09 '15 at 20:47
7

Since Excel is the most widely used DSL, I'll go with Excel. (excluding VBA of course)

It fits the bill:

  • It's always easy to reproduce (here's a spreadsheet - it's not working)
  • It's pretty easy to find the bug, as it's totally "functional" - start with the cell that's wrong and trace back all of its dependencies.
Scott Whitlock
  • 21,874
  • 5
  • 60
  • 88
  • This might be true as long as you don't add up easy-to-find bugs. – mouviciel Jan 22 '13 at 10:57
  • +1 A bit cheeky since Excel is data, not a language. Gave me a good laugh :) – recursion.ninja Apr 04 '14 at 19:04
  • 2
    @awashburn - oh, I don't know. I think it qualifies as a language. Each cell is a "variable". Each variable is declaratively set as either a literal (such as `123` or `ABC`) or a function (`=SUM(A2:A5)`). Excel then evaluates all the variables, figuring out what order to solve dependencies, etc. It's certainly not just data. – Scott Whitlock Apr 04 '14 at 19:45
  • 2
    I retract my statement, it turns out that Excel is Turing Complete... I learned something wholly unsettling... – recursion.ninja Apr 04 '14 at 20:26
  • 1
    "...the true [Lisp] master realizes that all data is code." Perhaps this applies to Excel as well, ewirdly enough. http://blogs.msdn.com/b/sriram/archive/2006/01/15/lisp-is-sin.aspx – James Mishra Mar 09 '15 at 20:09
5

The less powerful a language is, the less options it gives you to shoot your own foot.

High-level languages like Java and C# will produce less bugs than low-level languages like C++.

Having said that I believe Java is more secure than C#. Java is artificially limited so that an average programmer without advanced knowledge can master it and produce stable programs.

  • 4
    +1 for "The less powerful a language is, the less options it gibes you to shoot your own foot." – Michael K Dec 01 '10 at 13:39
  • The chart from missingfaktor seems to say that C# and C++ are on equal "footing" as far as being able to shoot yourself there goes and elevates Java above that. Not that I agree with that part of the chart, though. You are forced to go through hoops to do some C# shooting. – Jesse C. Slicer Dec 01 '10 at 14:32
  • 6
    Safety and power are not inversely proportional (which is what you seem to think ;-) Haskell, for instance, is EXTREMELY powerful and yet has very few ways to shoot yourself in foot. – missingfaktor Dec 01 '10 at 14:43
  • 3
    If the language is weak, you just need a bigger foot. –  Dec 01 '10 at 18:23
  • 7
    @missingfaktor, that is because it is a side effect to shoot yourself in the foot. –  Dec 01 '10 at 18:23
  • @Thorbjørn: LOL. Good one. :D – missingfaktor Dec 01 '10 at 19:41
  • Homer Simpson said it best: "Max Power". Feet blown off? _Make them carry you._ – chiggsy Dec 10 '10 at 07:49
3

What language, in your opinion, allows the average programmer to output features with the least amount of hard-to-find bugs?

In my opinion, Delphi. Being based on Pascal, the language is simple and intuitive enough for the average programmer (or even inexperienced coders) to pick up easily, and its rich tool and library support make most bugs easy to find.

  • Strong typing and a strict compiler that catches many common errors.
  • Intuitive syntax that doesn't encourage common errors. ("The World's Last Bug," if (alert = RED) {LaunchNukes;}, will not compile, for example.)
  • A well-designed object model that eliminates many of the common C++ OOP errors.
  • Bounds checking and range checking built in to the language, drastically reducing the chances of security problems.
  • Probably the fastest compiler known to man, which increases your productivity and makes it harder to lose your train of thought while waiting on a build.
  • The debugger Visual Studio's debugger wants to be like when it grows up.
  • Leak tracking built directly in to the memory manager, making finding and fixing memory leaks trivial.
  • A large, mature standard library providing prebuilt and pre-tested ways to accomplish common tasks without having to build your own, possibly buggy implementations.
  • Ships with useful tools, such as a powerful logging system and a profiler, to make tracking down problems easier.
  • Strong community support for common issues that aren't in the standard library, including a powerful third-party concurrency library.
Mason Wheeler
  • 82,151
  • 24
  • 234
  • 309
  • I am a Delphi jockey from way back, but it went away from it's Pascal roots when it allowed me to typecast anything to anything else, a la C/C++: `var I: Integer; Pointer(I)^ := $00;` – Jesse C. Slicer Dec 01 '10 at 14:36
  • 1
    @Jesse: Perhaps, but I see that as a necessary concession to pragmatism. Kernighan made a lot of good points when he wrote *Why Pascal is not my favorite programming language.* Typecasts are necessary to get a lot of important low-level things done. But one of the strengths of Delphi is the way its libraries encapsulate low-level details and make most of the unsafe pointer and typecast stuff unnecessary. – Mason Wheeler Dec 01 '10 at 15:27
  • I don't disagree that it may be necessary - but claiming Strong Typing is somewhat negated by this. Original Pascal didn't allow such shenanigans and therefore was strongly typed. But I wouldn't go so far to call Delphi weakly typed - it's sort of 'medium-well typed'. – Jesse C. Slicer Dec 01 '10 at 15:29
  • 1
    @Jesse: Didn't the original Wirth version of Pascal allow variant records? IIRC they eventually became so commonly used to subvert strong typing that Borland and others decided to just put typecasts in to make it simpler because everyone was doing it anyway. – Mason Wheeler Dec 01 '10 at 15:38
  • http://en.wikipedia.org/wiki/Pascal_(programming_language)#Divisions and http://en.wikipedia.org/wiki/Pascal_(programming_language)#Criticism as well as http://www.pascal-central.com/ppl/chapter3.html seem to indicate it was part of the first standard in 1983. I do see some references by Wirth which seem to date to 1974, so I'd say yes it did. I think the problematic part was allowing it to be subverted as such (i.e.the variant fields taking the same memory, like unions in C). If they were simply used as a scoping mechanism and the memory layout were for the superset, it'd be stronger typed. – Jesse C. Slicer Dec 01 '10 at 15:52
  • @Jesse, I believe that happened already in Turbo Pascal. –  Dec 01 '10 at 23:16
2

One thing to take into account is the turn around time.

For the last five years or so, I've mainly developed web applications in java (JSF, Seam, etc.). Recently I got a new job, and we're using Perl (with Catalyst and Moose).

I'm way more productive in Perl, than I was in Java.

Not needing to compile and (hot)deploy, is one reason. I also find that writing use cases is easier, as it can be done in a more iterative way. And the frameworks in Java seem to be unnecessary complex, at least for the projects I've been involved in.

I guess the number of bugs in my Perl code is more or less the same as the number of bugs in my Java code, it might even be higher. But, I find et easier and faster to find and fix these bugs.

slu
  • 150
  • 4
1

Perhaps surveying the number of tools available for static and dynamic code analysis for every programming language could give an idea. The more tools for a language, it is more likely the language is either very popular among users or very popular in generating hard to find bugs. But I am unable to get Google point me to any study made on this subject. It should also be noted that some languages such as C can be used to work around the underlying hardware bugs as well as work around the wear and tear of the hardware as it ages.

vpit3833
  • 1,330
  • 8
  • 11
  • 1
    "work around the wear and tear of the hardware as it ages"...? – j_random_hacker Dec 01 '10 at 13:20
  • I have read that some Unix OSes that run on mission critical machines check for the health of the CPU, RAM and such other hardware. http://serverfault.com/questions/56192/is-there-any-cpu-health-testing-software discusses about this to some depth. If some lines in a RAM module become faulty over time, those faulty modules will not be used by the OS and it will not report them in the total physical memory available. Such things could be done on other hardware as well. – vpit3833 Dec 01 '10 at 19:06
  • That's an interesting tidbit, but I don't see how it's relevant here. Also nothing in your link mentions these self-repairing Unix OSes -- it just talks about ways to stress-test a PC's hardware. – j_random_hacker Dec 02 '10 at 06:22
  • 1
    I mentioned it to mean that programs alone might not the sources of bugs, it could be the hardware or other external factors as well. – vpit3833 Dec 02 '10 at 09:06
1

Instead of talking about languages what about talking about language-features

  • java forces you to think about exceptions (throws ...) and you must either publisch or handle these exceptions. Does that realy prevent me from forgetting errorsituations or am i using more exceptions that are derived from SystemException that do not need this handling?
  • what about "design by contract" (http://en.wikipedia.org/wiki/Design_by_contract) that forces me to think about pre and postconditions. I have read that is now possible with c#-4.0.
k3b
  • 7,488
  • 1
  • 18
  • 31