Key Points From This Episode:
- Do you use semicolons, or not?
- What is a linter and what is it used for?
- Understanding the benefits of linting your code.
- Who invented linting and where did it come from?
- Code bases that don’t have a linter.
- Why implementing a linter should take some discussion.
- Tech debt that accrues when adding a linter later in a project.
- Recognizing that with linting, buy-in is key.
- The best time to run the linter on your code.
- Why a linter should be part of your continuous integration pipeline.
- Teach and learns: after initialize callback, docker container
- And much more!
Transcript for Episode 98. Code Formatting Standards Knife Fight (Linters)
[0:00:01.9] MN: Hello and welcome to The Rabbit Hole, from the boogie down Bronx. I’m your host, Michael Nunez. Our co-host today.
[0:00:08.0] DA: Dave Anderson.
[0:00:09.2] MN: Our producer.
[0:00:09.9] WJ: William Jeffries.
[0:00:11.3] MN: Today, we have a question. Do you even linter bro?
[0:00:14.3] DA: I see these semicolons all over the place, Mike. I really question if you’re linting your code.
[0:00:33.4] DA: No. I will fight you.
[0:00:36.0] WJ: I’m going to weigh in here, I’m just going to decide here and I’m going with Dave, no semi.
[0:00:41.3] MN: Okay.
[0:00:41.3] DA: You’re going no semicolons?
[0:00:43.9] MN: What do you mean no semis?
[0:00:45.9] WJ: Why do you need it? There’s no reason, it’s totally extraneous.
[0:00:47.9] MN: There is no – it just looks nice, I like it. I’ll be honest with you, I can easily be swayed but I’m going to be –
[0:00:54.3] WJ: Semicolon is an ugly punctuation mark. It’s unbalanced.
[0:00:57.5] DA: It’s like a vintage.
[0:00:59.4] WJ: It’s got a little dangly bit. Do you really want a little dangly bit at the end of every line?
[0:01:04.9] DA: Gross.
[0:01:26.8] MN: I will tell you this: If you’re responsible for introducing the linter to the code base that I’m working on and you happen to “forget to add that rule” and there are no semicolons in the code base, I’d be okay with that. I think tabs versus spaces, I think we’ll have to fight.
[0:01:45.0] DA: Oh yeah.
[0:02:11.5] WJ: But I thought they fixed that. That’s still broken?
[0:02:14.2] DA: Well, no. You can just avoid it if you use a linter. So we should get into it.
[0:02:20.1] MN: So you avoid it all together by using a linter.
[0:02:22.7] DA: Why don’t’ we talk about like you know what? What even linter is in case someone out there hasn’t used linter.
[0:02:28.2] WJ: What even linter is?
[0:02:29.7] DA: That monsters.
[0:02:30.5] WJ: What even a linter is?
[0:03:15.8] MN: I mean, one of the benefits I do like about linting is that the code is unified and all looks the same. The piece of code that I write when the linter runs will look exactly the same when William runs the linter or when Dave runs the linter. We all agree to have certain rules in place so that we can all read the code the same way.
[0:03:38.8] DA: Yeah, it reduces friction. Like you're not surprised opening a file that this file has tabs and the other file has spaces or, you know, something.
[0:03:48.8] WJ: No tabs, no tabs!
[0:04:23.0] WJ: So it was actually a computer scientist from Bell Labs who came up with it in 1978. Apparently he was writing a program that was hilariously called the Yacc, or Yet Another Compiler-Compiler. I don’t know what a compiler0compiler is but apparently, there were a lot of them in 1978.
[0:04:42.0] DA: Like we have mark-up languages now.
[0:04:44.7] WJ: Yeah. So he wrote a program that was designed to remove the lint from it, which lint being like the bits of fiber and fluff in sheeps wool. So it’s kind of funny, Yacc, linting and –
[0:04:57.6] MN: This guy.
[0:04:58.3] DA: I wonder if he had anything for like shaving the Yacc as well?
[0:05:04.0] WJ: Oh, that’s a good one. This is kind of a Yacc shave right now. Why are we on the Wikipedia page for this?
[0:05:09.3] MN: I really needed to know where it came from. Who thought of the idea of linting? I mean, this person may not have seen it right now but it’s so useful and so prominent in the work that we do. Have you guys worked at a code base recently that didn’t have any form of linter?
[0:05:26.7] WJ: Yeah, I mean I think that a lot of times code bases start out without linters and it’s not until a couple of people join that project and you start having differences of opinion on styles and it becomes a point of conflict.
[0:05:41.1] DA: Right, like when you start like having comments on PR’s about how things are formatted. Or like starting a project off with a linter is not a bad idea if you have a good sane default to run off of.
[0:05:55.9] WJ: Yeah, ideally you want like a seed repo with a bunch of sane defaults that you can pull from. But if you’re you know, on a new project and these things haven’t been done yet and you’re playing fast and dirty and trying to get off it quickly and linter is not your top priority, I mean, that seems like not a crazy tradeoff to make. That’s a thing you can do later.
[0:06:16.7] DA: Yeah, it’s something that takes a little bit of a discussion because it’s something that really is most powerful if everybody is going to be using it. If you setup a linter for the project and you’re the only one who is running it then that’s not going to really help the overall code quality.
[0:06:33.3] WJ: Straight buy in.
[0:06:34.8] DA: Yeah, you like at least the whole team that you're working on should be bought in on it and generally agreeing upon the rules.
[0:06:41.8] MN: Right, so jumping into the agreeing of the rules, how have you seen, or rather how have you two seen a codebase that doesn’t have any linters and then get introduced into having a linter? Like what are some of the ways you may have seen that introduction?
[0:06:57.2] DA: Punching.
[0:06:58.0] WJ: Yeah.
[0:06:59.1] MN: There’s always a fight, there’s always a fight to the death. We’ve got the Billy Jean music background playing with some duct tape and knives and it’s going down, always. Always at least once.
[0:07:11.8] WJ: Yeah, I think sometimes it starts because somebody gets pissed off about semicolons, sometimes it starts because there is just one good Samaritan who is like, “I’m going to fall on,” – sometimes there’s just one really noble team member who is willing to jump on that grenade and introduce the linter and deal with all of the horrible linting problems that always show up when you first introduce that into a project.
[0:07:34.8] DA: Convince everyone that it’s okay.
[0:07:37.7] WJ: Then they make one PR that’s like 10,000 files changed.
[0:07:43.5] MN: Oh man, that hurts.
[0:07:43.9] WJ: Conflict for a while.
[0:07:45.4] MN: Yeah, reviewing that PR hurts so much too.
[0:07:49.0] DA: Yeah, it’s tough like, that’s an interesting point too like when you decide to add a linter later, you have some tech debt that you’ve kind of accrued, a big ball of lint that you got to roll. Like you’ve got to get rid of that one somehow.
[0:08:04.6] MN: Man.
[0:08:05.6] DA: If you –
[0:08:06.0] WJ: You went to the cat café, you got a lot of linting to do. Get the roller baby.
[0:08:11.2] MN: Whatever, you have to do it, gain a lot of lint.
[0:08:13.9] DA: Not sanitary, don’t know how they passed the health code.
[0:08:18.8] WJ: They really shouldn’t be allowed to sell anything at all.
[0:08:23.1] DA: Yeah, but if you spread it out over a time then like those PR’s, the diffs for the PPR is less meaningful to a reviewer for a longer period of time. Like if you’re spreading it out over time versus like having a big bang fixing all of the lint issues as a focused change to the code.
[0:08:45.4] MN: When the user, or rather, when the developer wants to introduce a linter, do you find like, how does that work? Have you guys had ever found the linter that you really like and just follow it or do you, which one do you use, how does that work?
[0:09:20.2] DA: Yeah, those are ports of it.
[0:09:23.2] MN: Yeah because like, Ruby has like RuboCop. RuboCop is pretty big.
[0:09:26.3] WJ: I feel like in the Ruby community that RuboCop just won.
[0:09:29.3] MN: Yeah, there’s no one trying to challenge RuboCop at all.
[0:10:10.6] WJ: Although buying is so key. I mean, they may be saying defaults for a starting point but if people aren’t going to follow it then it’s going to require modifications until they are willing to follow it.
[0:10:22.7] MN: Right. I think what I’ve seen before is like, you know, an individual’s interested in adding the linter and doing all the heavy lifting, chooses a particular type or I’m going to use brand. I mean, I’m not actually sure? Like company linting style and then from there, then they start to add modifications to it, right?
We were joking around about these semicolons but that’s an easy example. Suppose, I’m not 100% sure what companies styles use what but let’s say Google does not use the semicolon linting style and people really want semicolons in their code. Then you can introduce that linter and then later on, you know have an engineering meeting that talks about some of the standards that we wish to call out.
One of the ways I’ve seen that done was creating an issue in the style guide. Like the organization had a style guide repo that discusses the style guide of the code that they want to write and anytime that there was a particular issue in the linter they would create a new issue in GitHub and in the engineering meeting people would read the list of issues and then have a discussion on how they want to update the linter to do that, and I think that is like fighting off having these little fights here and there about bringing the hammer down on what to actually enforce or lint versus what not to. But you could choose one of the big ones and then work your way down to have your own personal linting style.
[0:11:47.5] DA: Yeah, that’s true. When do you guys like to run the linter on your codebase?
[0:11:51.9] WJ: Pre-commit hooks.
[0:11:53.1] MN: Oh no, no, no don’t do that.
[0:11:56.4] DA: We’re probably going to fight you.
[0:11:58.1] WJ: I am just kidding. I am just trying to start another fight.
[0:11:59.3] MN: No, they’re like, “Yeah, come on Bobby don’t do that.”
[0:12:03.0] WJ: Here is the thing, pre-commit hooks do actually force people to run their linters.
[0:12:07.4] DA: That’s true and I mean you never have a dirty command in the repo and people are going to run it locally. I like just running it locally myself. Like I like running it and pulling that slot and seeing if I managed to write code that’s considered perfect by the standard of my peers.
[0:12:28.3] WJ: The problem with those pre-commit hooks I think is that it discourages committing early and often because it is a pain every time you commit to go, “Wait for the linter and then go fix of all the linting errors.”
[0:12:39.2] DA: Yeah or ask Git to ignore the commit hooks.
[0:12:42.7] MN: No, I think on VS code I have it run the linter on save so that I can immediately get the errors and then fix them.
[0:12:50.2] DA: That’s true. Yeah or if you have your ID set up or your editor set up with the linting rules that linting configuration then you can see it right as you are typing. That is the shortest feedback loop that is possible.
[0:13:02.7] WJ: That is great for training your brain to just do it correctly the first time but it is really distracting when you are just trying to get something out. Because it is constantly screaming at you to fix all of these stupid little errors, when what you really need your mental cycles for is solving engineering problem at hand.
[0:13:22.0] DA: You should write the perfect code, William. That’s the solution.
[0:13:27.0] MN: Write perfect code.
[0:13:28.7] WJ: Or get it to look prettier.
[0:13:31.2] DA: Yeah? Oh that is extreme solution, nuclear bomb.
[0:13:35.5] MN: Hold on, let us talk about that. Are you nice fans of prettier?
[0:13:38.9] WJ: I never bother setting it up, honestly. But I think it’s cool. I support it.
[0:13:42.9] DA: Yeah, I think it’s useful. It makes me a little nervous. I want the robots to take away my jobs. I want to be the one who writes that semicolon. But I totally get it because to look prettier where it has one setting, you don’t have any discussion about settings. It just formats the code automatically every single time the same way, it makes sense, there is really little friction with it. You’ve just got to get used to zany ways that it might put your arguments around on the screen or something.
[0:14:18.5] MN: Oh yeah, I have for some reason, every single React Native project that I start, which I never complete ever, ever do. But that one thing I do add is prettier and it’s just great to see that when it gets all formatted when I say, “You know, all right I am done with this. This is fine,” and then I never build that up again. I never look at it but all my apps are prettier because I don’t want to have to worry about it and setting it up as early as possible, future Mike doesn’t have to have a 10,000 line PR about all of these linter rules that I want to add.
[0:14:50.8] WJ: Yeah, well future Mike won’t have a job because prettier and the bots are going to take over right?
[0:14:56.7] MN: The bots aren’t writing the code. They are just fixing it for me.
[0:14:59.4] WJ: Yeah that is how they start man and pretty soon all your codebase are belonging to us.
[0:15:05.6] DA: Yeah that’s impeding that.
[0:15:07.5] MN: Before you know I’ll be homeless with a Starbucks cup asking for money because the robots took my job.
[0:15:15.6] WJ: This is the natural conclusion of what we do guys. All we do is destroy jobs with this programming.
[0:15:20.5] MN: Yeah, and they will destroy our jobs.
[0:15:22.8] DA: Yeah that’s fine. I’ll just take a vacation but I guess for quite less of when the linter –
[0:15:27.0] WJ: [inaudible].
[0:15:30.0] MN: Well this is going to happen.
[0:15:31.8] DA: Regardless of when you’re or how you’re running the linter or if it is taking your job or not, you should definitely run it in CI, right?
[0:15:42.6] WJ: Yeah, it should be part of your continuous integration pipeline. You should not be able to virtually master if you’re code does not pass lint.
[0:15:49.2] MN: I agree.
[0:15:49.8] DA: I agree with that.
[0:15:50.6] MN: Because you want to make sure that everything that goes that is in master is of standard.
[0:15:55.3] DA: Yeah, never let those semicolons into the codebase.
[0:15:58.4] MN: Oh come on man. Come on, what did the semicolons do to you?
[0:16:02.4] DA: When I was a kid.
[0:16:03.5] WJ: He got beat up by a lot of semicolons.
[0:16:05.7] DA: Yeah, another dark time.
[0:16:08.2] MN: Yeah, so I think we can all agree that linters are helpful to writing code and makes your lives easier as you write code, although sooner or later the robots will take our jobs and we are okay with that for now.
[0:16:21.5] WJ: Making lint will be the lint that they remove from the codebase.
[0:16:26.0] DA: Oh from the Yacc-y, Yacc-y codebase.
[0:16:28.7] MN: Exactly. Oh god. Imagine that config, a lint to config, remove, destroy all through.
[0:16:33.1] DA: Oh gosh. Do we have any teach and learns?
[0:16:35.2] MN: I have one. So I was looking up some active record callbacks and one of the things that I found was a callback called after initialize and the after initialize callbacks simple calls the function that you want to run after initialize, it simply calls a function that you want to run after the object has been initialized and what does that mean? It means that when the object has been created or when the object is found in the database.
So say you need to ensure that a particular field exists when you load that particular object, you can use the after initialize callback. I was really excited like, “Oh I learned the thing in active record an din the rails. This is awesome.”
[0:17:16.2] DA: So you are going to set a default value that may not have been there initially in the database or?
[0:17:21.0] MN: Yeah, just to like one of the things that this could have definitely been the worst way possible to build this thing, but MongoDB doesn’t have – you can’t run migrations on MongoDB. So I had to figure out a way to add a default value to the object that I am adding this value, this column in. So I ended up using the after initialize. So like any user who has to do – any user who looks up this particular or loads this object will now have this function that will set the default value for that particular object, which is cool.
[0:17:53.6] DA: And then when it’s saved then their record will have it on file.
[0:17:56.5] MN: Yeah then when on save it will have that record because it have to initialize will set that value.
[0:18:01.1] DA: Cool, Schema on reed with after initialize.
[0:18:04.2] MN: That’s for all the folks out there who are using MongoDB, take that one to the bank, that will help you out, can’t run any migrations.
[0:18:11.1] WJ: I have a teach and learn as well actually.
[0:18:13.1] MN: What’s up?
[0:18:15.3] WJ: I recently learned that you can – if you install VPC on a docker container, you can use the screen share program that is built in natively to all macs to connect to your docker container. So you can actually have a visual client, you can open a window as though it were running in operating system in visual mode.
[0:18:39.0] MN: You can see the content inside your docking container?
[0:18:42.6] WJ: You can see into your docker container. It’s crazy.
[0:18:45.7] MN: My gosh. I only thought that you could SSH and that’s it.
[0:18:49.0] WJ: Yeah.
[0:18:48.5] MN: That’s pretty cool.
[0:18:51.3] WJ: I have only done this on a docker container from Selenium. There may be something else that they’ve installed so that it can run browsers.
[0:19:01.4] DA: That makes sense.
[0:19:02.4] WJ: Makes it a little more complicated but just the idea that that was possible kid of blew my mind today.
[0:19:06.4] MN: That’s pretty dope. We’re out here learning, that’s awesome.
[END OF EPISODE]
[0:19:10.2] MN: Follow us now on Twitter @radiofreerabbit so we can keep the conversation going. Like what you hear? Give us a five star review and help developers just like you find their way into The Rabbit Hole and never miss an episode, subscribe now however you listen to your favorite podcast. On behalf of our producer extraordinaire, William Jeffries and my amazing co-host, Dave Anderson and me, your host, Michael Nunez, thanks for listening to The Rabbit Hole.
Links and Resources:
Our seasoned cross-functional agilists work with you to develop technology, ship product and deliver value. We leverage our diverse expertise across industries and throughout the organizational growth cycle to your benefit. We bring best practices, emergent practices and creative solutions to your problems.