RSSAmplifier

Blog

Shai Yallin

Writing on software engineering, testing, architecture, and engineering culture.

shaiyallin.comRSS feed ↗41 posts

Latest posts

Change Is Cheap. Until It Isn't.

I spent two decades advocating ATDD from the first line of code, because that was how you kept the cost of change low. AI agents changed the economics: I now start with days of violent prototyping, and only add e2e guardrails once I know what behavior is worth protecting.

Hiring in the Age of AI Agents

A hiring process exists to approximate what it's like to work with a person. AI agents changed how candidates write code, so I now let them use agents in pair-programming interviews; the signals I read stayed almost the same, and the project and system design questions survived untouched.

The Era Of Bespoke Software?

LLMs collapse the cost of writing single-use software, making bespoke viable where reuse used to win by default. Here's the framework for when bespoke beats reuse, when reuse still wins, and the real question underneath both.

Rebuilding this site off Wix, by the machine that did it

A guest post from Claude Code: the brief Shai gave, the places one of us overruled the other, how the Wix-to-Astro migration actually went, and what shipped.

Homebridging the alarm

How I reverse-engineered an Israeli alarm panel's wire protocol and shipped a Homebridge plugin, mostly written by an AI pair.

Codin' On A Prayer

AI Agents are just like human contractors only faster; to make them work at scale and in a stable manner, you need to use deterministic, executable checks like tests, compilers, linters, etc - otherwise you're doing no better than prayer.

Case Study: Three Years at HoneyBook, From “Soft Consensus” to a Coherent Engineering Culture

There’s a particular kind of joy in seeing seeds you planted years ago take root. Watching an engineering organization grow over the course of several years, and seeing ideas we introduced become part of its everyday rhythm, have been some of the most gratifying parts of my work. This is the story of how a small engagement with HoneyBook evolved into a multi-year partnership that shaped everything…

Integrative UI/Backend Acceptance Tests with NestJS and React

In the final post of this series, we’ll cover how applications where both the frontend and the backend are built with Javascript can benefit from a novel approach to testing: in-process, JSDOM-based acceptance tests that drive the UI, but incorporate a backend that uses memory fakes for speed and determinism. The benefits are substantial: with this type of tests, we do not need to mock or fake the…

Acceptance-Testing NestJS Microservices

Acceptance Testing multiple NestJS Microservices by running them a single process communicating via a memory fake.

Using Contract Tests for reliable memory fakes

How to make sure that memory-based fakes really behave like the production implementations they replace

Fast and Furious Acceptance Tests for NestJS applications

Writing memory-based black-box acceptance tests for NestJS apps, testing features rather than implementation details

Chaos-Engineering Your Culture: Building a Self-Healing Organization

In software, we design for failure. The same is true for organizations. Embrace replaceability to build a self-healing company.

Software Dermatitis

Overzealous elimination of duplication can cause code to become so DRY it's actually brittle: like dry skin, it cracks under pressure.

Your Code as a Lava Lamp

In the fast-paced world of software development, change is the only constant. User needs evolve, new technologies emerge, and market conditions shift. In this environment, rigid, inflexible code is a liability. It's like a brittle sculpture that shatters under pressure. To build software that thrives in the face of change, we need to embrace a different mindset. We need to think of code not as a…

You Don't Need Kubernetes (Yet)

K8s solves a problem that your new startup probably doesn't face. Invest your resources in finding product-market fit and scale up later.

The Hidden Benefits of Working on a Rotten Codebase

Working on bad code makes you better at writing good code

Shift-Left and The Pitfalls of Overplanning

PMs make overly detailed plans without dev feedback, resulting in waste. Shorten cycle time by planning briefly then develop and iterate.

Unit Tests Considered Harmful

Unit tests couple us to implementation detail, restrict refactoring and don't assert that features work. Prefer bigger-scoped tests.

Not The Design We Want, The Design We Deserve

Upfront design often results in over-engineering and a mismatch between design and reality; embrace Emergent Design to be truly flexible

Of Rigid Microservices and Flexible Monoliths

