spotifyovercastrssapple-podcasts

elm-review Tips

We revisit elm-review with some tips, useful workflows, and helpful packages that have come out since our intro to elm-review episode.
January 4, 2021
#21

Some tricks to easily try elm-review with no setup:

npx elm-review --template jfmengels/elm-review-unused/example

Init with a given template:

npx elm-review init --template jfmengels/elm-review-unused/example

Incremental adoption

Useful packages and workflow

Transcript

[00:00:00]
Hello, Jeroen.
[00:00:01]
Hello, Dillon.
[00:00:02]
Well, here we are again several months later, and it's time to look back on Elm Review.
[00:00:09]
Yeah, I love these episodes.
[00:00:14]
We should do way more.
[00:00:16]
Way more Elm Review episodes.
[00:00:17]
Just each week, let's do an Elm Review episode.
[00:00:20]
Yeah, let's do that.
[00:00:23]
Sometimes we can talk about your tools.
[00:00:26]
You know them, mine are better.
[00:00:27]
Oh yeah?
[00:00:28]
Well.
[00:00:29]
Well, you can, your tools can review my tools.
[00:00:33]
Yeah.
[00:00:34]
Can your tools review mine?
[00:00:36]
Your tool just reviewed my tool before this episode, which was fun.
[00:00:40]
Yep.
[00:00:41]
Got a personal walkthrough with Jeroen on the Elm pages code base.
[00:00:45]
And he has a lot of dead code.
[00:00:46]
Had.
[00:00:47]
You haven't fixed everything.
[00:00:48]
That's true.
[00:00:49]
I still have some dead code.
[00:00:50]
And with your nose, you've been a naughty boy.
[00:00:56]
Cool for me this year.
[00:00:57]
If you clean your projects by Monday, then maybe Santa will come and give you some gifts.
[00:01:03]
Okay.
[00:01:04]
Well, you better check that list twice.
[00:01:06]
Check the Elm Review rules twice.
[00:01:08]
Yeah.
[00:01:09]
All right.
[00:01:10]
Yeah.
[00:01:11]
So the idea was just to give you, no, let's grab that sentence.
[00:01:15]
Yeah.
[00:01:16]
So we talked about Elm Review in episode three, and I think we gave a pretty good foundation
[00:01:23]
of like the concept and what it is.
[00:01:25]
To reiterate, it's a way to review your Elm code written in Elm.
[00:01:30]
You can write your own rules or you can install other Elm packages for Elm Review rules that
[00:01:35]
others have written.
[00:01:36]
And it's more than just a linter.
[00:01:38]
It can enforce best practices in a particular code base following the norms that you have
[00:01:44]
in your team.
[00:01:45]
It can do static analysis.
[00:01:49]
Today we're kind of going to look back at some of the lessons learned, some of the tips
[00:01:53]
that you've found to be useful when using Elm Review, some tips on getting started,
[00:01:58]
some cool use cases.
[00:02:01]
So we're kind of going to look at some of the things you've learned over the past few
[00:02:04]
months.
[00:02:05]
Yeah.
[00:02:06]
So one of the things that I noticed is that a lot of people don't try the tool.
[00:02:11]
So yeah, unless you put it right in front of the noses, they just won't try it out.
[00:02:16]
And then they won't notice that it's good or that it's helpful for them.
[00:02:20]
So I tried to make it easier for them.
[00:02:24]
So you're a good example because you haven't tried this before.
[00:02:28]
Well, I have used your try version actually.
[00:02:33]
But sometimes I tried setting it up on a live stream once, but then I found some issue that
[00:02:43]
I didn't get past, which I probably could have with a little more time and didn't stick
[00:02:47]
with it.
[00:02:48]
Now it's bug free, by the way.
[00:02:51]
Yes.
[00:02:52]
But just having a way to just try it from the command line without any setup I think
[00:02:57]
is really useful.
[00:02:59]
And I think I agree with your theory that people should just try it out and they'll
[00:03:05]
enjoy it once they get using it.
[00:03:07]
And especially like in a team environment, actually one of my clients recently started
[00:03:12]
using Elm Review.
[00:03:13]
And it was really nice to see these unused bits of code and I really enjoyed that workflow
[00:03:19]
as part of the refactoring experience because you sort of try to refactor and expose some
[00:03:27]
unused code, remove that and the tool can sort of help you with that refactoring.
[00:03:32]
We'll go through that afterwards.
[00:03:33]
So yeah, what I noticed is that a lot of people don't even try it out.
[00:03:37]
I just thought I would make it easier to try it out.
[00:03:40]
So there's one thing that comes with NPM, which is called NPX.
[00:03:45]
So I think that's since NPM 6.
[00:03:49]
Where you can just do NPX, the name of a JavaScript NPM binary, and then it goes to download it
[00:03:59]
and it runs it.
[00:04:00]
It takes a long time, but you can try things out without installing it globally or in your
[00:04:06]
project.
[00:04:07]
So that is very nice.
[00:04:08]
And then I also added a dash dash templates flag to Elm Review.
[00:04:13]
So what it does is Elm Review needs a configuration to work.
[00:04:18]
And I don't want to impose a default configuration for several reasons that we can talk about
[00:04:24]
later if you want.
[00:04:25]
So if you don't have a configuration, Elm Review won't do anything.
[00:04:28]
So what dash dash template does is it fetches a configuration on GitHub, downloads it, and
[00:04:34]
then it runs Elm Review with that configuration.
[00:04:37]
So you can try Elm Review without pre configuring it.
[00:04:41]
So if you do NPX Elm Review dash dash templates and then some GitHub repository, then you
[00:04:49]
can just try it out like this.
[00:04:52]
So the example that I would usually give is NPX Elm Review dash dash templates, JFM angles,
[00:05:00]
that's my name, slash Elm Review unused with dashes between them.
[00:05:05]
And then you say slash example, so we use the example configuration that is on the GitHub
[00:05:11]
repository.
[00:05:12]
And then you just try it out and see what it reports and see if you like it.
[00:05:19]
So basically the template flag in the Elm Review CLI in conjunction with NPX to sort
[00:05:26]
of execute a package that you don't have in your NPM setup, you can run NPX Elm Review,
[00:05:34]
pass in a template, use a GitHub repository and use the configuration, which the config
[00:05:40]
is an Elm file, an Elm folder, an Elm project, it has an Elm.json with dependencies, and
[00:05:46]
you can just point it at one of these in a GitHub repository and run those rules.
[00:05:50]
So that's, it's awesome.
[00:05:52]
You should definitely try out the Elm Review unused example and just particularly try letting
[00:05:58]
it auto fix your unused code.
[00:06:01]
So yeah, once you've tried that out and if you find that you like it and you like those
[00:06:07]
rules, what you can do is initialize your project.
[00:06:11]
So there's an Elm Review init command, which initializes, which creates a blank project,
[00:06:18]
but you can also do init dash dash templates, which then just copies that configuration
[00:06:23]
from GitHub to your project.
[00:06:26]
So if you liked it, reuse it.
[00:06:27]
And then if you find new rules, then you will have to add them manually.
[00:06:32]
It's not as scary as it seems.
[00:06:33]
The init command just creates a folder called review, which has a module called review config,
[00:06:40]
and it has an Elm.json, which has dependencies, which will include some Elm Review packages.
[00:06:47]
And that's it.
[00:06:48]
And when you run Elm Review from your root directory, it goes into that review directory
[00:06:52]
and runs that Elm project.
[00:06:54]
That's all it is.
[00:06:55]
So init just creates that for you, and then you run Elm Review and you can add rules to
[00:07:00]
that list of rules in your review config.elm.
[00:07:04]
So what do you recommend for the CI workflow for, you know, if somebody is using GitHub
[00:07:11]
actions or something like that?
[00:07:13]
Yeah, well, first of all, I really, really recommend to put Elm Review in your CI.
[00:07:18]
If you put Elm Review in your project, don't enforce the rules on CI, especially when you're
[00:07:25]
working on a team that will just lead to chaos.
[00:07:29]
From having to try it out several times, it's not a good idea.
[00:07:34]
If you have tests or static analysis tools and whatever checks, you need to enforce them
[00:07:39]
on the CI.
[00:07:41]
Even if you enforce them using GitHub locally, that is not enough.
[00:07:46]
I've seen it go wrong many times.
[00:07:49]
Yeah, right.
[00:07:50]
It's better to have a smaller number of rules that are being checked that are checked in
[00:07:56]
CI and completely clean rather than a large number of rules with some noise of things
[00:08:02]
that are not following those rules and it not checked in CI.
[00:08:08]
Because at that point, that defeats the whole purpose because it doesn't allow you to just
[00:08:13]
run it and see everything is green.
[00:08:16]
So you don't know.
[00:08:17]
Although I think you did work a little bit on this backsliding workflow at some point.
[00:08:22]
I'm not sure where that stands.
[00:08:25]
Have you come to any conclusions about that workflow of having a number of failures and
[00:08:31]
saying it shouldn't go beyond this number of failures?
[00:08:34]
Have you tried it and decided it's a bad idea?
[00:08:37]
Or where do you stand with that?
[00:08:39]
That is still something I really want to have.
[00:08:42]
Just haven't worked on it and haven't figured out a nice way of using it yet.
[00:08:47]
Of capturing the exact errors?
[00:08:50]
The thing is, you have a configuration that says what rules you want to enforce on your
[00:08:58]
project and you also have ignored problems.
[00:09:03]
Currently you can use ignore errors for files or ignore errors for directories to say this
[00:09:09]
rule or all rules should not report problems for these.
[00:09:15]
Those are ideally used for vendor code or generated code that you don't want to be linted
[00:09:22]
or reported.
[00:09:24]
But sometimes you want to enable rule bit by bit.
[00:09:27]
What you need to do is either fix everything in one go or you need to use those two functions.
[00:09:34]
The idea would be to have another function that says Elm Review should ignore these errors
[00:09:40]
here and there, but only temporarily.
[00:09:44]
If things get worse, like for instance, we used to allow five errors and now there are
[00:09:49]
six, then Elm Review will report things because things got worse.
[00:09:53]
It will tell you to update the configuration if it gets less.
[00:09:56]
So that is something I really want.
[00:09:58]
I just haven't worked on it yet.
[00:10:01]
The problem is that you've got a configuration, a set of rules that you want, and then there's
[00:10:06]
how should it apply to my specific projects.
[00:10:10]
Those are the ignored files.
[00:10:12]
Ideally if your company uses the same configuration for several projects, then you would like
[00:10:21]
to share those.
[00:10:22]
But if you have ignored errors, then that doesn't work anymore because those ignored
[00:10:26]
errors are specific to some projects.
[00:10:30]
So there's two worlds that I just can't fit together yet.
[00:10:35]
It's a difficult problem because these sort of workflows can really be crutches as well.
[00:10:42]
One of the things that I think is most powerful in building software is this concept of minimizing
[00:10:50]
work in progress, not having too many balls in the air at once.
[00:10:54]
Whether that's building one feature rather than having 20 work in progress features that
[00:11:00]
are partially working.
[00:11:02]
You should see something through all the way, all the way through end to end.
[00:11:06]
You should build a feature and not just build the front end piece for five different features
[00:11:11]
and then start building and implementing the back ends.
[00:11:14]
Build it all the way through.
[00:11:15]
So this concept of reducing work in progress and seeing something through all the way is
[00:11:21]
something that I really believe increases quality and efficiency in building things.
[00:11:28]
This is sort of like this lean concept of pushing something through rather than kind
[00:11:33]
of this mass manufacturing, do a bunch of things on the production line.
[00:11:37]
It can really increase quality and make things much more efficient.
[00:11:42]
I think that the same applies to static analysis tools.
[00:11:47]
Turn on one rule, turn on no unused functions, and then fix all of them.
[00:11:54]
If there are some cases where you're like, wait a minute, but this is unused, but I need
[00:11:58]
to use it.
[00:11:59]
And so I need to, you know, instead of just saying, well, let's come around to that later.
[00:12:04]
We've got one problem.
[00:12:05]
We fixed all of the unused functions except for this one that it's complaining about.
[00:12:10]
Let's go add these other rules now and then have like a few issues in several different
[00:12:15]
rules.
[00:12:16]
It's a better use of your time to just take the time to clean up all of the unused functions,
[00:12:21]
get that completely sorted out, get it in your CI.
[00:12:25]
Now you have at least one rule and it's completely clean and you can trust it and it's integrated
[00:12:31]
into your workflow.
[00:12:32]
And if there are any unused things, your CI is going to catch it before you get that code
[00:12:38]
into production.
[00:12:39]
So I think that's in general, I think you would recommend that process as well, that
[00:12:43]
like just follow one rule through until it's fully integrated.
[00:12:49]
I'm not sure.
[00:12:50]
In our workplace, we tried turning on quite a few of them and fixing them all automatically
[00:12:56]
when possible.
[00:12:57]
But then we still got a lot of errors that required a lot of work or just decisions because
[00:13:04]
you don't always know whether something that is unused should be used or whether it can
[00:13:08]
be removed.
[00:13:09]
Like probably someone aimed to use it, but it didn't got used for some reason.
[00:13:16]
That might've been a mistake.
[00:13:17]
You don't know if you should remove it or whether you should keep it and use it.
[00:13:21]
And what we did was we added a lot of ignore errors for files.
[00:13:25]
And then we hoped that someone would fix those issues.
[00:13:31]
And well, that took a while for us to prioritize.
[00:13:34]
Right.
[00:13:35]
I mean, there's always version control though, right?
[00:13:38]
Like if it's in version control, then why not just delete something that's not being
[00:13:42]
used?
[00:13:43]
Well, it does become harder to find.
[00:13:45]
But yeah, as we went along, we were thinking more and more like Yagni, you ain't going
[00:13:51]
to need it.
[00:13:52]
Yeah.
[00:13:53]
Great.
[00:13:54]
So just delete it.
[00:13:55]
And hopefully if we need it back, then someone will remember it, that it was there at some
[00:14:01]
point.
[00:14:02]
So yeah, we had a lot of ignored errors, but we at least caught a lot of more errors.
[00:14:10]
So yeah, I don't know.
[00:14:12]
I think there's a lot of value in fixing everything, but depending on how hard it will be, maybe
[00:14:17]
a mix of the two would be nice.
[00:14:19]
Yeah.
[00:14:20]
I'm not so dogmatic at least.
[00:14:21]
Yeah.
[00:14:22]
But either way, step one should be a CI process, a build that is running your Elm review rules
[00:14:30]
and passing.
[00:14:31]
However you get there, that's step zero.
[00:14:35]
And if you need to ignore some files or minimize the number of rules you're using or whatever
[00:14:40]
you need to do to get there, that's step zero.
[00:14:43]
And then you build from there.
[00:14:45]
Definitely.
[00:14:46]
Yeah.
[00:14:47]
So it might be interesting to say why you need to enforce it at CI.
[00:14:50]
So imagine that I run Elm review on my machine, which I obviously do, and I fix a lot of errors.
[00:14:58]
So everything's green now.
[00:15:00]
I push it to master, someone pulls it, then commit something, then I pull again and I
[00:15:06]
get some errors and I'm like, no, no.
[00:15:10]
Yeah.
[00:15:11]
If you don't enforce it at CI, then someone will introduce things.
[00:15:14]
And well, the one who will have to fix it is the one that is running it.
[00:15:18]
But if it's running CI, then everyone has to fix it.
[00:15:22]
And it's a shared responsibility.
[00:15:23]
Right.
[00:15:24]
Yeah.
[00:15:25]
This is actually a principle that I think of in terms of lean thinking as well.
[00:15:32]
Sometimes people use the term Kanban in the software world, that you want to minimize
[00:15:37]
the amount of time that something is in progress.
[00:15:40]
And you want to tighten all these feedback loops.
[00:15:43]
So the shorter the amount of time between finding and fixing a bug, or the shorter the
[00:15:51]
amount of time you can have a unit test failing, the shorter the amount of time you can work
[00:15:57]
on a feature.
[00:15:58]
So rather than working on a giant feature, you work on a tiny slice of a feature and
[00:16:02]
get it all the way through and done.
[00:16:04]
The better.
[00:16:05]
If you don't have your continuous integration server as a shared single source of truth
[00:16:11]
that things are good, then you're going to get drift where things are drifting away from
[00:16:18]
a stable green state.
[00:16:19]
And you want that feedback loop as short as possible.
[00:16:22]
Yeah.
[00:16:23]
So we mentioned that we need to fix a lot of issues to get everything clean.
[00:16:27]
And Elm Review does provide automatic fixes, as we have mentioned briefly.
[00:16:32]
So it comes with two flags, dash dash fix and dash dash fix dash all.
[00:16:36]
So what fix does is that it runs Elm Review, finds at least one error with an automatic
[00:16:42]
fix and then it tells you, hey, I've found this error and I can fix it like this.
[00:16:47]
Do you want me to do that?
[00:16:49]
And then you say yes or no.
[00:16:51]
And then it will go to the next one.
[00:16:52]
Yeah.
[00:16:53]
It's like an interactive prompt, like a git commit dash P or that sort of thing.
[00:16:58]
Yeah, definitely.
[00:16:59]
Or git add dash P. Yeah.
[00:17:01]
If you're new to Elm Review, I really recommend using that because if you do fix all, then
[00:17:08]
you will see a lot of deleted code or changed code.
[00:17:12]
And that might be a bit frightening, but if you go through them all one by one, then you
[00:17:16]
will know why something was removed or something was changed with a lot of details because
[00:17:22]
we do try to make very good error messages.
[00:17:25]
So yeah, go through them all.
[00:17:27]
And once you're familiar with the process or the errors that are reported, then you
[00:17:32]
can go and use fix all.
[00:17:35]
So the fix all is very useful also.
[00:17:39]
So at first I was against having a fix all, but I turned around and I love it now.
[00:17:46]
But it can be a bit slow, especially when you run it on a very big project, which has
[00:17:51]
a lot of unused code.
[00:17:53]
Yes.
[00:17:54]
Right.
[00:17:55]
So it speeds up when that unused code is removed.
[00:17:57]
At least that's what I've heard.
[00:18:01]
So the way it works is that it does that interactive fix in memory.
[00:18:07]
So it finds one fix, it applies it, it re reviews everything again, and it finds one
[00:18:13]
that has an automatic fix, it applies it, and over and over and over again.
[00:18:17]
It's not very optimized yet.
[00:18:19]
So if you have a lot of dead code and a very big project, it can take a long, long time.
[00:18:25]
I do plan on improving that, but I haven't succeeded yet, fortunately.
[00:18:30]
Yeah.
[00:18:31]
And the good news is that it's a reliable process just finding all the unused spots.
[00:18:38]
So you just run it and you can just commit it and your code is going to keep compiling.
[00:18:44]
And if you don't feel comfortable just committing it directly, then you can use a git diff tool
[00:18:50]
and go in and choose the pieces of dead code that you're comfortable committing as removed.
[00:18:56]
Yeah.
[00:18:57]
What you can do to speed it up is to use the rules flag.
[00:19:00]
So that says run this configuration, but only run this and that rule.
[00:19:06]
You separate them by comma and you can just run it with a dash dash rules, no unused
[00:19:12]
exports and no unused variables.
[00:19:15]
So those are the main ones that will delete a lot of code.
[00:19:18]
Running only with those two will speed things up a lot.
[00:19:22]
And hopefully later on, it will be as fast as just running those two.
[00:19:25]
So you can also use the rules flag to run a single rule, which can be useful to run
[00:19:30]
a new rule that you've just installed, for instance.
[00:19:34]
Or when you only want to fix one kind of error, just like Tindon said, go one way, go one
[00:19:41]
rule and do it all the way down.
[00:19:44]
What you can also do, and that is I think my favorite feature in Elm review is the watch
[00:19:49]
mode.
[00:19:50]
So the watch mode is going to run the Elm review process, but not stop it after it has
[00:19:56]
reviewed your project.
[00:19:58]
And every time you touch it, every time you touch a file or remove a file, add a file,
[00:20:04]
it will rerun Elm review and report the new things.
[00:20:07]
So you can run that next to your ID, for instance, and then it will report things as you type.
[00:20:13]
It works quite well with updating your review config as well.
[00:20:16]
Yeah, it also watches that and reruns it.
[00:20:19]
So is that your typical workflow?
[00:20:21]
You've got like a window with a review Elm review watch running as you're writing code
[00:20:28]
and you've got that like on the side of your monitor as you're writing your Elm code?
[00:20:33]
Is your workflow something like that?
[00:20:35]
Sometimes yeah.
[00:20:36]
It's always sometimes I just run it at the end because it's mostly about unused code.
[00:20:41]
The rest I'm aware of what I should need to do myself.
[00:20:45]
But what I usually do when I do that is I run Elm review dash dash watch dash dash
[00:20:51]
fix all because those work together.
[00:20:54]
So every time I'm done with what I'm working on Elm review will let me know about all the
[00:21:00]
code that can be removed or all the fixes that I can apply automatically.
[00:21:03]
I just go to my terminal and say yes and commit that.
[00:21:07]
And that is my usual workflow when I do that.
[00:21:10]
For unused functions does that mean that you don't hit save until you've used a function
[00:21:17]
somewhere or does that mean that you define a function by calling like invoking the function
[00:21:23]
and then use your IDE to define it or something like that?
[00:21:27]
How does that work?
[00:21:28]
I just write my code as usual and when I'm done then I go to the terminal and press enter
[00:21:35]
because even in fix all it asks you.
[00:21:38]
Gotcha.
[00:21:39]
Gotcha.
[00:21:40]
It asks you to remove the code or not.
[00:21:43]
So it's not like you have to use things that you define and stop pressing save.
[00:21:50]
You want to know about it if that happens at some point and you may or may not mean
[00:21:55]
to have unused code.
[00:21:57]
But I only look at that when I'm out of the flow that it was in.
[00:22:02]
You know when you're doing like TDD, I'm running the codes as ugly as possible but I'm going
[00:22:09]
to get a test to pass.
[00:22:11]
Once that is done then I clean up.
[00:22:14]
That makes sense.
[00:22:15]
So you've got like a green mode and a refactor mode and if you're like implementing something
[00:22:22]
then you're not in refactor mode.
[00:22:23]
Yeah.
[00:22:24]
That makes sense.
[00:22:25]
I'm looking at the unused functions when I'm trying to make things pass.
[00:22:30]
That said looking at Elm review can tell me like hey it's not working because you're not
[00:22:34]
using that function that you just defined.
[00:22:37]
But yeah usually I do find the problems.
[00:22:40]
So since we talked about this last back in April a lot of new packages have emerged that
[00:22:46]
you've written and that other people have written and I'm sure you've got some cool
[00:22:51]
like internal workflows at Humia that you're using and have heard about others that other
[00:22:56]
people are using in their own companies.
[00:22:58]
So let's talk about some specific review rules and some use cases.
[00:23:04]
So like what are some of the new review rules that you're excited about and some of the
[00:23:10]
cool use cases you've heard about?
[00:23:11]
Do you mean the ones that are used specific for Humia or do you mean in general?
[00:23:16]
Just any you know the most useful rules that you've used or heard of people using.
[00:23:22]
What are some of the sort of new things that have come out since we last spoke about this?
[00:23:26]
One of my favorite ones is one that is very niche.
[00:23:31]
It's only for package authors.
[00:23:35]
Maybe even just for Elm review package authors.
[00:23:38]
So in the Elm review packages there's always a link to the different rules.
[00:23:43]
In the readme there's a link to no unused variables and that one needs to link to the
[00:23:52]
version of this package.
[00:23:53]
So you need to link to version 1.2.0 of the no unused variables rule.
[00:24:00]
You don't want to link to latest because otherwise links get broken when new versions arise.
[00:24:06]
You don't want to always link to 1.0.0 because then you have outdated documentation.
[00:24:13]
Or you're sending to outdated documentation.
[00:24:15]
So what I have is a rule that reads the Elm JSON file, finds the version and then everywhere
[00:24:22]
in the readme and later on in the rest of the documentation finds those links and replaces
[00:24:28]
the version.
[00:24:29]
So every time I'm going to publish a version I do Elm bump and I do Elm review fix all
[00:24:36]
and it fixes all the dead links.
[00:24:39]
Oh that's cool.
[00:24:40]
So now I don't have any outdated docs and I don't have any links that send to latest.
[00:24:47]
So I'm very happy about that.
[00:24:50]
That sounds great.
[00:24:51]
I mean yeah those types of workflows are so helpful.
[00:24:53]
Like I've been using Elm verify examples a lot in this package I've been developing recently
[00:25:00]
and it's the kind of thing where having the examples in the documentation and having that
[00:25:07]
be not just useful documentation but executable documentation is so valuable because otherwise
[00:25:14]
you end up like I was finding myself writing these like beautiful meaningful test cases
[00:25:20]
and then in the documentation I'm like hmm that unit test I had was a really nice example.
[00:25:26]
I should include that in the documentation for this function.
[00:25:30]
And then I'm like well but what if it gets out of sync?
[00:25:32]
So it just works so nicely that you have this example it executes it it checks the output
[00:25:39]
in the example and your documentation is always up to date.
[00:25:43]
But I think that same sort of workflow can equally apply to internal documentation.
[00:25:50]
You know you could imagine it applying to API documentation or maybe some sort of internal
[00:25:57]
design system that you need to have some example of everything in your design system or something
[00:26:05]
like that.
[00:26:06]
But so that ability to traverse your Elm code as well as your Elm JSON and readme is really
[00:26:13]
cool.
[00:26:14]
So are those the are they set to those specific files that you traverse or can you sort of
[00:26:20]
arbitrarily list files to traverse?
[00:26:23]
No you can only look at files that are related to Elm projects.
[00:26:27]
So the Elm JSON file, the readme, you have some knowledge about the dependencies and
[00:26:32]
then it's the Elm files.
[00:26:34]
You could always use code generation to create some sort of file that tells you about that.
[00:26:39]
Yeah exactly.
[00:26:40]
That's one of the examples that I sometimes use for CSS checking.
[00:26:44]
Like you can take your CSS files and compile an Elm file containing all the list of all
[00:26:50]
classes that are used in there and then you can use those for checking that you don't
[00:26:54]
have any unused CSS classes.
[00:26:58]
Or the other way around that you don't have any CSS classes that are used but never defined.
[00:27:04]
Yeah that's cool.
[00:27:05]
Yeah I've been thinking a lot about whether I should allow to look at other files but
[00:27:09]
then it gets pretty complicated I think with how to set up Elm review.
[00:27:13]
So that's also always a trade off that I need to make.
[00:27:17]
This example of updating the documentation, you can either use code generation or you
[00:27:22]
can use Elm review.
[00:27:24]
Sometimes one will be better than the other.
[00:27:26]
Like code generation will usually be better if you have information somewhere else.
[00:27:31]
Like in the readme, some of the information you only find in the readme so you need to
[00:27:36]
update it.
[00:27:37]
So in that case Elm review makes more sense.
[00:27:40]
Right, right.
[00:27:41]
Yes Elm review is only looking at files specific to an Elm project and the only way to get
[00:27:47]
other information right now is through code generation or something like that.
[00:27:51]
Okay so you sort of before this call you hinted at some new thinking that you have about the
[00:27:58]
regex rule which we talked about in Elm Radio episode 3.
[00:28:02]
We talked about the idea of using Elm review to inspect regexes and make sure that they're
[00:28:08]
valid regexes before in your build process so that you don't have to deal with regex.never
[00:28:16]
and worry about that maybe case.
[00:28:19]
So I actually went all in in that philosophy.
[00:28:23]
So I made a blog post called safe unsafe operations in Elm which basically makes use of the Elm
[00:28:30]
compiler and Elm review to make sure that you always have safe regexes at least when
[00:28:36]
they're literals.
[00:28:37]
So yeah I have enabled that rule at Humio.
[00:28:41]
So we have a no unsafe regex rule that looks at calls of regex.fromliteral.
[00:28:49]
If the literal is not a valid regex then it reports it.
[00:28:52]
Right meaning regex.fromliteral doesn't return a maybe unlike regex.fromstring.
[00:28:58]
Yeah so under the hood it's using an unsafe thing pretty much an infinite recursion.
[00:29:04]
Well no it could use an infinite recursion.
[00:29:06]
It could or it could use a maybe with default regex.never.
[00:29:11]
Yeah so in the case of regex we do have that option so that is what I'm using.
[00:29:15]
Right but you're proving that that code will never be executed through static analysis
[00:29:19]
so it's effectively the same thing.
[00:29:22]
Yeah exactly and I think I also report when regex.fromstring is used with a literal so
[00:29:28]
that you're forced to use fromliteral where you will get the guarantee that it works well.
[00:29:34]
And during the episode the last episode I mentioned that I would like to publish that
[00:29:39]
and now I'm thinking no and it's only for like a tiny reason but I don't want to so
[00:29:48]
you need to have that regex.fromliteral function in your code and I want you to set it up yourself
[00:29:54]
and if you don't set it up yourself then.
[00:29:58]
So essentially is it that you don't want to publish a package which has a function called
[00:30:05]
regex.fromliteral which can be potentially used without remembering to apply that elm
[00:30:12]
review rule?
[00:30:13]
Yes.
[00:30:14]
Yeah.
[00:30:15]
So someone, Emma Bastas is the user name I don't know what the real name is.
[00:30:19]
They wanted to publish a package to interpolate strings so you have some kind of function
[00:30:25]
that puts values in that function.
[00:30:27]
Yes.
[00:30:28]
Yeah I was actually discussing that in Slack as well that was a really interesting conversation.
[00:30:33]
Yeah and they wanted to publish a elm review package next to that to make sure that people
[00:30:40]
use it well.
[00:30:41]
The thing is people will use it without the elm review rule or without even having elm
[00:30:46]
review at all.
[00:30:48]
So you have just published something that is potentially broken for people.
[00:30:54]
Yeah because you can't make this impossible state impossible that there's a good state
[00:30:59]
of you're not using it fine or you're using it and you're remembering to use the elm review
[00:31:05]
rule to check that you're using this unsafe thing only when it's guaranteed to be statically
[00:31:11]
analyzed to be safe.
[00:31:12]
But then there's this impossible state of you're using the function but you're not using
[00:31:17]
the elm review rule and you can't prove that that's not happening.
[00:31:22]
Yeah so you're walking on a tightrope but you have not set up the safety net.
[00:31:27]
Yeah.
[00:31:28]
And that might be a very opinionated but I think that we as tooling authors we really
[00:31:34]
want to not get people to that situation.
[00:31:39]
So what do you think about like is the concern that people would not remember to wire in
[00:31:45]
that elm review rule or is the concern that they wouldn't be using elm review at all potentially?
[00:31:52]
Because I could imagine if it's about not using elm review at all I could imagine some
[00:31:58]
sort of technique where you I don't know where elm review does some code generation or something
[00:32:04]
like that and the only way that this generated code occurs is if elm review handles it and
[00:32:10]
then you could have some unsafe things that you could actually guarantee that you could
[00:32:15]
potentially guarantee through some code generation on the elm review side that the only way you
[00:32:20]
can use these things is with the type that's generated by elm review so you're guaranteed
[00:32:25]
to have at least used elm review initially with it.
[00:32:28]
Yeah yeah yeah my concern is mostly that people don't use elm review or the associated rule
[00:32:34]
because I think that people would mostly just find a package of oh this looks cool and because
[00:32:40]
it allows me to to make strings in an easier way and they don't read the documentation
[00:32:47]
fully or they don't know what elm review is and it sounds like a hassle or they...
[00:32:52]
Right but they want the safety they want the safe regex that never fails or the safe string
[00:32:58]
interpolation that's proven correct.
[00:33:00]
Yeah I think people mostly want just the easier version like oh I can build a regex without
[00:33:07]
having to handle the error case.
[00:33:09]
Yeah that sounds good.
[00:33:10]
Yeah yeah it's an interesting one we should brainstorm a little bit because I feel like
[00:33:14]
there might be some clever way to use a combination of code generation opaque types techniques
[00:33:21]
like that to actually gain some confidence that like elm review has blessed this code
[00:33:26]
and it's an elm review is actually being used otherwise it wouldn't generate the code you
[00:33:32]
need to use this unsafe thing safely.
[00:33:35]
Yeah but would you would you be able to publish it as a package and that is a question.
[00:33:40]
Well you could potentially publish it we need to brainstorm.
[00:33:45]
Yeah I feel like I feel like it might be possible.
[00:33:48]
Okay I'm interested.
[00:33:49]
If you get clever yeah yeah so and if people are interested in this general technique which
[00:33:54]
I think you're saying that you you think it's a good technique but you're reluctant to just
[00:34:00]
publish a package for these concerns but you think that people should use this technique
[00:34:05]
in their own code bases and build their own tools using this technique to use static analysis
[00:34:10]
to do things that would otherwise be unsafe.
[00:34:14]
Yeah definitely but they need to do everything and just publishing parts of it is not good.
[00:34:20]
Right for anyone who wants to read more about this you published a blog post called safe
[00:34:25]
unsafe operations in elm that is linked to in the show notes that's a really nice post.
[00:34:30]
Okay other other use cases and elm review rules that you think are really useful.
[00:34:38]
Yeah so we had one quite odd case at humio so we we have a very big main file with which
[00:34:47]
handles a lot of pages and we're trying to get somewhere to we're trying to get to a
[00:34:52]
state where we use something like elm SBA but the thing is we have a lot of pages that
[00:34:57]
acts like components which have sub pages under them.
[00:35:01]
Yeah they've got the mini t elm architecture trip triples or whatever.
[00:35:06]
Yeah but also some pages have their own router and they those pages also have their own router
[00:35:13]
so it's quite complex it makes things very hard to to refactor so we're trying to get
[00:35:19]
that to that elm SBA like thing thing that we we quite like.
[00:35:25]
Right see our see our elm radio episode about Brian Haskell God's elm SBA framework.
[00:35:31]
So we built our own version of that so that it better fits our needs but basically every
[00:35:37]
one of those pages they have a config page configuration variable that they expose and
[00:35:43]
that gets used in main but since we have a lot of pages we couldn't do them all in one
[00:35:49]
go so so we need we still need to do a lot of wiring in our main file manually and we
[00:35:55]
need to make sure that every page calls that the view from and we need to make sure that
[00:36:01]
the main file calls that pages view that is defined in the page configuration that it
[00:36:06]
calls the update function defining page configuration and so on and then it doesn't use the update
[00:36:11]
function directly because the code will still compile but it would use the wrong version
[00:36:17]
of the update function it would use the wrong version of the view function.
[00:36:21]
So what we did is we added an elm review rule that says if you use page configuration you're
[00:36:27]
not allowed to expose a view configuration a view function or an update function or a
[00:36:33]
subscription functions they should all go through the page configuration and just doing
[00:36:38]
that removed a lot of problems that we could have ended up in.
[00:36:42]
Oh that's a great use case yeah and then because of that you also necessarily reminded us in
[00:36:48]
the main file you should update the boilerplate code.
[00:36:52]
Right so yeah that was one rule that I like to write so at some point we needed to make
[00:36:58]
sure that our dependencies were using licenses that were approved by our company and we need
[00:37:06]
to update our docs using that so what I did was I wrote a elm review rule to make sure
[00:37:13]
that all dependencies have this or that license and if it didn't it was reported.
[00:37:19]
So there's this this rule that has a configuration that says these licenses are allowed these
[00:37:24]
are forbidden because we we have checked them and the legal team says we cannot use them
[00:37:30]
and all the others are reported for us to to contact the legal team and ask them is
[00:37:35]
this okay to use or not.
[00:37:37]
Very cool yeah that's a great use case and this is possible because we don't look only
[00:37:41]
at the elm files it's because we can look at the elm json file and the info about the
[00:37:47]
dependencies.
[00:37:49]
Do you fetch that information like the license information of the dependencies as part of
[00:37:54]
elm review or are you doing some special like extra step?
[00:37:57]
So the I download the dependencies docs.json file and the elm.json file and the license
[00:38:06]
is in the elm json file.
[00:38:08]
Oh cool that makes sense yeah.
[00:38:10]
So we talked about the regex rule and I think there's a mindset to to creating those kind
[00:38:17]
of rules are because if you don't know that a static analysis tool is something that can
[00:38:24]
solve your problem it's something that needs that you need to to be aware of and think
[00:38:29]
about more and more.
[00:38:30]
So now I see elm review as kind of a hammer and everything is nails so I'm trying to remind
[00:38:36]
myself that it's only a single tool or a specific kind of hammer.
[00:38:41]
But you need to I try to remind people that it is a hammer that they can use and sometimes
[00:38:48]
it is appropriate.
[00:38:49]
So usually when I try to use elm review is when I want to prevent people from doing something
[00:38:55]
like we found a bug and we want people to stop falling into that bug again.
[00:38:59]
So what I usually recommend is to use type design to to fix the problem so making impossible
[00:39:06]
states impossible because the compiler is much better at doing this kind of thing and
[00:39:11]
every elm developer knows those tricks.
[00:39:13]
I mean you could have like a you could have like an enum style elm custom type with three options and you could create an elm review rule that it's only one of three strings but represented as a string
[00:39:25]
and that's not the right tool for the job even though you could do that you should you
[00:39:29]
should have a very good reason to to reach for elm review rather than the elm type system
[00:39:34]
when possible.
[00:39:35]
Yeah exactly.
[00:39:36]
Unfortunately sometimes that is not enough.
[00:39:39]
Because you cannot forbid a problem prevent a problem from happening again using the type
[00:39:44]
system.
[00:39:45]
Right you can't inspect literal values in elm and sometimes you want to be able to make
[00:39:50]
guarantees about literal values that are being used.
[00:39:53]
Yeah.
[00:39:54]
So in that case elm review comes in and can save the day and sometimes it is not possible
[00:39:59]
to do with either of those things but you can use them together.
[00:40:02]
So like the regex.fromLiteral function that is a good example good example because you
[00:40:11]
you force people to write in a certain way but then you can check that sub part that's
[00:40:17]
subsection of all possible things and you can give the guarantee that in whatever subsection
[00:40:23]
we are in I can tell you that this is wrong or that this is correct.
[00:40:27]
So you use both API design type design and elm review and that's usually how I try to
[00:40:33]
think about things.
[00:40:34]
Yeah.
[00:40:35]
What are some elm review packages that you you think are worth taking a look at if you're
[00:40:41]
you know if you're getting started with elm review maybe you've tried like you know some
[00:40:46]
of the unused rules and you want to broaden your horizons a little bit and try some different
[00:40:50]
rules what are some that are worth taking a look at?
[00:40:53]
Yeah so there's a elm review debug which is under mining which reports when you use debug.log
[00:41:02]
debug.to do or to string.
[00:41:04]
I recently made a change to debug.log where it auto fixes the debug log so it removes
[00:41:11]
them and very happy about that one.
[00:41:13]
Yeah that's awesome.
[00:41:14]
Yeah but apart from that it doesn't do much.
[00:41:16]
It seems like there's there's a philosophy of keeping the elm review packages very focused
[00:41:22]
sort of Unix toolchain philosophy style.
[00:41:24]
Yeah they try to do well.
[00:41:27]
There's a elm review common which has some rules that yeah the name is just too common.
[00:41:34]
I couldn't find anything more specific without alienating some rules.
[00:41:39]
So they care about how you import things how you export things they care about type rotations
[00:41:45]
and they make sure that in your packages you don't forget to expose some things that should
[00:41:51]
be part of the package that should be exposed as part of the package.
[00:41:54]
You should definitely enable the last one if you have a package author.
[00:41:57]
There's also elm review the elm architecture also under my name which forbids some patterns
[00:42:03]
that we see sometimes in elm code but that is very much frowned upon.
[00:42:08]
I like calling update inside updates.
[00:42:11]
That's a good one.
[00:42:13]
Also defining subscriptions that are empty and forgetting to call the subscriptions of
[00:42:19]
a module if you use the update function.
[00:42:21]
So whenever now I define a subscription function I know that it will be used correctly.
[00:42:26]
It will not be forgotten.
[00:42:27]
Oh I see cool.
[00:42:30]
Phil Sparks also made the elm review ports package which makes sure that you don't have
[00:42:36]
any unused ports in your project because you know that one of the crashes that beginners
[00:42:42]
fall are because you know that when you don't use a port you get a nice sorry ah fuck.
[00:42:50]
So in elm when you have defined a port in elm and you use it in javascript but you don't
[00:42:56]
use it in elm you get a crash.
[00:42:58]
Oh yes oh I know and me you're in and me and you.
[00:43:04]
No I mean it's perfectly normal you know you like you define a port and then you you know
[00:43:11]
for some reason like comment out someplace that uses that port and and it crashes because
[00:43:17]
it's saying that it's an unused you know function does not exist on your app dot ports.
[00:43:24]
Yeah that's a nice one.
[00:43:25]
Yeah that's actually like a production bug that you can avoid by using a static analysis
[00:43:31]
tool.
[00:43:32]
The reason why I say beginners fall into that one yeah is because often they come to slack
[00:43:37]
and they say hey what's happening.
[00:43:39]
Sure sure.
[00:43:40]
Once you've met it then you know what the problem is.
[00:43:43]
You know what to do about it at least yeah.
[00:43:45]
Are you still you still don't sleep quite as soundly at night knowing that one day you
[00:43:51]
might forget and ship something to production that will just crash.
[00:43:56]
Especially if some tool just removed a quarter of your code you know.
[00:43:59]
A bunch of your unused code.
[00:44:01]
Well no but it can and covers right those kind of problems.
[00:44:05]
It makes sense yeah.
[00:44:06]
Yeah I mean you can create those problems.
[00:44:09]
Right right.
[00:44:10]
And then Max also worked on Elm Review imports.
[00:44:13]
So now review ports and imports to create consistent aliases for your imports.
[00:44:21]
Yeah that's awesome.
[00:44:22]
We talked about that concept in our earlier episode.
[00:44:25]
That's a really useful one.
[00:44:27]
There's still some work to be done on there but if you push him I'm sure you will resume
[00:44:31]
work on it.
[00:44:33]
Sometimes motivation is all you need you know.
[00:44:35]
Mm hmm.
[00:44:36]
Right.
[00:44:37]
Yeah just knowing that people find it useful.
[00:44:39]
Yeah good stuff.
[00:44:40]
Yeah.
[00:44:41]
Most of my work has has gone into the Elm Review unused package.
[00:44:47]
That is the most complex one and I think also the most useful one at least as a linting
[00:44:52]
tool.
[00:44:53]
Sure.
[00:44:54]
Yeah yeah.
[00:44:55]
Yeah I think a lot of the most useful things other than unused code rules are going to
[00:45:00]
be enforcing your own company specific standards.
[00:45:04]
And like things like you're talking about where hey if we have this page configuration
[00:45:08]
type and it's being used in this certain way then you know something's wrong.
[00:45:13]
If it's not being wired in then that should be an error.
[00:45:17]
One good rule of thumb for whether Elm Review can be a good solution for your problem is
[00:45:23]
can you detect this problem just by code reviewing it.
[00:45:27]
Just by looking at the code can you see a problem.
[00:45:30]
And if you can then a static analysis tool can do the same work.
[00:45:34]
That means that it can find most problems but it can get pretty complicated.
[00:45:39]
So I want to go through real quick how no unused all the unused rules work.
[00:45:47]
So we have a lot of rules in there.
[00:45:49]
So there is no unused variables.
[00:45:53]
There's no unused custom type constructors, custom type constructor arguments, exports,
[00:45:59]
modules, dependencies, parameters and patterns.
[00:46:03]
So each one does like one thing except variables which does variables and imports for some
[00:46:09]
reason.
[00:46:10]
It's the oldest one.
[00:46:11]
Okay.
[00:46:12]
And the thing is like you like they all do one thing and they're going to fix one thing
[00:46:19]
at a time.
[00:46:20]
So if you have like a let variable which calls a function but you notice that the variable
[00:46:25]
is not used then Elm Review can remove it.
[00:46:28]
So that is one step.
[00:46:30]
So we can commit here and we can compile and we can push to production.
[00:46:34]
Once you do that what Elm Review will find is that the function that it was now what
[00:46:39]
Elm Review can find is that the function call that was the only function call in the whole
[00:46:44]
project for that function.
[00:46:46]
So what we can do is we can remove that function altogether.
[00:46:50]
So instead of doing it as two steps where there's an unused function but within that
[00:46:55]
unused function it's calling another function which is otherwise unused.
[00:47:00]
Is that the case you're talking about?
[00:47:02]
I didn't get it.
[00:47:04]
So there's a function called foo which is unused and that function calls a function
[00:47:09]
called bar and that's the only place that bar is called in the unused function foo.
[00:47:15]
Oh no.
[00:47:16]
Then we first remove foo.
[00:47:17]
Okay.
[00:47:18]
So you do two steps.
[00:47:19]
You call Elm Review fix all.
[00:47:21]
It removes foo.
[00:47:22]
Then you call it again and it says oh I found a new problem and then it removes bar.
[00:47:28]
Yeah exactly.
[00:47:29]
And it does all these tiny things one step at a time.
[00:47:34]
So you can stop at any time and whenever you think oh it's going too far because this actually
[00:47:38]
does need to be used then you can stop, fix the problem or ignore the rule at this point
[00:47:45]
in time.
[00:47:46]
But yeah you do it one step at a time and that is kind of like the incremental steps
[00:47:51]
or the tiny steps that we talked about but just as a tool.
[00:47:55]
Right right.
[00:47:56]
And when you apply all these tiny tiny things like even removing the patterns or the parameters
[00:48:02]
well it uncovers a lot of things.
[00:48:04]
Like even just a let underscore equals something if you remove that maybe you can find that
[00:48:11]
you remove a dependency.
[00:48:13]
Right if you have a custom type constructor which has some data value and you, an Elm
[00:48:21]
review rule tells you that data value is never read, turn it to underscore and then you follow
[00:48:26]
that fix, turn it to an underscore and then you find that that constructor is not being
[00:48:33]
used anywhere.
[00:48:34]
Yeah the argument is never used.
[00:48:36]
The argument is never used and then you can keep following that thread and perhaps that
[00:48:40]
variant is no longer needed.
[00:48:42]
Yeah exactly.
[00:48:43]
So yeah you do all those tiny things and at the end you will remove a lot of code.
[00:48:47]
Some colleague of mine they were able to remove 7000, over 7000 lines of code recently and
[00:48:54]
that was because of all those tiny steps.
[00:48:56]
Like if you just like looked at the unused top level functions then maybe you could remove
[00:49:02]
a tiny portion of that.
[00:49:05]
But if you apply all those things you move a lot more.
[00:49:08]
And then maybe a little bit of manual assistance in between to connect the dots.
[00:49:12]
Yeah sometimes because Elm review won't automatically fix things where it will trigger a compiler
[00:49:18]
error.
[00:49:20]
So some people they want their names to be there for like patterns.
[00:49:27]
Like you do you put a match on the results and you have okay okay and error error.
[00:49:33]
If you don't use the error then people want it to stay, they want the name to remain.
[00:49:39]
With a meaningful name.
[00:49:40]
Yeah exactly.
[00:49:41]
But if you remove that one then it becomes much more easy for a static analysis tool
[00:49:47]
to figure out other things.
[00:49:50]
So that's one reason why I try to not care about that one because I know that the tooling
[00:49:55]
will help me out.
[00:49:57]
There will be some gains.
[00:49:58]
Right.
[00:49:59]
Well any final words of wisdom for people getting started with Elm review?
[00:50:04]
gmpx elm review dash dash templates jfm angles slash elm review unused slash example.
[00:50:11]
Or if you prefer copy pasting look at our show notes.
[00:50:15]
Yeah there will be less error prone.
[00:50:19]
Great stuff.
[00:50:20]
All right well good checking back in on this Jeroen and have a great day.
[00:50:24]
You too.
[00:50:25]
Thanks for watching.