I say put the linting into your editor or IDE environment and you’re done. Things like Pycharm and various emacs / Vim modes do this handily.
One of the interesting use cases for a linter is prototyping certain checks for potential addition to a compiler. This is the de facto case with rust-clippy, which includes a variety of checks that may at some point be added to the Rust compiler. Having them in a separate tool allows users to opt-in to using them, and allows the compiler writers to get a sense of the effect of the lints without committing to them. In this way, linting is quite useful.
Rust also has rustfmt, which appears to be closer to what the author is complaining about. It’s a tool to format your Rust code according to your formatting configuration. I think it’s useful, in that it makes it easier to guarantee that all contributions follow a consistent style-guide, but I can understand not being as keen to use it compared to something like clippy.
Turning on the TypeScript “noImplicitAny” check, which requires all types to be explicit (or inferred), means putting a lot of type annotations in Angular 2 codebase where they are currently missing.
I don’t understand why more linters (or linter-editor integrations, more precisely) aren’t source control-aware, only linting the diff from the trunk branch. Pronto is a linting framework for the Ruby ecosystem that lints “incrementally” and I find it useful for guiding the codebase in a healthy direction and documenting style in an executable format, while avoiding mass style-only patch sets that add noise to the git history. Unfortunately I haven’t found an easy way to integrate Pronto with vim, and am too lazy to run it on my local command line, so I usually just let it run against my pull requests, which is a slower feedback cycle. It seems to me the holy grail would be incremental feedback in editor with a matching CI step going off the same configuration. Is this complete package available in another ecosystem?
Code is read more than it’s written. Having standards that apply only to code written since time t seems like a bad idea - if you joined the codebase after t, you’d be very surprised when a function you called violated that standard.
For sure. Then do you fix file-by-file as you touch them, or lint the whole codebase in one fell swoop?
And how do you develop your standards in such a way as they may evolve but not requiring you to reformat the whole codebase every time you tweak the standards?
And do you have any tricks to use eg. Git blame but ignoring style patches by default?
The whole codebase.
Reformat the whole codebase every time. If that’s hard, develop the tools to make it easy.
I don’t generally make a lot of use of blame, but the right thing here would be to have it use something more granular than line diff, I think.
I’d rather encourage evolving our style at the expense of the codebase being consistently formatted. It’s not that reformat is difficult (well it is in Ruby, but that’s another problem), but a codebase-wide format requires stopping integration while the team switches to the new style.
a codebase-wide format requires stopping integration while the team switches to the new style.
It can do but it doesn’t have to. If you have a reliable reformat tool you can just have everyone run it on their branches at the same time (or at least, before merging). If the VCS causes problems with this, let’s fix them.
The author makes three primary points:
The author seems to be working on angular, so I think this article makes sense when directed specifically to his team for work on angular. However, I don’t think I agree with him in general.
Linters are often written by end-users of a language who have a set of standards that they want to communicate, and no longer want to tell people manually. In this scenario, his arguments make less sense.
This makes sense on the surface, but in practice, for end-users who don’t want to hack the compiler, the only way around this is to implement your own lexer / parser for the language. This is feasible in simpler languages like lisp or go, but might be an enormous amount of engineering effort in a more complicated language like scala or C++. In comparison, you can often implement a naive linter with a few shell commands. One argument against this is that the compiler already has an AST, so you can simply hack the compiler to do the lexing / parsing for you. However, it can be a big upfront expense to become familiar with a large codebase, which is often not worth paying when there are significantly simpler options.
If you don’t already know the compiler well, making compiler changes can be fraught. If you don’t already own your compiler, it requires that you own your compiler, and means that you will also need to have someone in charge of pulling patches in when they come in, so that you can move forward. At a company like Google (which runs angular) you can own every layer–this isn’t feasible at every company. Linters can in a way function like extensions for the compiler, which is almost certainly how findbugs started.
Write better copy!
Go does much of this with “go fix”, “go fmt”, and “go vet”.