Skip to content

Commit 3fdcf6c

Browse files
committed
New note
1 parent 6500c9c commit 3fdcf6c

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

Diff for: src/notes/2025-01-24-15-18-18.md

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
date: '2025-01-24T15:18:18+02:00'
3+
location: Cape Town, South Africa
4+
timezone: Africa/Johannesburg
5+
title: Code greppability
6+
tags:
7+
- dev
8+
---
9+
10+
**Code greppability** is such an underrated code metric in how we judge and work with a code base.
11+
12+
At work, we try to be very diligent in how we name
13+
14+
- database columns,
15+
- file names,
16+
- functions,
17+
- one-off variables.
18+
19+
We pick a _noun_ for a new feature and stick with it throughout the "vertical" that forms **from frontend to database**. This makes it really easy to trace a feature's flow through the various layers. Same goes with the _verbs_ that form actions on the feature noun: those should be consistent too.
20+
21+
I use the _greppability_ to my advantage in two cases:
22+
23+
1. **Project wide search.** I hit <kbd>cmd+shift+f</kbd> and search for my keyword.
24+
2. **File search.** I hit <kbd>cmd+f</kbd> and spam `next` to step through all the call sites the feature touches in the local file. This gives me an overview quite quickly.
25+
26+
Some examples:
27+
28+
## Always do named exports
29+
30+
In Javascript:
31+
32+
```ts
33+
// ❌ DON'T
34+
export const myFunction = () => {};
35+
36+
// This has now been renamed 😰
37+
import { myFunction as someOtherName } from './module';
38+
```
39+
40+
Although Language Servers will pick up this on-the-fly alias, we don't like it.
41+
42+
Same goes with default exports:
43+
44+
```ts
45+
// ❌ DON'T
46+
export default function myFunction() {}
47+
48+
// This has now been renamed 😰
49+
import someOtherName from './module';
50+
```
51+
52+
## Be specific
53+
54+
Avoid terms like `utils` and `process` in a feature's various functions. Name it with what they do, specifically.
55+
56+
## Context
57+
58+
Okay, inside of a scoped function (see below), we allow ourselves to be looser with the one-off variable names:
59+
60+
```ts
61+
export const myFeatureCreate = async () => {
62+
// ❌ DON'T
63+
const myFeatureExisting = await db.find(...);
64+
// ✅ DO
65+
const existing = await db.find(...);
66+
};
67+
```
68+
69+
However, if we use some _other_ feature/model, we are strict with naming:
70+
71+
```ts
72+
export const myFeatureCreate = async () => {
73+
// ❌ DON'T
74+
const docs = await db.find(...);
75+
// ✅ DO
76+
const otherFeatureDocs = await db.find(...);
77+
};
78+
```
79+
80+
## Problem: Scoping
81+
82+
"Okay, so you don't use the ES Module system to the fullest. How do you cope with name collisions?".
83+
84+
We do it the old fashioned way of… 🥁 _prefixing_! Such as:
85+
86+
```ts
87+
// Some model file
88+
export const myFeatureCreate = () => {};
89+
90+
export const myFeatureUpdate = () => {};
91+
```
92+
93+
If you start typing `myFeature…`, your editor's <abbr title="Language Server Protocol">LSP</abbr> integration will probably autocomplete with a list of the available functions above. Simplicity!

0 commit comments

Comments
 (0)