13 ms·
To type or not to type: quantifying detectable bugs in JavaScript
- xntrk 9y agoThe author over looked flow-typed which I believe is an analog of DefinitelyTyped.
- sAbakumoff 9y agoMy vision of it is Flow and TS and stuff prevent 15% of bugs that the beginner and intermediate level developers typically make, but engineers on the advanced and higher levels avoid these bugs by just writing a good code in any language they use.
- faceplanted 9y agoTrue, but a lot of those people would rather use a safer language to prevent those bugs than write preventative code every single time, or remember to replace built in language features with their own functions every time.
- Gys 9y agoSo it helps developers that need it and does not get in the way of developers that don't ? Then its a win without any downsides.
- dfischer 9y agoThat's an assumption for a best case scenario vs optimizing for the worst. I rather optimize for the worst, especially in a team; and furthermore a company with growth.
- oelmekki 9y agoI've been writing js professionally for more than ten years, and I totally love flow. Sure, it doesn't happen that often that I feel like I've caught with it a bug I wouldn't have without it (not even sure how you can tell one from the other, when you correct a type check error), but the most notable effect is the release of tension : I don't have to double check everything I write, I can rely on the type system to report obvious problems. If anything, I think flow does not go far enough, compared to compiled languages with type systems. The fact that it allows to mix typed and non typed code is error prone, and there are annoying edge cases, like the spread variables not being correctly checked for (this can cascade quickly, when passing properties in react). I would love to see types as a core part of the language, with native browser tooling.
- sAbakumoff 9y agoThanks, that's interesting experience!
- noir_lord 9y agoSimilar experience with typescript, the win is not having to make room in headspace for things the machine can handle.
- koolba 9y agoNo amount of good code will prevent a typo in a property name that's only encountered on the edge case of an edge case. It's arguably that 100% test coverage could catch such a bug but that's neither always possible nor cost effective. Static type checking is for catching exactly that sort of thing.
- zihotki 9y agoEven advanced and higher level developers can easily make the same mistakes as beginners or intermediate given that the code base is big enough and there are many people working on it. The probablility of that is lower but not 0. As an example you can look at quotes from MS guys, they said that it was benefitial for them to create TypeScript. And from my experience many MS engeneers are at very good level.
- ComputerGuru 9y agoOh yes, the old “I’m too good to need help from no stinking compiler” argument.
- sAbakumoff 9y agoI never mentioned my level, didn't I? :-) In fact our team is going to switch to TS and I just don't have any other option but start using it. I am OK with that, I guess.
- Can_Not 9y agoI dunno man, it sounds more like an intervention than a switch.
- sAbakumoff 9y agoThe best comment in this thread!))
- gldalmaso 9y agoWon't most code bases be written by teams consisting of some or even most beginner and intermediate level developers? My impression is that most companies experience a shortage of talent such that they take in greener members with each passing year. Ideally they should have the best conditions to turn out good quality code before they get to an advanced level. The tooling plays a big part.
- watwut 9y agoRevolutionary complement: if your definition of talent excludes junior developers, there won't be any seniors 10 years later. Every single senior was junior few years ago. Moreover, companies are biased more against older people then young. Which gives us few yes when we are hiring magically appearing seniors - after they got experience (elsewhere) and before they are old.
- Eridrus 9y agoTo not make type errors you not only have to be a perfect typist and completely engaged all the time, you also need to be an expert in the part of the system you're developing.
- preordained 9y agoDon't you just need to to actually use/test your code? Don't you need to do this in a statically typed language as well?
- lmm 9y agoOften you don't. When you're really leveraging the type system, if it compiles it'll be correct. You might need to test the actual business logic, but realistically that ends up being a small proportion of the code you write. People don't like talking about how type systems let you write fewer tests, perhaps because it makes them sound like cowboy coders, but honestly it's a huge advantage.
- Can_Not 9y agoNot only can you write more precise tests (because you don't have to worry about run time crashes from type errors or logic errors from type mismatches) but your tests themselves are also type checked.
- dahauns 9y agoI wouldn't consider engineers who think they "just write good code" and won't make those mistakes "advanced" or on a higher level. They have yet to learn one of the most important lessons.
- coldtea 9y ago>but engineers on the advanced and higher levels avoid these bugs by just writing a good code in any language they use. Belief that one can just "write good code" and you don't need types/tooling/linting etc is a sure sign of a still inexperienced developer. Actual senior developers are much more humble and use all the help they can find.
- sAbakumoff 9y ago>Actual senior developers are much more humble and use all the help they can find. sure, this is raison d'etre of package managers like NPM.
- lllr_finger 9y agoTyping systems for dynamic languages shouldn't be viewed as crutches for the inexperienced dev - experienced devs should seek them out when the ROI is there. If any level of your tech stack offers you guarantees, use them so that you have less code to write. Less code is less opportunity for bugs and faster development.
- sAbakumoff 9y agoI am wondering what level downvoters have :-)
- marksomnian 9y ago"I think you're arrogant in suggesting that only beginner and intermediate programmers make these mistakes" level. Yes, advanced programmers make these mistakes too, and they find tools like this helpful in catching them. That's why Microsoft created TypeScript. That's why Facebook created Flow. Facebook and Microsoft are two companies I wouldn't call beginner or intermediate.
- sAbakumoff 9y ago1. Never I suggested that advanced programmer don't make mistakes. They do. Beginners just make more and/or more expensive mistakes. 2. Never I suggested that MS and FB are beginners.
- mannykannot 9y agoThis is an issue on which self-serving opinion, on both sides, predominates, so this study is very welcome. If you think it is flawed, do your own study.
- mamcx 9y ago> writing a good code AND using good code. If a "Expert" have the option between use something that solve more problems better than other, is NOT a expert to not use it. Is just masochist.
- sAbakumoff 9y agoAgreed, re-using a good code is one of the most important skills.
- Can_Not 9y agoEngineers on the advanced levels are concerned about lightning fast and safe refactoring and resilience against spaghettification when passing on their code to other team members or outsiders of unoptimisticly unpredictable skill sets.
- pron 9y agoIt's great to see the wealth of data we have thanks to open-source being used for such studies, and we should have more. More concretely, I can see why actual benefit could be either greater or smaller than the reported result: Greater: One of the advantages of types is that they impose a certain discipline and organization on the code. This global quality may have a significant impact that isn't measured in this study, which focuses on a very local effect, and so the actual effect may be significantly greater. Smaller: Not all bugs are created equal, and there's actually a huge variability in both the effort bugs require to fix and in their impact on total product quality. If the 15% reduction is mostly in "cheap" bugs, then the actual effect may be significantly smaller. We should try to create a taxonomy of bugs, classified by kind, domain, project size, cost to fix and impact. This would help us get a better picture of the overall effect of various techniques.
- koblas 9y agoThe next 5% of bugs can be taken care of by a handful of goodl tslint rules. - missing awaits - using 'this' in the wrong context - shadowing variables Those errors make for valid code that's wrong in many cases.
- camus2 9y agoit doesn't catch type coercion, missing properties, ... a whole class of bugs that don't yield runtime errors.
- sfvisser 9y agoType systems aren't just about adding static type annotations to your otherwise dynamically typed code to catch a few bugs. If you embrace the type system and start modeling your domain types with the natural invariants in mind you start seeing the real benefit. Once you enforce the invariants of your data in the types you'll notice entire categories of bugs will impossible to introduce. Abstraction barriers between different parts of your codebase will become more clear and impossible to break. Otherwise complicated architectures will become easy to express. Types change everything.
- kybernetikos 9y ago> If you embrace the type system and start modeling your domain types with the natural invariants in mind you start seeing the real benefit. Except that few type systems have the capability to do this in a reasonable way that doesn't lead to horribly contorted code full of type-induced damage. Just look at the difficulties that people have trying to express code at a higher level of abstraction like partial application, currying, generic composition, etc (as in fantasy land or ramda) in typescript. If you're acclimatised to working in a specific type system, you'll probably never notice the areas where it stops you legitimately abstracting. > entire categories of bugs will impossible to introduce. This is true. > Otherwise complicated architectures will become easy to express. This, I think, is false. In fact many complicated architectures (depending on your type system) will become impossible to express, and to some extent this is a feature rather than a bug.
- skybrian 9y ago"Impossible to express" seems a bit much, but you might have to write your own Any type.
- deleted 9y ago[deleted]
- aczerepinski 9y agoThere's a great talk on this subject by Richard Feldman from Elm Conf. I haven't used typescript so I'm not sure if the techniques translate well. https://www.youtube.com/watch?v=IcgmSRJHu_8 https://www.youtube.com/watch?v=IcgmSRJHu_8
- dpratt71 9y agoAs we have recently adopted TypeScript, this is a nice affirmation, but preventing bugs is only part of the benefit and I'm not sure it's the most important part. TypeScript, in conjunction with a code editor that supports it, significantly improves the code editing experience. Sometimes I still have to chase down documentation, examples, etc. to figure out how to use something, but it happens far less often. In general, I feel like I can code faster and with more confidence. I assume all this is also true of Flow, though I've never used it.
- seanmcdirmid 9y agoThe killer apps of static types are code completion, documentation, modelling rather than safety and performance. This makes TypeScript's unsoundness much more acceptable, though many in the type systems community still have a difficult time grocking this.
- taeric 9y agoPretty sure the first code completion programs were in dynamic languages. With many environments, you literally asked the object what methods it had. Same for documentation.
- seanmcdirmid 9y agoThe first code completion system was in Alice Pascal circa 1986. Statically typed. After that, it appears in production for the first time in VS 97, still using static type information. It wasn't present in smalltalk IDEs before then, or LISP ones.
- taeric 9y agoI'll confess this surprises me, but not overly so. I'll try to find what I was thinking of. Primarily, I thought you could do live reflection in lisp machines. Which is basically this.
- 9y ago
- kerpele 9y agoMy team is in the process of switching a React app to TypeScript and an interesting issue popped up just today. I was refactoring some component to be able to implement a new feature. At some point of the process I managed to break the component so that it would not render, only complained about an object not being a proper React component and that I was probably trying to render a bunch of items that should be put in an array. The error was reported by something deep inside React so I couldn't tell from the stack trace where the issue was. After trying to find the problematic bit by trial and error (lots of undo/redo there) I finally decided to just move the whole file to TypeScript. 20 minutes later I was done and the error was gone. I don't even know what I did to fix it but obviously I had to change quite a few things here and there to get the file to compile cleanly with decent typing and one of those type errors must have been the key.
- revelation 9y agoAnd it prevents 100% of the time wasted on testing something in a browser (or generally at runtime) only for it to fail for some trivial type mismatch. These things don't typically make it as bugs into production code but are a big time sink with dynamic languages.
- marcosdumay 9y agoI would really like a "strict mode" on my browser developer tools that would cause any problem in Javascript to stop everything on the page and write a huge "Hey, your code can not run because it had a parsing error at this line!" at the console.
- kitten_mittens_ 9y agoEslint and a Webpack dev server would have you covered in that regard.
- flavio81 9y agoThis premise of many bugs being "type errors" is overblown and certainly very recent, for i've never heard such a claim on the internet until only recently (1 or two years ago). And the world was using dynamic languages for decades on the internet (old ASP, old Actionscript, old JS, PHP4 anyone?) If the 15% of your bugs are simple type errors, then I'd suspect the quality and experience of your development team. The big white elephant in the room that javascript users don't want to acknowledge. Mind you, static type checks are nice stuff, but to claim that 15% of bugs are type bugs, is another thing altogether. I speak from experience, having managed development teams for years. Junior coders need (and deserve) to be trained first doing stuff without hurry to allow for mistake, not used immediately or thrown into critical (or rushed) projects.
- mannykannot 9y ago> I've never heard such a claim on the internet until only recently. Knowledge progresses. You can choose to come along or be left behind. > If the 15% of your bugs are simple type errors, then I'd suspect the quality and experience of your development team. This is an empirical study, carefully constructed to be conservative in its estimation of the achievable benefits of what even these limited type systems could achieve in practice. No amount of sophistry about what can be called a type bug can alter that. If you think the code sample was unrepresentative, perhaps you could arrange for the code of the projects you have managed to be analysed by the same methods.
- flavio81 9y ago>Knowledge progresses. You can choose to come along or be left behind. Dynamic weakly typed languages have been in use on the internet for more than 10 years and i've listed them above, so we're not talking about new stuff or new paradigms. If you, with your overtly smug comment above, want to imply that you are not "left behind" in terms of "knowledge" of the state of the art in programming, you shouldn't be clinging to javascript transpilers but using truly modern tools like Haskell, Clojure/Clojurescript, Racket, Julia and Lisp/Parenscript. Because knowledge progresses, and you shouldn't be left behind.
- mattferderer 9y agoI'm a big TypeScript fan but at times it just doesn't work & needs to be ignored. Like all things, you get to a point when you know what rules are okay to ignore. You can't do default props in React very nicely for example. Functional programming like pipes can also be a pain. That said, TypeScript (and Flow) offers other huge benefits than the 15% of bugs mentioned. * Improved documentation * Better code hinting in the editor & better editor experience * Teaches better JavaScript & prevents browser bugs. Some browsers are very forgiving when you incorrectly use JavaScript with DOM elements. Others are not. Types slow down beginners a lot but that's a good thing. When learning a new language, a type system can act like a pair programmer or a teacher helping guide you in learning the types of the language. Each type has things you can & cannot do. People who learned JavaScript using JQuery & then try to type JavaScript without JQuery run into many of these issues. After using types for a while, the time investment is very minimal especially compared with having to come back & find the error later.
- bpicolo 9y agoDoesn't seem overly tricky? https://stackoverflow.com/questions/37282159/default-property-value-in-react-component-using-typescript https://stackoverflow.com/questions/37282159/default-propert...
- mattferderer 9y agoI've done that method & maybe I've missed something but I get a ton of "object is possibly undefined" warnings then.
- taeric 9y agoThis seems sorta silly. Better tooling prevents more bugs. That is the Crux of the claim. Yes. It should. Better static analysis is almost certainly going to prevent bugs. Type checking is the fashionable static analysis nowdays. My bed with it is that it requires rewriting. Which, itself, will introduce bugs. Or just be expensive. Using other tools are likely to give similar benefits. With the side benefit of keeping the working code you have.
- dangoor 9y agoTypeScript and Flow are both designed to work with the way people write JavaScript. The DefinitelyTyped project adds TypeScript types for existing JavaScript code without touching the existing code. You don't rewrite your code to use these systems. You add annotations, which should not be introducing bugs.
- drderidder 9y agoI feel there should be a counter-article along the lines of "Unit testing and static code analysis conservatively prevent 80% of the bugs". I've used both Flow and Typescript and imho they're both frequently more trouble than they're worth. They catch the simplest of newbie bugs that are rare in modular, linted, unit-tested codebases. There are static code analyzers (eg. tern.js) that provide hinting without requiring a transpiler. With Flow and Typescript you have transpiler overhead, but when it comes to places you might need them the most - checking and sanitizing data interchange that's so common in modular, service-oriented architecture - they fall flat. Flow or Typescript could have been more useful if the annotations truly were annotations in the form of comments, unfortunately they went the transpiler way.
- flavio81 9y ago>They catch the simplest of newbie bugs that are rare in modular, linted, unit-tested codebases. This can't be repeated often enough.
- deleted 9y ago[deleted]
- dangoor 9y agoFWIW, Flow allows you to put the annotations in comments, but the syntax for the type annotations is generally more pleasant to work with. I have found the types to be useful in a large (for JS) codebase with more than a handful of developers. The types help catch bugs, especially when refactoring, even with a decent test suite and linting. Plus, using React and GraphQL, we get static types all the way from data coming from the server through to the UI.
- drderidder 9y agoNice. It's too bad they didn't support that initially. It was issue #3 on their repo, incidentally. I might still be using it if it had been implemented sooner.
- marcosdumay 9y ago
- m12k 9y agoAs someone whose background is mostly in statically typed languages, who has been using Ruby and Rails for the past year, the biggest issue for me is when refactoring/making big changes to central parts of the app, the many repercussions of these changes often take a long time to track down, and subtle bugs are often introduced. By comparison, similar changes in a statically typed language are are usually much less scary, and less prone to having subtle breakage going unnoticed. A big test suite helps, but it's not a replacement for all the help a static type system will give you.
- christophilus 9y agoI'm in the same boat. Mostly C# for 15 years, and now Rails. I've seen bugs in production that were non-trivial to track down that a static type checker would have caught. Refactoring is tough, not just because of the lack of static typing, but because of implicit dependencies, crazy and inconsistent ways to handle and invoke method messages, etc. In short,I'm not a Ruby fan...
- noncoml 9y agoI actually use Typescript to speed up development. Having the type-system looking over your shoulder is great for reducing the code-test cycle.
- Rapzid 9y agoI feel like I'm on a completely different wavelength with those who offer up "full test coverage" as a desirable alternative to a type system's assistance. Or a desirable situation period. I'm all for tests as a tool, but not full coverage as its own goal. One of my favorite tools is Visual Studio Code. As far as I can determine from the github repo it is very far away from the full coverage end of the spectrum. And yet, it works pretty darn good. Maybe I just haven't found the unit test hoard, but it appears they have taken a more strategic, moderate approach.
- pier25 9y agoThe TC39 has to step up their game and introduce static typing to JavaScript. I don't buy the bugs argument, but I firmly believe it would make the development experience considerably better. Not only because of tooling, but specially because code would be more way more expressive. Also in my almost 20 or so years writing Javascript and other dynamic languages I've never once changed the type of a variable. Changing a var from string to int or object is just wrong.
- yorwba 9y ago> ... I've never once changed the type of a variable. I only do that for functions that accept multiple types (accept liberally and all that), but internally convert them into a canonical representation. For example, if a plain string is to be treated the same as an object with a name property, I will have code like if(typeof(x) === "string") { x = {name: x} } I like how Rust just lets you declare a new variable with the same name but different type, which then shadows the previous declaration for the rest of the scope.
- pier25 9y agoIn those cases I usually create a new function depending on the type. So for example I have a "main" function that does something with a date and expects a date object: doSomething(date) And then if I want to pass a string I do something like: doSomethingString(date) { doSomething(new Date(date)) }
- cozuya 9y agoYou've never taken a value from a web input field that was supposed to be a number? You've never used parseInt?
- dvlsg 9y agoI assume they meant if they had to do that, they would assign the result to a new var instead of overwriting the existing one.