[HN Gopher] Three Ways to Debug Code in Elixir ___________________________________________________________________ Three Ways to Debug Code in Elixir Author : clessg Score : 103 points Date : 2021-12-04 16:01 UTC (6 hours ago) (HTM) web link (blog.appsignal.com) (TXT) w3m dump (blog.appsignal.com) | marcus_cemes wrote: | After seeing Elixir pop up so many times on Hacker News these | last few months, I deicded to give it a go for the Advent of | Code. | | It's been pretty amazing actually, it takes a little getting used | to, but it really feels like a language that was designed in | every way possible to be ergonomic and productive. I'm still not | sure whether it's easier to read purely functional code over a | few mutable variables and simple loops, especially with a lot of | filter, reduce, scan, zip, etc. | | It's been pretty amazing so far, I haven't gotten further than | IO.inspect()ing yet. The language server is still leagues even | behind something like Rust analyzer (even renaming symbols is | still a work in progress), but it's amazing that such a language | already has one of the leading web frameworks (Phoenix), and | despite being very network orientated, it's also excellent at | solving AoC problems that involve a lot of clever manipulation of | strings, binary, integers, and the sorts! | brightball wrote: | Yea, my experience has been that after getting deep with Elixir | and understanding how and why it (and the BEAM) works the way | it does, everything else feels very limiting. Like I know all | of the problems I'm willingly setting myself up for long term. | dnautics wrote: | > It's been pretty amazing so far | | Wait till you learn about async tests that are pinned to single | database checkouts. And -- how async is composable with respect | to resource pinning. AFAICT no other language does this (not | even erlang). | clessg wrote: | > I deicded to give it a go for the Advent of Code. | | That reminds me: in case anyone is curious how that looks in | practice, it just so happens the creator of Elixir (Jose Valim) | has been streaming Advent of Code exercises using Elixir (and | Livebook): https://www.twitch.tv/josevalim | peoplefromibiza wrote: | My 2 cents | | I've been an Elixir developer for years now, loved it | immediately and still loving it after all this time. | | About refactoring: I've been working as a Java developer for | the past couple of years and I must admit thaat Intellij does a | pretty impressive job at helping you refactoring code and their | code sense is top notch. | | But, there's a but. | | I've never found myself having to make nuclear refactorings in | Elixir, not because I don't refactor my code, but because | modules are self contained and not tied with anything else, | most of the times it is faster to abstract something over what | you already have than to refactor all the things. | | For example, if you decide that you need a struct instead of | the old map, you advd a new function that pattern matches on | the struct and pass it down. | | If the struct has a different structure, you process it and | pass it down. | | The "treat data as something that is constantly transformed" | mentality can take you a long way. | | When I can code in java in a way similar to what I do in | Elixir, things get easier in Java as well. | | I miss symbol renaming in Elixir too, but it's never been a big | stopper in the 6 years I've used it as a primary language. | | edit: biggest strength of Elixir is Jose Valim himself. If you | watch his videos you can see him finding a bug while doing | something, actually explaining why that's a bug in Elixir (or | some library) open an issue and ask for PRs | | All while showing you complex software patterns that I though I | could never face before using Elixir. | marcus_cemes wrote: | I understand, but a lot of my refactoring is within functions | to simplify and improve legibility once they work, renaming | variables with generic names from "result" or "data". | | It's a lot faster to do a cheeky F2, knowing that it's not a | blind find/replace but a static code analysis with the | ability to understand variable shadowing. Definitely not a | show stopper though, and it feels more old-school, where | every letter you type is more meaningful, if that makes | sense. | | And a huge +1 for Jose Valim and the whole community behind | him! | michaelterryio wrote: | Ah, yes, this is how I refactor in Elixir too. I feel icky | about it from a DRY standpoint but I'm training myself to | ignore the scolds that held me back from being productive for | so long. | ketzo wrote: | It can't be emphasized enough how good IEx is. | | Maybe it's because it is my first experience with a language like | Elixir, but man, it just feels like I'm _living inside_ the | program while it's running in a way that an IDE debugger doesn't. | It's so cool and so powerful. | marcus_cemes wrote: | I will never forget the first time I started IEx from within a | Phoenix project, and found that I had a live shell into the | running application, while the Phoenix development server was | running and reachable from the browser, all with hot code | reloading... No need to create a dummy REST endpoint to try | running a function. | | My mind was blown. | zorbash wrote: | Another thing worth trying, is connecting a Livebook instance | (see: https://livebook.dev/) to a running application. Keep | in mind Livebook allows for multiple users to work on the | same notebook at once so this can come handy in pair- | programming / debugging situations. | derefr wrote: | Give a remsh connection to a production cluster, you'll find | IEx really does mean "living inside" the process--you can reach | out and add a live trace hook to e.g. a Phoenix Controller | function, and then immediately see traces from _your live prod | users_ hitting that trace point. Without recompiling or | restarting the app--their _existing_ in-memory session state, | local in-memory caches, etc. are suddenly exposed to you, | without needing to discard any of it via a redeploy /restart | and then wait for new user sessions to reproduce the problem. | | (You can even redefine the module in-place in memory to see how | changes affect what you see. Brings a whole new meaning to | "hotfix": you can do hotfixes that don't even exist on disk!) | arthurcolle wrote: | :observer.start is awesome too | dnautics wrote: | It's like you are in bash, except you can run real functions, | and your variables aren't stringly typed. | dnautics wrote: | for anyone using Elixir + vscode, this snippet is invaluable: | { "Inspect": { "prefix": "ins", | "body": "|> IO.inspect(label: \"$0$TM_LINE_NUMBER\")", | "description": "Adds a pipeline with a labelled `IO.inspect`", | } } | | when you type ins<tab> it injects a labelled IO.inspect that | makes it easy to track where the data came from; usually in a | debugging session the line numbers will be sufficient to track, | and more importantly, it's almost always easy to ninja out these | IO.inspects in one shot, because they are almost always the same | number of characters long (since contiguous line numbers are | usually in the same decade). Credit goes to one of my former | junior devs who built this. | | video demo: https://www.youtube.com/watch?v=JXQZhyPK3Zw&t=1410s | (note slickbits doesn't seem to exist anymore) | mmartinson wrote: | Recon trace is a worthwhile addition. I've used it for some hairy | production bugs that don't reproduce locally. Allows you to | unobtrusively instrument a running system and echo back function | calls with their params, including process targeting if needed. | | There are a number of powerful tools for BEAM runtime tracing. I | prefer this one because the API is simple enough to commit to | memory, and it protects against some common foot guns. | | https://ferd.github.io/recon/recon_trace.html | michaelterryio wrote: | Yep, and here's a nice intro video from this year's ElixirConf: | | https://m.youtube.com/watch?v=F7YtYTMud-Y | jetpackjoe wrote: | I recently wrote a port of the python IceCream | project[https://github.com/gruns/icecream]. | | Feel free to check it out for easier IO.inspect ergonomics: | | https://github.com/joseph-lozano/ice_cream | enraged_camel wrote: | I don't think I've ever used `IO.puts` for anything. As the | article notes, `IO.inspect` is far superior. | | Also, the Erlang observer is super neat. One really cool thing | you can do with it is attach it to a _remote_ machine, which | comes in real handy. ___________________________________________________________________ (page generated 2021-12-04 23:00 UTC)