Do you use Dialyzer/Dialyxir in your Elixir projects?
- Yes - all of them
- Yes - some of them
- If you only use it in some of them, which ones?
- If you don’t use it, why not?
- If you do, any thoughts or experiences you’d like to share?
Do you use Dialyzer/Dialyxir in your Elixir projects?
Totally! And additionally I use Gradient, and Credo, and ExDoc in every project as part of my QA.
Recently added specs to a lib I am creating and let Emacs run the dialyzer.
However, I might checkout other typing libs in the future as imho dialyzer clutters the codebase and it’s error reporting is not on par with modern type checkers.
I find dialyzer to work well for projects, which are deployed. I tend to not like it for libraries, which don’t really use their code, because that usually means dialyzer doesn’t find half of the issues.
Hopefully Gradualizer as well, once it is mature enough to run on large code bases!
I use dialyzer, but it’s almost an act of faith for me: I pray and hope it will help me discover some nasty bug in my code someday. That hasn’t happened yet but I keep waiting and hoping
Yah, I used it for a year, but I finally gave up updating specs. Doctests seem to do the trick for me.
Yep. Big fan.
Anything that lets me catch potential issues before they happen brings me value.
I always try to have typespecs on my functions, both as an help to the reader of the code, but also in order to allow the Dialyzer to catch at least some errors.
But I have to admit that I do have quite a love/hate relationship with the Dialyzer. It does really catch potential errors, but the error messages can be really difficult to understand, especially when largish structs are involved.
Over time I’ve gotten somewhat used to the error messages so much, that I in most cases relatively quickly can scan through the errors and identify the problem. But for newcomers, it’s really not a pleasant experience.
However, as I do prefer having explicit typespecs on most functions, it is really nice to have at least some validation of them.
I’m using it but I definitely have mixed feelings about doing so. I’m currently building my first non-trivial/non-toy project with Elixir and I would say on balance Dialyzer has been helpful, but it can be frustrating. The cost/benefit of employing Dialyzer isn’t completely clear to me yet.
On the plus side I do think it has helped me to find issues, maybe not a lot show-stoppers, but let’s say it’s kept me honest. I also like the documentary aspect that the typespecs have on code, despite the visual clutter.
The downsides, often times the problems it finds are with code that works fine and would even always work fine even in the presence of the found error; the more important errors are usually found through other means like reasonable testing before I get there with Dialyzer. I’m concerned that I don’t understand what sorts of things it won’t or can’t find that could be real problems; it’s possible to take typespecs pretty far, but that Dialyzer the tool can follow is unclear. Finally, I get a number of errors in my editor (VS Code / ElixirLS) that don’t get found by Dialyzer. I think this is due to false negatives in the editor moreso than Dialyzer missing something; the cases that I’ve very thoroughly looked into this has been true and the fact that often times I can resolve the issue the editor is reporting by cleaning/rebuilding the project suggests that the Dialyzer analysis is more correct. My gut feeling is that the presence of typespecs seems to cause these discrepancies between the tools to happen more often than not having the typespecs. Anyway all this leads to the feeling that I’m investing a fair amount of time troubleshooting the tooling and that writing of typespecs causes a class of false negatives leading to distractions from the work at hand.
As a beginner in writing the language without a second set of eyes looking over my results, I think this ends up being a net positive since even the smaller issues that I tend to find with Dialyzer are conditions I need to be sensitive to to move beyond the beginner stage. But if I were more accomplished or working on a team, as I said at the beginning, it’s unclear whether or not the benefits would out-weight the maintenance overhead. I want to feel that running Dialyzer in CI and getting an all clear means that I’ve achieved a certain kind of soundness to a high degree, but that trust just isn’t there yet.
No. Too slow, too cryptic. Hoping for something like Gradualizer to be usable. In the meantime, I invest time in end to end tests.
We use it at work but I never in my personal projects. I also don’t use specs except on
defstructs and behaviours (though do use pretty liberal use of pattern matching and guards where it makes sense). I’m one of those dynamic-loving wienies and probably always will be.
As an Elixir beginner I’m using Dialyxir and it gives me some value, so I keep using it. I’ll echo what others have said before me - the error messages are really hard to understand compared to what something like mypy produces for Python. It’s gotten to the point where I usually don’t read the Dialyxir messages, but instead just look at the code/specs myself and try to figure it out.
As always, if I practised reading the error messages more I’d get better at it, but there’s definitely some skill involved in making sense of them right now.
I encourage everyone to start using Gradient, GitHub - esl/gradient: Gradient is a static typechecker for Elixir, and publishing issues with whatever you think it should be improved/fixed. I will help a lot to Gradient and Gradulizer itself to reach the point of maturity that still needs.
I use it everywhere and all the time. After 6 years of full time Elixir I think it’s one of the most underrated tools available to us. I think dialyzer is only as good as you use it. More (and better) the types, the better it works. I think when it’s sprinkled in a code base and the type definitions aren’t very clear (like using any, term, keyword, and map types) most places the tool doesn’t really help. Being really clear in the typing and use of type docs also provides a benefit to the documentation of the code and even that provides longer lasting benefits to maintenance over time. It’s one of those tools where you get out of it what you put in IMO. It’s not perfect in developer experience but it has provided me massive value over the years. Drop me into a Elixir project with very little to no types I’d probably struggle, I am not smart enough to not use types in my code base.
I have two decent size work projects. We use dialyzer pretty consistently through that project - specs on the interface to every module and dialyzer run in CI.
I’m not sure we got value out of it - we spent some hours tracking down odd failures that we’re caused by an area completely different to where the error is reported and mostly it was a dialyzer/spec issue rather than a real one.
So when the second one started I didn’t make it part of the process. Dialyzer is not running in CI and there is only the occasional hand written spec (in addition to ones provided by libraries and use of behaviours). We do get some value out of this - I (and most of the team) have error highlighting on VS Code like you normally do and that catches some stupid stuff before running anything. As our target is embedded (Nerves) that can really save some time.
If the errors were better (both in content and pinpointing the location) then I would definitely revisit it, but I remain to be convinced of the value of ‘tacking on’ a type system. I need to experiment with gradualizer too.
Dialyzer as it exists today is a net negative value add for me. I only use it if forced. In principle it checks out, but in practice it always costs more than it saves.
Dialyzer gets some time to get used to and I understand the pain associated with learning how to use it effectively.
Moreover, I have the impression that in Elixir, due to much higher macro proliferation than that of parse transforms in Erlang, it’s more often “wrong” (not technically wrong, but a nuisance without being helpful) because of warnings about the generated code. E.g. a macro might take params and based on them sometimes generate clauses which are always true or always false etc. This will trigger a Dialyzer warning. It’s not a Dialyzer bug, rather a macro bug or just “coarseness”, but the result is having to add such cases to
I’ve run into a lot of the things others have already mentioned, e.g. cryptic errors, but I think, overall, Dialyzer is great. It does make me wish that typespecs were more ‘algebraic’ – or that I could (sometimes) use ‘regular’ static typing instead.
Most of the errors/warnings reported for the code in the projects for which I’m using Dialyzer have been helpful – it’s definitely spotted real errors/issues.
The biggest annoyance has been warnings about other code tho, i.e. dependencies. That did result in me contributing at least one fix to another project tho, e.g. correcting a typespec. But even reproducing the warning for the dependency itself has been difficult, in particular for at least one Erlang project.
In the biggest project for which I’m using Dialyzer, it takes less than 30 seconds to run, even when several dozen files need to be compiled first. That’s acceptably fast IMO.
As someone who is working a lot with Typespecs, for instance while working on the library TypeCheck, here’s some of the struggles I have with using Dialyzer:
MapSets will make Dialyzer complain about usage which is recommended by Elixir’s official documentation. (Source: elixir/#8463 and elixir/#8480)
However, I still use it regularly, especially on smaller and simpler projects. I like the ‘belt ánd suspenders’ kind of approach w.r.t. detecting potential bugs early.
And as @eksperimental already noted: Gradient/Gradualizer is a wonderful new project, and very much worth keeping check on!