| There are two ways to deal with bugs. Correcting them, and avoiding them. ... Of these two, the only one that is significantly influenced by the structure of programming languages is avoidance. This is an interesting statement to me, and one that I think may be telling towards the author's experience as a programmer. This is not my way of saying he is a poor or inexperienced programmer! I skimmed through a few other articles on the site and what stood out to me is that he is heavily "academic." Some of the best programmers I have worked with had deep academic experience and were quite adept at writing fast, concise, correct code in many different languages. What stands out to me is the absence of something that (as is my personal observation) most experienced programmers in non-academic settings begin to realize at some point... While avoiding bugs (by, for example, choosing a language with strict type-checking, or immutable data/vars) is quite important, writing code that can be easily corrected is arguably just as important! In regards to just the use of a programming language, this comes down to choosing a careful balance of constructs - syntax, features, naming, etc. Coding standards for a project or organization are not just there to stoke somebody's ego or cater to the "lowest common denominator". Well-chosen standards and conventions are there to simultaneously avoid bugs and make code easier to debug and maintain - which is what one must do to make corrections! It is therefore crucial to insist on it when choosing (or designing) one. This sentence is what really drove me to comment: No programming language can prevent all bugs. Not even most bugs. In practice, I have even found that constructs and limitations that are intended to prevent bugs of one type can lead to bugs of some other type. In the worst cases, these limitations can lead to programmers making code that is much more verbose and complicated, which, of course... leads to more bugs that are harder to correct. IMO, one should choose a language based on many, many more criteria than "avoidance of bugs." Personally, one of my top criteria is to choose a language with which those who will write and maintain the software (now and in the future) are going to be most productive. |
The easiest to correct errors are the ones that are detected as early as possible.
> No programming language can prevent all bugs. Not even most bugs.
Sure. No programming language can prevent you from misunderstanding a specification. But some languages can prevent you from missing out corner cases in your case analysis, or from redundantly writing overspecific code that works in essentially the same way for a wide range of data types.
> In practice, I have even found that constructs and limitations that are intended to prevent bugs of one type can lead to bugs of some other type.
I have no idea what you are going on about. What kind of bugs do features like algebraic data types (Haskell, ML), smart pointers (Rust, to a lesser degree C++), effect segregation (Haskell) and module systems (ML, Rust) lead to? I can only see the bugs they prevent.
Normally, the kind of feature that "leads to bugs of some other type" does not try to prevent bugs in first place, just mitigate their consequences. For example, bounds-checked array indexing does not try to prevent programmers from using wrong array indices, it just turns what would be a segfault into an IndexOutOfRangeException.
> Personally, one of my top criteria is to choose a language with which those who will write and maintain the software (now and in the future) are going to be most productive.
I see writing buggy code as negative productivity. So a language that gives you the illusion that you are writing correct code, when you in fact are not, actually makes you less productive.