What this codebase asks of a newcomer

Free preview 4 min to read

Mentoring is specific to a codebase before it is anything else, so start with this one. What does someone joining have to know before they can write a line that would be merged?

The numbers

$ git log --all --oneline | wc -l
3858
$ git log --all --oneline --author=dependabot | wc -l
24

One human author (under three spellings of the same name) and 3,834 commits; the other 24 are Dependabot's. That is the situation this lesson is about. Not a large team with an onboarding program, but the far more common case where the conventions are real, consistent and entirely in one person's head until someone writes them down.

Someone did. MEMORY.md is 659 lines and opens:

This file is the authoritative reference for every pattern, convention, and architectural decision in this codebase. Read this before touching any code.

That document is the single most valuable mentoring artifact in this repository. And lesson 5 is about what it does well and where it has quietly gone wrong.

What is not derivable from the code

Onboarding difficulty is not measured in files. It is measured in decisions a newcomer cannot derive by reading. And this codebase has a lot of them because it is opinionated in ways that are correct and non-obvious.

Five a newcomer would break on the first day:

Domain namespacing, with no exceptions.

"Every piece of code belongs to a named domain. There are no exceptions: do not add controllers, models, services, or helpers at the root level."

A newcomer generates rails g controller Profiles, gets app/controllers/profiles_controller.rb, and has departed from a rule that nothing in the code enforces.

Uniqueness errors say "is not available." Never "has already been taken". The reason is user enumeration: the default message tells an attacker that an email is registered. Nothing in the validation explains this, and "fixing" it back to the Rails default looks like a cleanup.

Queries return Data objects, never Pagy objects.

"Queries must be infrastructure-agnostic. Receive page and per_page, use .limit/.offset, and return records + total_count."

Returning a Pagy is what the gem's README shows, and it is wrong here.

form_with always takes an explicit url:. Model array inference breaks with namespaced models, and the failure is a confusing routing error rather than a clear one.

Stimulus identifiers use the ui-- prefix matching the directory. A controller in controllers/ui/navbar_controller.js is ui--navbar, and a newcomer who names it navbar gets silence rather than an error.

flowchart TB
  C["reading the code"] --> A["what it does"]
  C --> B["what the conventions are"]
  B -.->|"not derivable"| D["no root-level controllers"]
  B -.->|"not derivable"| E["'is not available' prevents enumeration"]
  B -.->|"not derivable"| F["queries return Data, never Pagy"]
  B -.->|"not derivable"| G["form_with needs explicit url:"]
  B -.->|"not derivable"| H["ui-- prefix on Stimulus identifiers"]

The pattern in all five

Look at what those five have in common. Each has a reason, the reason is not visible at the site of the rule, and following the general Rails convention produces the wrong result.

That combination is precisely what makes a codebase hard to join, and it is not a flaw. Every one of those decisions is defensible, and three of them are protecting something specific. The cost is that a newcomer cannot arrive at any of them by being competent. And will produce a pull request that is wrong in ways that look like carelessness.

This is the single most important thing to understand before mentoring anyone. Their first pull request will violate conventions they had no way to know about, and how you respond to that decides most of what happens next.

What it means for a first task

A good first task in this repository is one where the domain is already chosen, the pattern already exists nearby. And the conventions are visible in the neighboring file. Adding a query object next to fifty-eight others. Adding a spec to a file that already has six.

A bad first task is one that crosses domains, creates a new namespace, or has no local example, because the newcomer's only source for the conventions is a 659-line document they have not read yet. And nobody reads 659 lines before their first commit.

Key takeaways

  • 3,834 commits by one human author: the conventions are consistent, real, and were in one head until they were written down.
  • MEMORY.md is 659 lines and declares itself the authoritative reference.
  • Onboarding difficulty is measured in decisions a newcomer cannot derive by reading the code.
  • Five here have a reason that is invisible at the site of the rule, where the general Rails convention gives the wrong answer.
  • A good first task has the domain chosen and a working example in the neighboring file.
Lesson 1 of 7 · free

Keep going with lesson 2

Pairing modes

Driver and navigator, ping-pong, strong-style and silent observation, with when to use each and common failure modes.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...