December 19, 2022
Code I like (V): Active Record, nice and blended
This article was originally published in the 37signals dev blog. Persisting objects in relational databases is an intricate problem. Two decades ago, it looked like the ultimate orthogonal problem to solve: abstract persistence out so that programmers don’t have to care about it. Many years later, we can affirm that… it’s not that simp...
Read more
Read more
December 13, 2022
Compared to what?
This article was originally published in the 37signals dev blog. I loved this article by Kent Beck on cohesion. At some point, when discussing how cohesion and coupling are opposing forces, it says: “Wait!? Isn’t coupling bad? But cohesion is good? But cohesion is coupling of subelements? Isn’t that bad? And good? This is where I got s...
Read more
Read more
November 27, 2022
My curse with plain code editors
I think the first IDE I used was Borland Delphi in 1999. I remember being marveled by its code insight features, where the editor would suggest what properties and methods were available for a given symbol. I remember being puzzled about the programming sorcery powering that — pretty much the same feeling I have today when I play a mod...
Read more
Read more
November 15, 2022
What defamation looks like
Last Sunday a friend shared with me this Twitter thread by Kasper Timm Hansen: He confirmed later in the thread he was referring to me as the author of the Vanilla Rails article I recently published in the 37signals dev blog. Kasper starts by presenting a history of friction during PR reviews between us, where he was careful with words...
Read more
Read more
November 8, 2022
Code I like (IV): Vanilla Rails is Plenty
This article was originally published in the new 37signals dev blog. Read it there. I have often heard this: vanilla Rails can only get you so far. At some point, apps become unmaintainable, and you need a different approach that brings the missing pieces, because Rails encourages a poor separation of concerns at the architectural leve...
Read more
Read more
October 15, 2022
Online discussions, the good parts
Some recent positive experiences made me think about the source of my distaste for online discussions. The blame is on me: I assimilated online to social media or online comments in the wild. I can’t imagine a worse discussion platform than Twitter. Any meaningful discussion requires nuance, which Twitter eliminates by design. Making p...
Read more
Read more
October 10, 2022
Code I like (III): Good concerns
Rails concerns have received much criticism over the years. Are they the solution to all the problems or something to avoid at all costs? I think a problem with concerns is that you can use them however you want, so no surprise you can shoot yourself in the foot when doing it. After all, concerns are just Ruby mixins with some syntax s...
Read more
Read more
September 24, 2022
Aging programmer
Back in college, they told me that I would start my career writing code, but eventually, I would move to a position where I would ask others to code my designs. To celebrate that this turned out to be completely false, here are some assorted reflections as a 40-year-old programmer that looks back: • Compared to my younger versions, I f...
Read more
Read more
September 18, 2022
Code I like (II): Fractal journeys
Fractal is about similar patterns recurring at progressively smaller scales. To me, good code is a fractal: you observe the same qualities repeated at different levels of abstraction. This is not surprising. Good code is the one that is easy to understand, and the best mechanism we have to deal with complexity is building abstractions....
Read more
Read more
August 6, 2022
Utility-first CSS
Recently I've found myself with the need to use a CSS toolkit a couple of times. The motivation was building from scratch some internal admin tools. I had heard great things about Tailwind, and David had bootstrapped a Rails integration for it, so we decided to go with it for building a new version of our internal Basecamp admin panel....
Read more
Read more
June 13, 2022
Code I like (I): Domain-driven boldness
One of the first things I did when I started working at 37signals almost three years ago was cloning the git repo for Basecamp. I poked around and ended up at this method: module Person::Tombstonable ... def decease case when deceasable? erect_tombstone remove_administratorships remove_accesses_later self when deceased? nil else raise ...
Read more
Read more
June 5, 2022
What do we want people to feel?
Since I started using HEY World last year, I have written 28 posts. Those are more than what I wrote in my six previous years of blogging. Publishing an article in HEY World is as easy as sending an email, which I am sure is a life-changing feature for many people, but not for me. I am a programmer nerd, and publishing on my personal s...
Read more
Read more
May 26, 2022
Enterprisey expectations
As a customer, I can't think of something I value more than how a company handles the problems I have with them. I have recently been evaluating Datadog for Basecamp. It's a fantastic product, and we are in the final testing stage. We recently tried the new version of its official Ruby/Rails gem, finding a severe memory leak problem. I...
Read more
Read more
May 16, 2022
Priceless adversity
It's hard to appreciate the good without having experienced the bad. My first job made me professionally very unhappy. It lasted a few years, and it deeply impacted me. I swear there hasn't been a week since I quit, almost ten years ago, where I didn't reflect on my good luck compared to my starting point. Don't get me wrong: if I coul...
Read more
Read more
May 14, 2022
Performance in context
When it comes to analyzing code performance, context matters a lot. For example, say we have this code that adds two numbers: a = 1 + 2 And now we need to add a subtraction: a = 1 + 2 a = a - 3 So what's the cost of this change? We can benchmark: require "benchmark/ips" Benchmark.ips do |x| x.report("only add") { a = 1 + 2 } x.report("...
Read more
Read more
May 7, 2022
Rails attributes: an essential API you can probably ignore
A few years ago, Rails 5 introduced an API for declaring Active Record attributes. It lets you define typed attributes at the model level and control via types how to cast values assigned to them. Active Record internally uses this API profusely. Active Record models automatically declare these attributes for you by inferring the types...
Read more
Read more
Ceremony at work is those self-imposed rituals people follow to get things done. Too much, and it becomes a burden. Too little, and it's chaos. Ceremony serves two purposes: assessment and communication. Assessment is about making sure you are working on the right problems at any given moment; communication is about getting everyone on...
Read more
Read more
April 23, 2022
What did you work on today?
Everyone at Basecamp answers this question at least twice per week: "what did you work on today?". We use Basecamp check-ins, of course. It's a simple practice with profound implications and something I would recommend to any company working remotely. These answers are in written form, and anyone in the company can see them and make co...
Read more
Read more
April 4, 2022
Writing for yourself
This question applies to most people, and it certainly applies to me: does it make sense to write without an audience? It does. One of my favorite books is Pragmatic thinking and learning by Andy Hunt. It's a book about how our brains work, which is a subject I find fascinating. A core concept it develops is how our brains operate in t...
Read more
Read more
April 2, 2022
Not a designer
I love design (as in product design). It's a discipline I have tried to educate myself at, and it's what I appreciate the most in any product I use. And yet, I'm terrible at it. I have empirical evidence that it's not my thing. But I can't help having strong opinions on how things should be designed. A contradiction, you see, HELP! I g...
Read more
Read more
March 12, 2022
Changing critical code paths with scientist
I recently worked on improving the inbound email analysis system in HEY. This system analyzes every email that hits HEY to decide whether it should flag it as spam, bounce it, or warn the user about specific problems such as having a forged sender or containing a virus. In its current form, the system was making it difficult to add som...
Read more
Read more
March 6, 2022
Social media evilness
Why are so many people so awful towards other people on Twitter? How can there be this massive gap between how people conduct themselves on Twitter and in real life? I've always found fascinating how our brains work, and I was sure there would be good answers out there. I've read a few books and articles on social media issues lately, ...
Read more
Read more
February 13, 2022
No silver buckets
The suggestion that mixing buckets is the root of all your software quality problems is common in our industry. In Rails, it's a recurring theme from his critics. Augment Ruby core classes with monkey-patching? Wrong! Those buckets are meant to remain separate. Invoke models logic from controllers? Wrong again! Those actions deserve th...
Read more
Read more
Balance is hard. We love extremes: they are simple and effective. Take learning and the Shu-Ha-Ri model. When learning something new, you first look for strict recipes: sharp boundaries that guide you through every step. At some point, you forget about recipes and start acting without thinking much. Those initial boundaries become fuzz...
Read more
Read more
February 5, 2022
My MacOS essentials
Just because the world is short of lists of favorite apps, here is mine: Task Paper for todos I used to have a thing for todo apps. I tried them all and even tried to build my own. I switched to Task Paper years ago and have stuck to it since then. The truth is that my relationship with todos has changed significantly over the years. T...
Read more
Read more
February 2, 2022
Of bugs and giants
In October of last year, we started to receive reports about chats that stopped working in Basecamp. They were all iOS/Safari users. Campfires wouldn’t work, as if there was no internet connection, and the only solution was completely restarting Safari. The bug was elusive and happened very intermittently. We tried several things witho...
Read more
Read more
I quit Twitter for the first time nine years ago. Two years ago, when I started at Basecamp, I felt like giving it a new try. Long story short: it didn’t work. I had identified noise as my biggest problem with Twitter back in the day. The signal was very low. I naively thought I could improve that by carefully selecting who to follow a...
Read more
Read more
December 22, 2021
A system to encrypt data in bulk for Rails
We just released mass_encryption, a library to encrypt large sets of data using Active Record Encryption. If you have been following along, Rails 7 was recently released and, among many goodies, it supports at-work encryption with Active Record. This new gem addresses a problem many apps will face: perform the initial encryption in exi...
Read more
Read more
November 28, 2021
Don't block yourself: a remote-worker super-power
When working remotely, this is a great habit: make decisions and communicate them, but try to avoid getting blocked waiting on others. Imagine this typical example: you are not sure about how to do something. Your first idea might be to jump into a chat and ask someone for help. I won’t say I never ever do this, but it’s not a great ap...
Read more
Read more
November 20, 2021
MacBook Pro M1
Two weeks ago, I got a MacBook Pro 16-inch. I got the base model (M1 pro, 16GB). My previous machine was a loaded-up MBP 15-inch from 2019. Bottom line: it's been the most noticeable performance jump I've experienced since SSD disks. Performance The improvement is ridiculous. My previous MBP felt slow, and it often struggled to dispatc...
Read more
Read more
See more posts »