Microservices incur significant overheads in costs of change, runtime and complexity. Start with a monolith and break it down when needed.

SomeEstimates

Estimates cost a lot and deliver little. To progress effectively, Focus on Trust, Information Flow, Mentorship and Cooperation.

Holistic Software Development

How Scrumfall creates a culture of Waste, Fear, Irrationality and Loss and how Holistic Software Development keeps us flexible and adaptable

Agile Isn't Dead, It Just Smells Funny

How the word 'Agile' lost its meaning, and how to remain flexible and cultivate a culture of sustainable, holistic software development.

Case Study: Testing the Codium.AI VS Code Extension

How I wrote tests for a VS Code extension that relies on a React.js WebView as its UI, using Playwright, Mocha and some HTTP hacking

Fake, Don't Mock

Fakes are complete implementations of an API used to replace IO-bound adapters with memory-bound doubles to facilitate Acceptance Testing

Learning Tests: better than benzos

Learning Tests are an easy and useful methodology for integration with new and unknown APIs, reducing stress and improving feedback times.

Flutter: a love story

How I learned Flutter to create an iOS app for usage during concerts with my band, using TDD and Acceptance Testing.

Chronomatic: my side-project story

How I used React with TypeScript and Firebase to build my own client management system, using TDD and Acceptance Testing.

Beautiful Object Builders in TypeScript

Fixture test data create stale and outdated data, and make tests unreliable. Object Builders are a better way, here's how to use them.

dotenv considered harmful

Relying on .env files couples your codebase to env vars, making your software harder to change. Here's how to decouple them.

The Anatomy Of A Rotten Codebase

Code rots because we build too many features, too fast. Emergent Design is an effective way to fight code rot and make change easier.

Case Study: Versatile CraneView Refactoring

How I helped Versatile remove fear of change in a key subsystem by introducing TDD and refactoring to Hexagonal Architecture.

The woes of a Mac migration

Update, January 2022:Shortly after publishing this post the Mac failed to connect to the display. Through a friend who works at Apple I got to a person who maintains the Thunderbolt firmware on Macbooks, and apparently the problem was caused by a combination of two issues; the first issue being a physical breakage in the Thunderbolt cable affecting only half of the wires inside, and the second…

Your Software as a Kitchen

When there are too many dirty pots and plates in the sink, it's impossible to clean them. It's the same with software and technical debt.

Tzvika's Revenge's Revenge

Recovering a Pascal game I wrote at age 16, lost to a dead hard drive in the late 90s and resurrected from an ARJ archive twenty-some years later.

Litany Against Fear of Change

Written 56 years ago, the Litany Against Fear plays an important part in the novel Dune, allowing the protagonist to overcome his crippling feelings and go through difficult ordeals. Recently it dawned on me that it could be just as effective - and just as true - when dealing with fear of change in software systems. Let's go over the litany line by line and consider its meaning and implications.I…

Permanent Prototypes

Prototypes are a lie; when it's good enough for production, it *becomes* production. Here's how to make them easily maintainable.

On Remote Pair-Programming

For the past few months I've been working with a startup building a mobile app using #ReactNative. I last used #React back in 2016, and my most recent mobile development was in the joyful J2ME days of 2007, so I was a bit hesitant to dive into this codebase. Usually, I find my way around new codebases and technologies by #pairprogramming with an experienced colleague, but with COVID-19 and the…

It's all about the maintenance, dummy

We spend most of our time maintaining software. Writing features we might need in the future is not only a waste of time, it makes your software harder to maintain.

Inside The Inner Hexagon: Component Tests

This blog post was originally published in the Orbs Engineering blog in 2018.My previous post described how the Go reference implementation of the Orbs Network blockchain protocol used Hexagonal Architecture to facilitate upfront design, while allowing the inner design of components inside the system to emerge via TDD. We left off with a promise to discuss Component Tests, as well as elaborating…

Big Design Up-Front or Emergent Design? Hexagonal Architecture Gives Us Both

When we started coding the Orbs reference implementation in the Go programming language, we had several guidelines in mind: The code must be written outside-in using TDD The code must have bounded contexts, expressed as interfaces generated f