Phoenix LiveView: Async Assign Pattern

I've been using LiveView for about two years now. It's a great framework that makes snappy and responsive pages. One anti-pattern I see fairly often is loading a lot of data in the initial page render. For the un-initiated, the mount/3 function is called twice.  Once for the initial 'dead' render, and again after the socket is connected.   Many times, for the sake of simple straight forward code, not much is done differently between these two renders. I haven't found any references (I'm sure they exist) on a best practice for managing the following flow: Set sensible, lightweight default values on initial render. Kick off one or more async processes to make longer running function calls. Receive the values in the LiveView, and update the assigns. As always in Elixir, the tools are powerful, and theres many ways to accomplish this. Spawn a linked, or unlinked process. Start a supervised, or unsupervised Task. Make a call to a GenServer, and have it send a mess

Custom Kaffy Styling

I recently gave a talk at Empex NYC ( link to talk ) on why you should be writing admin tools from day one .  In my talk, one thing I highly suggest is to make it very obvious what environment you are in when providing a web admin UI for your team.   We've been using Kaffy at SwayDM since the beginning.  At the time, you couldn't easily overwrite the styling.  I maintain a private fork of Kaffy for changes I've made, which included the ability to change the background color. I recently merged the past few minor Kaffy releases back into my fork, and saw that Kaffy now has the ability to provide Extensions which allow you to inject custom html, css and javascript.  I spent a little time making a custom CSS file to change the color of the Kaffy nav, and add a title which notes which environment you are in. For each environment, I have a static file for CSS styling overrides. kaffy-ext-local.css kaffy-ext-staging.css kaffy-ext-production.css defmodule SwayDMWeb.Admin.Kaffy

ELI5: ChatGPT is a Giant Plinko Game

Photo By: sumofus ChatGPT is like a giant Plinko game. Plinko is a game where you put a coin in at the top. The coin falls down the board, hitting pins that influence it on the way down. At the bottom are slots, with various points or prizes. Depending on where you put your coin in at the top, you have different chances of which slot it will land it at the bottom. It's not random, some slots will be more likely than others depending on where you start. Now, rather than a coin going in at the top, assume it's your question to ChatGPT. At the bottom, rather than prizes, assume it's all possible words. ChatGPT looks at your question, and determines based on the words you used where to put your question in at the top. Then, the pins influence your question on the "way down" depending on what the words are. Rather than landing in on a single word, ChatGPT outputs a list of the most likely words to come next. ChatGPT then picks a word from the most likely words and show

Write Admin Tools From Day One

UPDATE:  I gave a talk expanding on this blog post at EMPEX NYC 2023 . The Problem Writing useful features for your users is key to a successful product.  It makes sense then that you should maximize your time writing features for those users.   This approach is very effective at the beginning of a product's life, but over time, you may find you are spending more time maintaining the product that developing it. Some of the biggest development time sucks can be: Tracking down the cause of unexpected behavior. Fixing data. Answering user, or team member questions. Running maintenance scripts, or other ad-hoc tasks. The "Oh #&@$" Solution These small support tasks start to add up, and there is no easy way to offload the work to product, or support.  You and your development team reach a breaking point where you must start prioritizing administrative tools. Unfortunately, you will slow down your new feature development even more in the short term.  It will take time for t

Your Software Should Suck

Good software is really hard to write.  When software is good, you almost don't notice it.  The UI / UX doesn't get in your way.  You can do what you want easily. When software is bad, it's frustrating, but you still use it because the alternative is worse.  Maybe it's replacing a manual / tedious process, or provides functionality that simply could not exist otherwise. People will put up with bad software. I've worked on projects where the #1 user requested feature wasn't implemented for over 7 years.   Guess what.  The software still sold, and the company was still successful.  This is because it was better than the alternative. So what makes good software?    Good software doesn't start good.  It most likely sucked.  The odds that you will get every aspect of your software correct on your first iteration are slim.    So don't try to pack every feature into that first release.  Get the bare minimum out there, and get feedback.  The key is to listen to

Fingerprinting Knock errors for Sentry in Elixir

At SwayDM , we use the fantastic Knock platform to define notification workflows, and deliver emails, and SMSs to our users. Our codebase is written in Elixir , and we use Sentry for error reporting via sentry-elixir .  One thing you can do with sentry-elixir is report an event to Sentry every time your app logs at the error level.  You can also specify which metadata logger keys are forwarded to sentry as metadata attributes. This works great in conjunction with Knock, but if you only log the error, all your Knock related issues in Sentry will be grouped as one, regardless of which identify, or workflow caused them.   This is where custom fingerprinting comes in. Configure Sentry First, configure sentry to define a module, and function to be invoked before the event is sent to Sentry. You must have the Sentry LoggerBackend configured.  If you want to pass logger metadata to sentry, you must explicitly add it to this configuration. Capture Logger Metadata Capture details in the logge

Don't Outsmart Yourself

  The great Richard Feynman had a saying.  "The first principle is that you must not fool yourself and you are the easiest person to fool."    I believe there is a similar principle that can be applied to software engineering.  "Don't outsmart yourself."    As a software engineer, it can be easy to: Over-engineer a solution to a simple problem. Strive for elegance over ease of understanding for others. Use an obscure, or less popular approach to solve a problem. Abstract away complexity pre-maturely. Write a custom library when something that could have worked off the shelf would have sufficed but maybe wasn't a perfect fit. It feels good to do these things.  It works parts of your brain that might be aching to do something interesting.   It can impress your peers.   In time though, you will outsmart yourself .  The smarter you are, the more prone you will be to outsmarting yourself.   The trick is to balance ego with prowess.  Yes, you could  do it your sup