Approach · shipping · in production
KISS, YAGNI, Rule of Three
I apply KISS, YAGNI, and the Rule of Three to ensure I ship the simplest viable solution today, avoiding premature complexity and abstracting only when a pattern explicitly repeats.
The core of my development process adheres to KISS, YAGNI, and the Rule of Three, guiding me to build only what is needed right now and deferring generalized solutions until patterns are undeniable.
What it is
KISS, or "Keep It Simple, Stupid," is a design principle that prioritizes simplicity. I apply this to code, architecture, and even business models. If there's a simpler way to achieve the goal, that's the path I take. YAGNI, "You Ain't Gonna Need It," is the practice of deferring any functionality or infrastructure until it's explicitly required by a user or system. This directly combats premature optimization and speculative building. The Rule of Three dictates that I only refactor and abstract code after I've written similar code three times. The first two instances are often copy-paste; the third is when a true pattern emerges, justifying the investment in generalization.
Why I do it this way
As a solo operator running Total Ventures with AI as my team, resources are always finite. Every line of code, every abstraction, carries a maintenance cost. Premature optimization or abstraction slows down shipping and introduces complexity that might never be needed. I learned the hard way that building for an imagined future often means building the wrong thing. My focus is on getting functional products into users' hands today, gathering real feedback, and iterating. This approach forces me to solve the immediate problem, not an abstract future one. It also aligns directly with a profit-first allocation mindset, ensuring that development effort is spent on validated needs that contribute to the bottom line, rather than speculative engineering.
How it works in practice
When starting a new feature for Total Formula 1 or Pregnancy Power Hour, I write the most direct, often duplicated, code to get it working. If I need a specific API call, I write it directly where it's needed, even if it means duplicating a small helper function. My AI agents, powered by Claude Code and Gemini, are instructed to follow these principles. When I prompt them for a feature, the instructions include prioritizing direct implementation over complex patterns. They generate the simplest working solution first.
Refactoring happens only when I see the exact same logic appear for a third time, across different parts of a codebase or even different micro-services. For example, a specific data transformation before sending to Resend or Stripe might start as inline logic in two separate Vercel functions before being extracted into a shared utility on the third instance. For Inky, I initially considered a complex user permission system. YAGNI dictated I ship with a single admin role. When the need for differentiated user access became clear from actual customer feedback, then I built it. This approach extends to infrastructure: I start with the simplest Firebase functions or Vercel deployments. Only when performance or cost dictates, do I explore more complex setups. It also influences how I think about multiple revenue streams, one back office – each stream starts as a simple integration, then shared components are identified and built out.
Where this breaks down
This approach can lead to initial code duplication, which can be tedious if the "third time" never comes or comes much later. If not managed, the "Rule of Three" can be an excuse for excessive duplication, making the codebase harder to navigate for human and agent alike. It requires discipline to not abstract prematurely, which can feel counter-intuitive to experienced engineers who are used to designing for scale upfront. It relies on effective audits as crons to identify patterns that are ready for extraction; otherwise, they might be missed. The "Rule of Three" can also be subjective – what constitutes "similar enough" code? My agents often flag potential refactors, but the final decision is mine.
FAQs
- Doesn't this lead to a lot of duplicated code?
- Initially, yes. The point is to validate the pattern's necessity before investing in abstraction. Duplication is cheaper than incorrect abstraction until the pattern is proven. I accept this as a necessary trade-off for speed and validated design.
- How do you avoid technical debt with this approach?
- I view initial duplication as 'pre-debt' that I'm willing to incur to learn. True technical debt comes from unmanaged complexity. By abstracting only proven patterns, I'm building on solid ground, reducing future refactor risk.
- How do your AI agents handle this?
- I instruct them to prioritize direct implementation. They'll often generate duplicate code if it's the simplest path. I then use them to identify refactoring opportunities when the Rule of Three is met, acting as a code review layer.
I run this and four other brands. Want to see the operator playbook in detail?
Get the Builder's Playbook →