RSSAmplifier

Blog

Max Chernyak

Max Chernyak's software engineering blog

max.engineerRSS feed ↗20 posts

Latest posts

Don’t Build a General Purpose API (4 Years Later)

In 2021 I wrote an article encouraging people not to build general purpose APIs for their own front-ends. (You should probably read it before reading this one.) It got featured on Hacker News twice, albeit with a worse reception (and more heated discussion) the second time around. My guess is, more front-enders showed up. 😛 Having observed this approach for 6 years, I’ve only grown more confident…

Failover to Human Intelligence

There’s no denying that AI is getting very capable, but one thing keeps bothering me: what happens if something goes wrong? Right now, self-driving cars still require human monitoring and intervention (outside of specially-designated areas). Isn’t this also true of a sufficiently complex system where you might need to intervene quickly in case AI fails to resolve an issue? Worth considering,…

Getting Answers from a Big PDF with RubyLLM

Some API vendors give you an API doc in a giant custom-edited PDF file. In my case it’s >1200 pages, with a “ helpful” table of contents that itself spans about 20 pages. Well, I dislike reading giant PDF docs, love writing Ruby, and there’s an awesome RubyLLM gem , and Gemini supports PDF parsing, so maybe I can just throw together a quick CLI tool that can answer questions for me? Alas, Gemini…

Long Term Refactors

Big (or “ Long Term”) refactors are hard to pull off in a busy company. To succeed, we must: Convince business that it’s worth the delay. Decide what features will have to wait. Produce regular status updates and ETAs. Justify the refactor as we go. Is it the right approach? Keep ourselves from burning out. Allow time for the team to digest and review the huge diff. Fix a bombardment of QA issues.…

4 Reasons to Leave a Code Comment

