Hi friends 👋 Welcome to March, the only month where you get to wear both your favorite winter coat and your favorite flip-flops on the same day.
We have a packed issue today, so I'll keep the intro short. But here's the one thing I don't want you to miss: Frontend at Scale has a new podcast! I know, I know, they let anyone have a podcast these days. But hey, what I lack in professionalism, I make up for with excellent guests. You'll find a link to watch/listen to the first episode of Frontend.fm below. I'd love to hear what you think of it :)
This week we'll also talk about fighting complexity one line of code at a time, Doom in TypeScript, React in Laravel, John Ousterhout vs. Uncle Bob, and much more.
Let's dive in.
MAXI'S RAMBLINGS
Sustainable Simplicity
If you’ve been following the newsletter for a while, you might have noticed I have a bit of an obsession with complexity.
Well, maybe obsession isn’t the right word, it’s more like a fascination or admiration for it. Either way, you’d be right to say I just won’t shut up about it.
A normal person would have talked about this with their therapist. Me? I did the next best thing—I gave a talk.
The TLDR of my talk is that complexity is an impossible enemy that can never be completely eliminated, but that it is our job as software developers and protectors of the realm to try anyway. And the most effective method I know how to do that is to attack it directly at its core by finding ways to make the code easier to change or easier to understand.
There are a few ways we could go about this. One is with the infamous big rewrite or refactor, which, while necessary in some cases, tends to be a far too expensive option for most projects. Another method is by doing periodic “simplicity sprints”, in which part of the team takes some time off of their regular duties to tackle the gnarliest parts of the codebase. This is a good option, but also not a permanent solution.
In my experience, the most effective way to keep complexity at bay is by practicing what I like to call sustainable simplicity—making small, incremental improvements over time by essentially asking ourselves this question every time we touch the codebase:
“What’s one thing I can do to make the codebase easier to change or easier to understand in the future, either by me or someone else?”
If you draw a blank with that question, you’re certainly not alone. Coming up with ways to simplify your code isn’t always easy, so here’s a checklist with more specific questions that can help you get started.
The Sustainable Simplicity Checklist
‣ How can I make this code more readable?
This includes tiny things like giving functions or variables more descriptive names, as well as bigger but still not huge things, like “un-nesting” a piece of code to make its flow of execution easier to follow.
‣ How can I make this behavior more obvious?
Whenever we make a change that ends up breaking a completely different part of the codebase, and we have no idea why, we’re dealing with some of the main symptoms of complexity—implicit dependencies and unknown unknowns. Making those dependencies explicit and more obvious is a great way to reduce complexity and make our code more predictable.
‣ How can I optimize for the most likely changes?
We’re often told that we should “optimize our code for change.” This is a great piece of advice, but it can also be a bit confusing. After all, there’s an infinite number of ways in which the codebase could change in the future, and we clearly can’t optimize for all of them.
Sometimes, however, we can figure out what the most likely changes are and find ways to make them easier in the future. Did we just spend two weeks adding support for a third type of user in the system, even though the product team pinky-promised us that there would only ever be two types of users? How can we prepare the codebase so that adding a fourth type of user in the future doesn’t take as long?
‣ How can I represent this complicated logic as data?
Data structures such as objects and arrays are always easier to deal with than functions or classes, so whenever we can represent the rules of a piece of code as data, we should. We saw an example of this type of optimization when we talked about preparatory refactoring a while ago.
‣ How can I better encapsulate this logic?
Sometimes, the piece of code we’re dealing with is just too complicated and there’s no good way to simplify it. Maybe the rules are too complex, or there are too many edge cases, or (worst of all) timezones might be involved. When this happens, it helps to ask ourselves how we could better encapsulate the code so that its consumers don’t need to know anything about its internal logic.
‣ How can I separate what changes from what stays the same?
In every codebase, we’ll typically find at least one module that is a) extremely big—potentially thousands of lines of code, b) changes very often, and c) contains some of the most important logic in our entire application. Sandi Metz calls these “death stars,” and while they aren’t pretty, they’re a staple in almost every codebase out there. One of the most effective ways of dealing with these is to identify the parts of the code that change more often and pull them apart, so that the next time we have to work with them, we aren’t exposed to the death star’s entire complexity.
‣ How can I break down this large module into a bunch of smaller ones?
This is a more general version of the previous question. Whenever a piece of code is doing more than one thing at a time, there’s an opportunity to simplify it by decomposing its responsibilities into two or more smaller chunks.
‣ What information did I just learn that could be useful for someone else in the future?
Have you ever spent an hour trying to understand how a piece of code worked so that you could make a one-line change in the right place? How annoying is that?! Anyway, don’t let your hard-earned knowledge go to waste, and document it for the next person. This doesn’t have to be a whole thing—even spending 5 minutes writing a useful comment could save the next person hours of pain. And remember, just like the nearest exit on a plane might be behind you, the next person to touch this code might be your future self.
You might be aware of the campsite rule of always leaving the codebase better than you found it. The sustainable simplicity rule is an adapted version: always leave the codebase simpler than you found it.
By themselves, none of these tiny changes will have a disproportionate effect on your codebase, and frustratingly, complexity will still continue to accumulate despite our best efforts.
But these tiny improvements add up, and they’re our best line of defense against an impossible enemy that is otherwise guaranteed to take over our code.
FRONTEND.FM
AI, Personal Software, and the Future of Software Development with Addy Osmani
Have you heard the good news? There's a new podcast in town! And yes, I'm a bit biased, but if you ask me, I'd say it's pretty good :)
Addy Osmani joined me on the very first episode of Frontend.fm to chat about his journey in tech, the rise of personal software, the impact of AI in software development, and much, much more.
I'm really happy with how the episode turned out, and I'm sure you'll find Addy's insights incredibly valuable. You can listen to our full conversation on YouTube, Spotify, and Apple Podcasts, and you can also check out the shiny new website to find the show notes, full transcript, and links to all the things.
If you enjoyed the episode, please subscribe to the podcast on your favorite platform (or all of them for extra awesomeness points!) More conversations with other incredible guests are coming soon.
Add to your queue |
ARCHITECTURE SNACKS
Links Worth Checking Out
- There is a big chance you've seen Jodie Burchell's talk on LLMs at last year's GOTO conference already because it is, according to Tech Talks Weekly, the most-watched talk of 2024. And for good reason—it is an excellent, hype-free, and super clear overview of how LLMs work, whether they're actually "intelligent," and how can we learn to use them more effectively.
- My friend and teammate Buzz Usborne launched 2 Weeks AI, a FREE and absolutely beautiful crash course for total AI beginners. If you know someone who's curious about AI assistants like ChatGPT but doesn't know where to start, this course is perfect for them. And it's totally free! There's no sign-up or anything—just open it and start learning.
- Stefano Magni wrote a super detailed deep dive on how his team at Preply improved the INP of their Next.js application without React Server Components or the App Router. If you're looking to learn strategies for measuring and improving your app's performance, I highly recommend giving this one a read.
- Harper Reed wrote about his workflow for building with LLMs, complete with prompts to help us brainstorm, plan, and execute tasks, both when working on greenfield projects and with legacy, rusty code.
- After a year and a half of what I can only imagine being an absolutely painful experience, Dimitri Mitropoulos from Michigan TypeScript managed to run the classic 1993 Doom entirely within the TypeScript type system. All it took was for him to develop his own computer from scratch and process 3.5 trillion lines of TS types. No biggie.
- If your level of TypeScript expertise is closer to mine, on the other hand, Dr. Axel Rauschmayer gots us covered with a beginner-friendly overview appropriately titled What is TypeScript?.
- A new version of Laravel is out, and it comes with some brand new, fully-customizable, and absolutely stunning React, Vue, and Livewire starter kits.
- Addy Osmani, whom you might recognize as the guest of the hottest new podcast around, wrote about his experience vibe coding with AI assistants and voice recognition tools.
- This was one of my favorite findings of the last week: a collection of software design discussions between the author of one of my favorite books, John Ousterhout, and Uncle Bob. It's long, and I still have to read through the whole thing, but I'm a big fan of how practical and low-level the discussion goes.
- I loved this take by Francesco Gadaleta on why firing programmers for AI will destroy everything. "This is like firing your entire fire department because you installed more smoke detectors."
That’s all for today, friends! Thank you for making it all the way to the end. If you enjoyed the newsletter, it would mean the world to me if you’d share it with your friends and coworkers. (And if you didn't enjoy it, why not share it with an enemy?)
Did someone forward this to you? First of all, tell them how awesome they are, and then consider subscribing to the newsletter to get the next issue right in your inbox.
I read and reply to all of your comments. Feel free to reach out on Twitter, LinkedIn, or reply to this email directly with any feedback or questions.
Have a great week 👋
– Maxi