[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)