I originally wrote this list as a part of Writing Maintainable Code is a Communication Skill , then made a tweet . Since then, I had to link this list multiple times. This post makes it easier to link. Reasons An odd business requirement (share the origin story) It took research (summarize with links) Multiple options were considered (justify decision) Question in a code review (answer in a…

Adventures in Ruby-esque type enforcement

In Ruby you can kinda pretend that you have type enforcement at runtime, because Ruby is very flexible. This could be a useful-enough thing to do to organize and formalize the “ guarding” of your data. As a disclaimer, I’m not actually a huge fan of this practice, because I think that if you’re going to enforce types at runtime, you may as well achieve the same result via learning how to write…

Rails — narrative vs model centric approach

I’ve explored DHH ’ s way of writing Rails applications. His introduction of CurrentAttributes and suppressors of callbacks a few years ago made me want to revisit his Youtube Screencasts on Basecamp 3 and try to really appreciate this approach with an open mind. I soon understood our fundamental difference in thinking. DHH approaches application code as an interconnected web of rich models. Each…

Good Engineering is not Premature Optimization

The term “ premature optimization” is often misused. It’s supposed to be about trading simplicity for unnecessary performance gains. Instead, it’s used as a blanket dismissal of anything unfamiliar. That’s both inaccurate, and hostile to good engineering. Throughout my career, I’ve heard every one of these situations referred to as “ premature optimization”. None of them are. It’s not premature…

Ruby Enumerator.new(size)

Every ruby enumerator supports count . It’s a method that will iterate over every item and return their total count. irb> enum = Enumerator.new { |yielder| ( 1 .. 100 ).each do |i| puts "counting item: #{i} " yielder << i end } irb> enum.count counting item: 1 counting item: 2 … counting item: 100 => 100 However, Enumerable also has size . Except, by default it’s just nil . irb> enum.size => nil A…

Writing Maintainable Code is a Communication Skill

Writing maintainable code is easy. Just keep methods and argument lists short, names and comments long, and follow a styleguide. Boom! Done. Unfortunately, as one famous journalist once wrote: “ For every complex problem there is an answer that is clear, simple, and wrong.” — H. L. Mencken It’s not style and shape that makes code hard to maintain. It’s the lack of clarity on how the code works,…

Mindful Code Reviews

Code Reviews are First-Class Citizens Code reviews are an integral part of our daily work as engineers. They help us reduce bugs, share knowledge, collaborate asynchronously, build rapport, feel recognized, and most importantly, keep software maintainable. Diligent code reviews can save the team from insidious architectural mistakes that may hinder all future development. So why do we often treat…

Don’t Build A General Purpose API To Power Your Own Front End

Update 2025-12-11 : There is now a follow up article (4 years later) . TL;DR YAGNI , unless you’re working in a big company with federated front-ends or GraphQL. It’s popular in web dev nowadays to build a backend that serves JSON , and a frontend that renders the app. This is fine. I’m not the biggest fan, but it’s really okay. Except it’s not okay if you think that your backend needs to be…

3 Reasons Not To Implicitly Memoize

The other day I was listening to this Bikeshed podcast episode , where the hosts were discussing when is it a good idea to memoize values using ||= ruby idiom. Since this is a common question even among seasoned developers, I decided to write up my take on it. The short answer is: never . Problem Let’s take a look at this example. We query the database to find the user by id, then use their email…

Don’t use docker to run your app in development

Using docker in development can be very convenient, but running your actual app (you know, the one you’re coding) in docker introduces various headaches. Mounted volumes are slow and error-prone You need hacks and shortcuts to run any console/debug commands in containers Live updates on code changes are unreliable in docker Runtime is slower in docker Dependency updates are slower in docker…

Elasticsearch gems and modules, clearly explained

Non Rails-specific Gem elasticsearch-transport Provides a bare-bones HTTP client that doesn’t have any Elasticsearch-specific api methods, but knows how to discover and connect to multiple servers, rotate connections, and log things. readme: elastic/elasticsearch-ruby/elasticsearch-transport Gem elasticsearch-api Provides a module that adds elasticsearch-specific methods such as search , cluster ,…

6 practices for super smooth Ansible experience

I started porting my setup from Chef to Ansible a few weeks ago. Having had plenty of experience with Chef gave me a pretty good idea of what I wanted to achieve. One of the main advantages I see in Ansible is the ability to drive your server setup via ssh from your own machine. If you don’t have 100s of servers ( update: actually more like tens of thousands, see the comment by mpdehaan ), this…

Linux permissions cheatsheet

chmod [a]bcd bit scope description a sticky:1, setgid:2, setuid:4 (optional, default: 0) b owner x:1/w:2/r:4 - xw:3/xr:5/wr:6/xwr:7 c group x:1/w:2/r:4 - xw:3/xr:5/wr:6/xwr:7 d everyone x:1/w:2/r:4 - xw:3/xr:5/wr:6/xwr:7 Note: only file/dir owner can chmod it Note: scripts need both x and r permissions to execute (that’s because scripts are read into interpreter) (only r is enough if ran via ruby…

CMS Trap

Many years ago there was a Rails app. It started with things. These things were actually blueprints for other things. The other things needed many associated parts, and parts of parts. How many? The blueprints knew. The blueprints absolutely had to have an admin interface, but changing the blueprints would cause a chain reaction on things and parts. Every modification to the things and their…

Tips on Rails 3 load paths

If you add a dir directly under app/ Do nothing. All files in this dir are eager loaded in production and lazy loaded in development by default. If you add a dir under app/something/ (e.g. app/models/concerns/ , app/models/products/ ) Ask: do I want to namespace modules and classes inside my new dir? For example in app/models/products/ you would need to wrap your class in module Products . If the…

Multiple Table Inheritance With ActiveRecord

Imagine writing an online shop with different types of products. Normally all products would have common attributes such as title and price . Some attributes will likely differ. Tee may have size such as S, M, or L, while a Pen could have an ink_color . It’s easy to see that Tee is a Product , and so is Pen . We are looking at an is_a relationship. When I program this type of relationship I…