4 ms·
I 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
by drderidder 9y ago
I 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> They catch the simplest of newbie bugs that are rare in modular, linted, unit-tested codebases. They catch 15% of the bugs in Javascript projects on GitHub. Why do people insist on restricting their static code analysis into heuristic rules when there are so many perfectly good complete rules to be checked with a type system?
- flavio81 9y ago>They catch 15% of the bugs in Javascript projects on GitHub. Using JS projects in GitHub is a really misleading sample. GitHub is used by all kinds of purposes, for example most coding bootcamps and institutes here tell the students to upload their code to GitHub. You have, for each institution, about 400 Javascript GitHub repositories each year, full of code written by true beginners. GitHub is simply a big container of code for literally everybody, so judging kind of bugs produced by looking at what it's inside the Github repositories is akin to judging how many gramatical errors book authors make by taking a look at all the MS word documents stored in Dropbox.
- skybrian 9y agoThe study only includes projects where people file bugs and fix them. That excludes most true beginners since they won't use the issue tracker at all.
- klibertp 9y ago> Why do people insist on restricting their static code analysis Because it's trivially easy to show cases where a static type system rejects useful and correct code. Yes, static type systems do "eliminate whole classes of errors", but they also eliminate whole classes of correct code! Is the freedom from (some, not all!) runtime type errors really worth the loss of expressive power? Well, the answer is of course "it depends" on specific circumstances: sometimes it's worth it, sometimes it's not and most of the time the very choice (ie. should I write in statically or dynamically typed language in this case?) is not important at all because tons of other choices have much more of an impact on whether the project succeeds or not.
- watwut 9y agoUnit testing is not mutually exclusive with static typing. Normal statically typed projects have unit tests too. The biggest advantage of static typing, in my opinion, is that simple refactorings like "rename" or "move method from one class to another class" or "change what method does and then modify all places that call it" are done routinely and very often. Where renaming something in javascript is careful change you do when fully fresh, rested and focused, it is one quick right click when you are lazy and too tired to do real work in statically typed code. Means difference between rarely done and often done. The other big advantage is when I am learning somebody elses code, all info about who calls who and how is right there.
- flavio81 9y ago>The biggest advantage of static typing(...) or "move method from one class to another class" You are posting about static typing advantages. Please note that the use case you mention would not need too much refactoring in languages like Common Lisp (dynamic language) or Julia (dynamic), because of multimethods and because of the way methods are called. Methods -and method signatures- aren't constrained inside class definitions, they are separated.
- watwut 9y agoJavaScript does not have multimethods and methods are called on objects. It sounds like methods must be purely functional and not use any instance fields. The use case I had in mind was that I delete method from one class and create it in another. Then I go through all red in workspace and modify what is needed - sometimes just call the other place, other times remove the call entirely, yet other times conclude that method needs to go back because that two special places that don't have access to the other class instance. Similar with changing signatures - I add/remove parameters and then go through all reds and decide how to fix them case by case.
- skybrian 9y agoThe kind of refactoring you need to do depends on the language, but it seems like multimethods will have their own issues. I don't have experience with this, but suppose you decide to split a multimethod into two separate operations because on second thought, they shouldn't have the same name after all? How do you fix all the callers?
- lmm 9y ago> I feel there should be a counter-article along the lines of "Unit testing and static code analysis conservatively prevent 80% of the bugs". We need to talk about costs though. If a type system lets you write 15% fewer unit tests, it's worth it for that alone. > There are static code analyzers (eg. tern.js) that provide hinting without requiring a transpiler A static analyser is already a type system. You need a way to hint to the analyser, at which point you've got a notation for types in your language as well (maybe a limited one). You want the analyser to run on every build anyway, so a transpiler is no more effort; if you make the analyser optional developers will skip it, and will introduce bugs as a result, so it's better to simply not have the option. > 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. You need to use types on the interfaces too. Use something like thrift.
- drderidder 9y agoAlright, costs. I think it's not well advised to use a type system as reason not to write unit tests. It seems to be a common misconception that static types are a replacement for testing. I think the real question is can you afford not to write unit tests that exercise functions with invalid arguments. I think it's still worthwhile because, like I said, you can have code where all the type constraints are satisfied but become violated by ingested data. You probably shouldn't assume that every user of your code is going to use thrift or graphql or whatever. I think it's a stretch to say a static analyzer is "a type system". It doesn't obviate runtime type checking and implicit type conversion. But yes, absolutely you should run it on every build.
- lmm 9y ago> I think it's not well advised to use a type system as reason not to write unit tests. It seems to be a common misconception that static types are a replacement for testing. Of course they are: whatever your acceptable defect rate, both types and tests are ways to spend effort towards achieving it. The more defects you can eliminate via one, the less you need to catch via the other. > I think it's still worthwhile because, like I said, you can have code where all the type constraints are satisfied but become violated by ingested data. Most languages won't allow that to propagate through the system, and if you get an error at the boundary then it's obvious what the error is. (Admittedly a compile-to-Javascript language is the example here and may be the exception). Fundamentally you decide how likely certain classes of errors are and look at the cost/benefit of the various measures available to you. In my experience types can, when you commit to them and work with them, reduce the defect rate very close to zero, and more cheaply than any other measure; I only feel the need to supplement them with tests very occasionally, and only for the very core parts of the code where defects would be most expensive. > I think it's a stretch to say a static analyzer is "a type system". It doesn't obviate runtime type checking and implicit type conversion. In terms of the mechanics of what it does, it's a type system. I don't see any value in having two type systems for the same code - type systems work better if they're part of the language so that all of the tools understand the same types the same way - so I prefer to use a language where the language type system covers all the use cases that a static analyzer might be helpful for.