As of last Tuesday, Elixir Streams has a 100 tips! Since Elixir Streams has hit this milestone (and I'm amazed it did), I wanted to look back and share some history, some behind the scenes, and some of my experiences.
I have worked in teams where a product manager assigns tasks to developers. On paper, that works. And it's likely done in the name of parallelizing work -- "look at all the projects we're working on at once!" But in my experience, that top-down approach to assigning work has a huge downside: it discourages team collaboration.
We either refactor continuously as we build features -- paying the price. Or we slowly accumulate cruft until our codebase is impossible to change -- paying the cost.
Someone in my Testing LiveView course recently asked me, "When would you use assert_redirected instead of assert_redirect?" Just by looking at the helpers, you might think we want to use assert_redirected. But I always prefer using assert_redirect. Here's why.
I've always been fascinated by how Elixir's Stream module handles lazy operations by storing the operation data in a struct. 🤯 It's so simple but so brilliant! So, I wanted to see what it'd be like to write a simple implementation of a lazy math evaluator.
Phoenix 1.7 is dropping path helpers in favor of a new concept called verified routes. Let's see how it handles typos, missing paths, arguments, and query params.
I've been digging a bit more into Elixir's `dbg/2`. It's a really powerful tool for debugging. For example, it's an improvement over `IO.inspect/2` calls, and we can use it to pry into code with `iex`.
Phoenix 1.7 is dropping Phoenix.View, but it's for a good reason! Controllers and LiveViews will now render function components. And the aim is to collocate templates next to the controller that renders them!
In the past, I used `hub` to create GitHub pull requests. Recently, I decided to replace `hub` with GitHub's newer, official CLI (gh). At first, I found `gh` to be too verbose. But soon enough, I found the correct commands and flags to fine-tune my workflow. Here are some of my favorite commands and flags to deal with PRs.
When I first learned BDD (behavior-driven development), I saw a graph in The RSpec Book that helped me understand the flow of BDD. I don’t have that book anymore, but I still remember what the graph looked like, and it’s so helpful! Let me show you what I remember.
I want to see how to handle 7 GUI tasks in LiveView. Here are the highlights from implementing the sixth task: a Circle Drawer with undo and redo functionality.
The title of this post is a quote from The Mom Test, a book that teaches the art of having useful conversations with customers so they won't lie to us about that business idea we're eager to explore.
One problem with shared setup in Elixir is that it can pollute our tests: creating unused data, introducing mystery guests, requiring extra database operations, and obscuring critical information.
Back in LiveView 0.12, testing a LiveView connected to the database would sometimes result in our test passing but us seeing the Dreaded Wall of Red Text. Then, in LiveView 0.13.0 those errors were gone. How?
Someone from my Testing LiveView course recently asked me about the immutability of the `view` we get from `live/2` in LiveView tests.
It's not the first time someone's asked me that question, so I wanted to try to clarify things a bit.
You're working in a codebase. You stumble upon something you'd like to change. The code change will only take 2 minutes.
Do you make the change and open a Pull Request?
The answer likely depends on how costly it is to open that Pull Request. And that cost is commensurate with the loss of context of our current work.
To practice test-driven development (TDD), I recommend developers reduce the friction involved in running an individual test.
Since TDD uses test failures as guidance for implementation, it is most helpful when we have a tight feedback loop. But if running tests takes a long time, we don't run them as frequently, and we miss out on the tests' feedback.
I really like how closely Ecto integrates with our database. That was a surprising difference when I first came from Rails.
Ecto’s constraints are a great example of that. Like Rails, Ecto has validations. But unlike Rails, Ecto also has constraints. Validating uniqueness is the example that most easily comes to my mind.
In a previous post, I wrote about how we can test a named singleton process in our system. There's one more improvement we can make for better cleanup.
I was reading the paper Mock Roles, not Objects, and there's a description of TDD that captures an important concept I haven't been able to put into words before: TDD changes code design from invention to discovery.
A reader recently asked me about mocking external dependencies in Elixir. So, I wanted to discuss two popular mocking libraries and how to mock without a library (and which option I like best).
I've always liked the Dependency Inversion Principle (DIP). Once understood, it helps us decouple code in surprising ways. Let's take a look at how Elixir protocols decouple code through DIP.
When developers onboard new projects, we are uniquely positioned to help improve the onboarding experience for future developers. So, when I join a new project, I relish the opportunity to clarify and simplify setup instructions.
elixir lunch is now elixir social. I renamed it because very few people brought lunch 😅. It seems most weren't interested in that part. But they were interested in hanging out with other Elixirists. So, I figured I'd roll with the punches.
Named singleton processes are wonderful for Elixir applications, but they often make it hard to test their behavior. Since singletons are started as part of the supervision tree, they become a globally shared resource for our tests. And that can lead to intermittently failing tests due to race conditions.
I'm excited about LiveView's JS commands (introduced in 0.17.0) because they allow us to express JavaScript within our LiveView code. And that makes it easier to create certain types of interactions.
People new to Elixir, especially those coming from Ruby, might be surprised at how Elixir dates and datetimes are compared. It's easy to introduce a subtle yet dangerous bug.
Many Ruby friends think of Elixir as just a functional Ruby. So they see it, maybe try it, and walk away. But that's just the surface. Beneath the surface, Elixir brings a runtime system that we can design and control to build applications that heal themselves.
Testing web pages often requires targeting elements with CSS selectors. But which CSS selectors should we use? Are some better than others? I think so.
One of the concepts I found most interesting about Shape Up is the concept of appetite. Like a deadline, appetite talks about the amount of time we're going to spend on a feature or project. But the process is wonderfully reversed.
It's tempting to write `LiveViewTest` assertions that specify too much of our HTML. But that couples our tests to the implementation specifics. There's a better way: the `has_element?/3` helper can help us be specific without adding coupling.
Our communication practices can be very disrupting. Remote work has taught me to be more considerate of how I communicate with others. We should treat other people's time as we like ours to be treated.
Our communication practices can be very disrupting. Remote work has taught me to be more considerate of how I communicate with others. We should treat other people's time as we like ours to be treated.
Most people learn vim's `normal`, `insert`, and `visual` modes. But they're only casually acquainted with vim's powerful Ex commands. Let's take a look at some.
Vim has a reputation for being hard to quit. But it turns out there are so many ways to get out of it — it's like vim wants you to quit. Let's look at a few.
My workflow usually involves squashing many commits into a single one. But sometimes, the workflow calls for the opposite action -- splitting a single commit into many. This is how I do it.
Having your code reviewed can be daunting. But it can also be very helpful. As reviewers, we can make the difference. Here are five tips to make your code reviews more helpful to the author.
When faking external services in tests, start with something simple. I like having a public interface to adapters and having an in-memory adapter for tests. Let me show you an example.
Toggle between alternate files, edit files by type, and create files with templates — all with `vim-projectionist`. If you've never used it, you're in for a treat.
Many people ask, "How do I find time to refactor?" I think the question itself betrays a misunderstanding of refactoring. Let me tell you when I refactor.
Don't let your git repo become a graveyard of stale branches. But how do you even know what branches are there? Let me introduce you to `git branches`.
Refactoring has a specific meaning. When we misuse the word, we lose the ability to communicate an important concept. Let's revisit what refactoring is and what it is not.
Recently, thoughtbot decided to make Upcase free. It has a lot of great
learning materials, especially when it comes to Rails, vim, test-driven
development, and tmux.
Elixir is known for being a language made for building distributed applications that scale, are massively concurrent, and have self-healing properties. But is Elixir good enough for the mundane scripts of this world?
When coming from object-oriented languages, I often hear people ask the question, “How do I organize my code? Modules are just bags of functions!”. That is a question I asked myself as well, but after using Elixir and Elm for a while, I have noticed that there is a principle of organization that I keep using and that I see in the wild. I like to think of it as the principle of attraction.
Concurrency is a first-class citizen in the Elixir platform. The concurrency
model is that of isolated, independent processes that share no memory
and communicate via asynchronous message passing. In other words, a process
can run concurrently without concern of others, and processes communicate
with each other only via send-and-forget messages.
One of the benefits of tests is that they are the first piece of code that will interact with our application. As such, they can offer valuable insights into the application's complexity.
Supervision trees are awesome. For a while I was a bit confused as to how to use the simple_one_for_one
supervision strategy. Let’s look at it step by step by creating a simple
bank account from which we can deposit and withdraw money.
When working on a feature, I often find pieces of code that I have not seen before. In order to better understand the class or method, I like to use tests as documentation and as a way to explore the code's functionality.