dsfx/docs/tigerstyle.md

128 lines
6.2 KiB
Markdown
Raw Normal View History

2025-03-09 16:26:25 -04:00
# TigerStyle
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Adopted from the original [Tiger Style](https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/TIGER_STYLE.md)
for **zig**, created by tigerbeetle.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
## The Essence of Our Go Style
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
> “There are three things extremely hard: steel, a diamond, and to know one's self.” — Benjamin Franklin
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Our Go style is not merely about formatting code—its our design philosophy. It blends engineering excellence with artful clarity to ensure that our systems are safe, high-performance, and enjoyable to develop and maintain.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## Why Have Style?
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
In our view, design is as much about how the system works as what it looks like. Our style makes each decision explicit, ensuring that safety, performance, and developer experience remain paramount.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- **Safety** first,
- **Performance** next,
- and then **developer experience**.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Good style does more than improve readability; it enforces the design decisions that prevent technical debt from creeping in.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## On Simplicity, Elegance, and Technical Debt
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- **Simplicity** is our ultimate goal—but it is never a free pass. Achieving simplicity is the result of thoughtful design and disciplined iteration.
- A “zero technical debt” policy applies: we design and implement things right the first time. This saves each of us from the cost of firefighting production issues later.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## Safety
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Even in Go, safety is nonnegotiable. We frequently embed explicit checks and assertions to ensure our code behaves as expected. Consider this sample assertion helper:
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
```go
// Assert panics with a message if the condition is not met.
// Not idiomatic Go, but used here to enforce critical invariants.
func Assert(condition bool, msg string) {
if !condition {
panic(fmt.Sprintf("Assertion failed: %s", msg))
}
}
```
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Key safety guidelines:
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- Use **simple, explicit control flow** (avoid unnecessary recursion and hidden complex abstractions).
- **Limit loops and queues**: every loop should have an explicit upper bound to avoid infinite cycles.
- Favor fixed-size types (e.g., use `uint32` or `int32` where appropriate) instead of architecture-dependent sizes.
- Use assertions liberally—both to check expected states _before_ and _after_ important operations. Aim for at least two assertions per function.
- All memory usage should be planned up-front. Although Go provides garbage collection, design your modules with a fixed resource strategy in mind for predictability.
- Keep function bodies short. In Go, we suggest striving for functions to be easily digestible (roughly keeping functions around 70 lines or less) by breaking out helper functions where it makes sense.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## Performance
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Performance starts in the design phase—even before profiling code.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- **Back-of-the-envelope sketches:** Before implementation, roughly gauge resource (network, disk, memory, CPU) usage.
- Identify the slowest resource (network → disk → memory → CPU) and optimize that first.
- Use batching to reduce overhead and context switching. For example, aggregate database writes rather than doing them one at a time.
- Separate the control plane from the data plane. For “hot loops” or performancecritical code, create small, stateless helper functions accepting primitive types. This helps both the compiler and human reviewers spot redundant computations.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
---
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
## Developer Experience
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Our goal is to make our code easy to read, maintain, and extend.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
### Naming Conventions
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- **Go idioms:** For exported functions, use `CamelCase` (e.g., `ReadSector`), and for local functions and variables, use `camelCase`.
- Avoid abbreviations unless they are well-known acronyms (for example, use `HTTPStatus` rather than `httpStatus`).
- Include units and qualifiers in variable names at the end, so names like `latencyMsMax` (where “Ms” stands for milliseconds) are both clear and neatly aligned with related variables.
- When a function delegates work to helpers, consider prefixing the helper name with the parent function (e.g., `readSectorCallback`) to provide context.
- Place important constructs (like `main`) or critical types near the top of files for clarity.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
### Comments and Commit Messages
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- Write clear and complete comments. Comments should be full sentences with proper punctuation.
- Document why a decision was made, not just what the code does. Commit messages should convey context and rationale.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
---
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
## Handling Errors
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Errors must always be handled explicitly:
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- In Go, this means checking returned errors immediately. Do not ignore them.
- Test error paths thoroughly, including non-fatal errors, to mitigate the risk of catastrophic failures found in distributed systems.
- Use assertions where appropriate to ensure that numbers or states remain within expected ranges.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## Avoiding Off-By-One Errors
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
Misunderstandings between zero-based indexes and one-based counts can be problematic:
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- Clearly differentiate between an index, a count, and a size. For example, increment an index when calculating a count.
- Use helper functions for mathematical operations—consider naming them in a way that demonstrates intent (like `divExact`, `divFloor`, or `divCeil`).
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
---
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
## Formatting and Dependencies
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- Run `go fmt` on all code. We also recommend using linters (such as `golangci-lint`) for consistency.
- Set a limit on line lengths (suggested maximum of 100 columns) to ensure clear visibility of code segments.
- Aim for a “zero dependencies” mindset where possible. Rely on Gos standard library to reduce external risk and simplify builds.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## Tooling
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
- Choose tools that streamline development. When writing scripts or utilities, consider writing them in Go.
- A standardized toolchain reduces personal variations and ensures consistency across the team.
2025-03-08 15:07:27 -05:00
---
2025-03-09 16:26:25 -04:00
## Final Thoughts
In our adapted TigerStyle for Go, every detail—from strict assertions to deliberate naming and error handling—is designed to create robust, clear, and high-performance software. Remember: even though some of these practices (like assertions) arent common in Go, we include them as an essential part of our commitment to safety and clarity.
2025-03-08 15:07:27 -05:00
2025-03-09 16:26:25 -04:00
> "You dont really suppose, do you, that all your adventures and escapes were managed by mere luck?"
> Keep iterating, keep improving, and let your code be both a precise tool and a piece of art.