Hey friends đź‘‹ Today's issue of Frontend at Scale is brought to you by my newfound love for the early hours of the morning.
That's right. I begrudgingly became one of those people who wakes up at 5 in the morning and apparently won't shut up about it, so get ready for an upcoming issue with all the details of my new morning routine. Is it as glamorous as the morning routines of those super good-looking people on YouTube? Sure. Except mine is less about journaling and meditation, and more about caffeine and screaming kids.
Speaking of trends, are you on Bluesky? Most people in my Twitter bubble seem to be giving it another try. I haven't posted there in over a year, but maybe I will soon? Who knows. Follow me @charca.bsky.social and we'll find out together.
This week, we have a short essay on the controversial topic of separation of concerns, a longer article about software migrations, and a bunch of cool resources on every topic from performance to AI-generated code to spooky UIs đź‘»
Let's dive in.
SOFTWARE DESIGN
Separation of Concerns is Great BTW
I can see some of you rolling your eyes right now at the sight of “separation of concerns.” But hold on a second.
I'm not here to tell you that using Tailwind is a poor separation of concerns or that you should keep your HTML, CSS, and JavaScript code in separate files. On the contrary, I actually think those are examples of a good separation of concerns—but more on that in a minute.
Last week, I was deep down a software design rabbit hole for… reasons that I can remember when I stumbled upon a 1974 essay by Edsger Dijkstra titled "On the role of scientific thought."
In his essay, Dijkstra quotes two paragraphs from a letter he had recently written to one of his colleagues. A letter that, today, is considered to be the birthplace of the separation of concerns principle:
“Let me try to explain to you, what to my taste is characteristic for all intelligent thinking. It is, that one is willing to study in depth an aspect of one’s subject matter in isolation for the sake of its own consistency, all the time knowing that one is occupying oneself only with one of the aspects. […] It is what I sometimes have called “the separation of concerns”, which, even if not perfectly possible, is yet the only available technique for effective ordering of one’s thoughts, that I know of. This is what I mean by “focussing one’s attention upon some aspect”: it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect’s point of view, the other is irrelevant. It is being one- and multiple-track minded simultaneously.”
I love the idea of thinking about separation of concerns as a “technique for effective ordering of one’s thoughts.” It almost feels like a productivity tool—a way to focus our attention on one part of the system without concerning ourselves with everything else that might be going on.
If we think about it from an architectural perspective, we can see that the style of our architecture is essentially a way to separate our concerns. Let’s take a simple layered architecture for example:
​
Each one of these layers represents a different logical concern. By keeping them separated and relatively independent from each other, we can focus our attention on one of them without having to think about the others at all times.
In fact, if we follow the dependency rule of this architecture (the direction of the arrows), we'll be able to change any of the layers with the guarantee that it will not impact the layers below it.
We can use this example to talk about the difference between “separation of concerns” and “separation of technology” as well. Can we mix and match different technologies within the same layer? Well, that depends on what your concerns are.
Are you using Vue or Svelte’s single-file components to keep your markup, styles, and scripts in a single file? That’s perfectly fine under this architecture because they all belong to the same architectural concern—the presentation layer.
Do you have a React Server Component that renders a piece of UI, transforms some data, and makes a MySQL query? Well, that’s actually crossing three architectural layers, so it’s probably a good idea to split the functionality a little bit.
By separating concerns, I’m not talking about putting barriers between the different layers, though. After all, they all depend on each other to some degree, and the easier and quicker we can move across them, the better.
I recently started experimenting with tRPC at work, and I’ve been blown away by how quickly I can move across layers of the stack compared to our traditional SPA + PHP setup. Cmd + click on a client-side React component and I’m now on the server-side controller. Another cmd + click and I’m in the function that makes the DB query. Moving across the codebase like this makes me feel like Freddy Mercury in Don’t Stop Me Now—traveling at the speed of light and having a good time (having a good time 🎵)
But even though I’m moving fast, the concerns I care about are still separated. I’m not tweaking the border-radius of my buttons in the same file I have my validation logic, and I’m not doing business calculations data alongside my ORM calls. It’s easier to move across layers, but the layers still exist.
Of course, your application (and architecture) will have different concerns based on the things you and your team care about.
Maybe you don’t care about keeping presentation and business logic separated, but you care about keeping your different domain objects as independent as possible. Or maybe you care about separating entities and use cases, so you might choose to model your layers based on Clean Architecture instead.
Whatever they are, the concerns you care about should be separated. Otherwise, you’ll end up with an architecture that doesn’t let you focus on a single aspect of your system and order your own thoughts. You’ll have to care about everything to care about anything, and I don’t mean to speak on behalf of any legendary computer scientist here, but I’m pretty sure Dijkstra would find that… well, concerning.
SOFTWARE MIGRATIONS
Out With the Old: 3 Steps for a Successful Software Migration Plan
Last week, I had the pleasure of writing an article for Jordan Cutler's excellent High Growth Engineer newsletter. Jordan's newsletter is one of my favorite resources for career development essays, so I was honored to contribute a piece of my own. My article isn't exactly about career development, but it's about a topic that is dear and close to my heart: migrations.
Software migrations are among the most rewarding projects I've ever worked on; even more so than projects that I've started from scratch. But they're also quite tricky, and there's a funny thing they do almost without fail: they take a lot longer than you originally thought.
If there's one lesson I've learned from working on migrations of all shapes and sizes over the past 15 years, it's that the clarity of your migration plan has a massive impact on your chances of success. So in my article, I share what I consider to be the three fundamental steps for crafting a clear and robust migration plan, along with a template that you can use for planning your next migration.
I had a ton of fun collaborating with Jordan on this one. I hope you check it out!
​
Read on High Growth Engineer |
ARCHITECTURE SNACKS
Links Worth Checking Out
- Jenna Zeigen gave a wonderful talk at LeadDev NY earlier this year called Several components are rendering. She currently works at Notion, but until very recently, Jenna was a Senior Staff Engineer at Slack leading a number of rendering performance optimizations on the app's client—making the app faster so that we can share memes with our coworkers as quickly as possible. I learned a lot of tips in this talk, from how her small team "scaled themselves" by building and sharing performance resources, to how they evaluated tradeoffs when considering a re-architecture. Highly recommended.
- I'm sure you've heard about headless UI components before, but what about boneless, skinless, and lifeless UI? Adam Argyle wrote a great article with everything you need to know about these spooky and emergent UI abstractions.
- Fernando Cardenas wrote about the subtle but very important difference between a layer of abstraction and a layer of indirection. I really enjoyed this short read. To me, the difference boils down to how top-of-mind implementation details are: a good abstraction allows us to ignore them completely; with a bad one, we have no option but to be aware of them.
- Want to learn more about layered architectures? This chapter from Mark Richard's Software Architecture Patterns is a great explainer.
- Rudis Muiznieks thinks using AI-generated code will make us bad programmers... unless we care about self-improvement and taking pride in our work. That stings, I'm not gonna lie. But also, I can definitely see his point.
- On the other hand, Simon Willison thinks that using AI to write code for us is an absolute game-changer, and he proves it by sharing a list of the 14 mini-apps he built using Cloud Artifacts (with the prompts he used to build them) in the span of a week.
- My teammate Nickolas introduced me to Civet, a superset of TypeScript (so, a super-superset of JavaScript?) designed to "do more with less." It reminds me a lot of Python and CoffeeScript but with a much cuter logo and out-of-the-box JSX support.
- Chris Coyier wrote a great tutorial on how to create a staggering effect using one of the coolest new features of the web platform: view transitions.
- I really enjoyed this list of 8 Practices of Reliable Software Design by kqr. "Idea to Production Quickly" is something I've been trying to embrace in my own work lately, so you might see me writing something about it soon :)
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