Programming Style
Congratulations, you’ve found a secret level!
This is a super work-in-progress page which collects various rules-of-thumb I use. The primary goal so far is to collect the rules for myself, that’s why I don’t link to this page from anywhere yet.
General
Naming
Prefer full names except for extremely common cases (ctx
for context), or equal-length pairs
(next/prev
). Use consistent names. Naming variables after types (let thing: Thing
) is a way
to achieve global consistency with little coordination.
Build a vocabulary of standard names and re-use it:
ctx
-
“context” of an operation. Typically holds something mutable. Read-only context is named
params
. params
-
A bag of named arguments. Unlike
config
, might hold not only pod types. config
-
Generally user-specified POD parameters.
sink
-
“output” of an internal iterator, typically
sink: &mut FnMut(T)
orsink: &mut Vec<T>
. lhs
,rhs
-
operands of a binary operator.
fuel
-
Recursion and infinite loop guards
result
-
A “return” variable.
line_index
,line_number
-
Index is unambiguously zero-based. By convention, number is one-based.
Equisized pairs;
- add/sub, mul/div
- lhs/rhs
- s/e
- next/prev
- source/target
- src/dst
- index/count
- insert/remove
- beg/end
- fresh/stale
Explicit Data Tables
Remove code duplication by extracting commonalities into tabular data
Bulk IO
Avoid opening file descriptors in favor of bulk operations. To write data to a file, you need to
follow a lifecycle: open file descriptor, issue write syscalls, close file descriptor. Lifecycle
handling requires complicated type-system machinery and is bettre avoided. Usually, standard library
provides something like std::fs::read_to_string
which encapsulates lifecycle management.
Rust
No Self Types
Write types out explicitly, avoid Self
alias if possible:
Rationale: reducing cognitive load, optimizing for the reader.
Resolving Self
is a small mental effort, it can be avoided.
Prefer new Over default
Use new
over default
to construct instances.
Rationale: new is too ingrained.
Blank Line Between Declarations
Leave blank line between top-level declarations:
Rationale: consistency. Omitting blank line leads to somewhat terser code, but is very hard to do consistently.
Derive Order
Use the following order of derives:
Rationale: consistency. Debug comes last because it is the most often added item.o