We get feedback from the compiler. We get feedback from Test Driven Development. But what sources of feedback lie in between?
This is where linters come in. A linter goes beyond “Does the code compile?” A linter answers questions like, “Is the code idiomatic? Is it stylistically clean? Are there any red flags?”
MAGNIFYING GLASS by Rafael Anderson Gonzales Mendoza, used under CC BY-NC-SA 2.0
We want the ability to fearlessly change code. The antidote for that fear is feedback. That’s why I practice Test Driven Development. TDD gives me fast feedback about whether the behaviors of my components match the desired business rules.
At the other end, compilers don’t understand business rules. But they do understand programming languages. The most basic level of compiler errors tell us whether our code is language compliant. But Xcode also offers:
You can specify what level of Analyzer warnings to use for the “Build” action, as opposed to the “Analyze” action. My practice is to turn up Xcode warnings as far as I can stand them.
So far, all of this analysis is what we might call “strong rules”: they apply to any codebase. But beyond these strong rules, there are softer rules. This is where linters come in.
Soft rules are discovered by the larger community. These rules often express idioms. Such idioms may make sense for one team (or codebase) but not another.
I’ve been using linters since my C and C++ days. Those old linters issued a lot of messages! At the time, much of it seemed like noise. Either they were inherently noisy, or my code was horrible. (Maybe both!) But I don’t remember any way to configure linters with what to report and what to ignore.
Things are a lot better today! Modern linters let you specify which rules you do and don’t want for a particular project.
For Objective-C, I use OCLint. It offers rules like:
…Well, I used to use OCLint. I largely stopped because AppCode’s “code inspections” give me good feedback without no set-up. AppCode tells me about:
For Swift, the go-to linter is SwiftLint. It offers rules like:
private
will silently fail to run, because they’re hidden from the test runner.What about AppCode “code inspections” for Swift? There’s actually a nice SwiftLint plugin for AppCode. With this plugin, I can instantly see SwiftLint messages within AppCode, before compiling.
Of course, AppCode still reports typos in camel-cased identifiers, since that’s independent of language.
SwiftLint is updated regularly with new rules. Some rules are enabled by default. Others are “opt-in” and won’t take effect unless you explicitly enable them.
To see the current list of rules, type swiftlint rules
.
In the spirit of turn it up to 11, I want to enable as many opt-in rules as I can stand. (Click here to see my SwiftLint configuration for the MarvelBrowser project.) Let me point out the few opt-in rules I don’t enable:
Linters are like warnings on steroids. Experiment with the opt-in rules to see which ones make sense for your projects. When you update a linter, don’t forget to check for new rules you can use.
Test Driven Development helps us write code that satisfies business rules. Linters (and static analysis in general) help us write code that is cleaner. It’s win-win.
What static analysis tools do you use? And how do you like to use them? Please share in the comments below.
I first experienced the joy of programming in junior high. But on the job, some of that joy was sucked away by seeing code my teammates were afraid to touch. Poor code led to fear, and fear led to our entire team being let go. I began searching for ways to improve code. I stumbled upon the first wiki, which was about Design Patterns, Extreme Programming, and Test Driven Development (TDD). I rediscovered joy on the job. I've now been doing TDD in Apple environments for 17 years. I'm committed to software crafting as a discipline, with the hope of raising you, my fellow programmers, to greater effectiveness and joy.
Session expired
Please log in again. The login page will open in a new window. After logging in you can close it and return to this page.