Skip to content

Commit 93f2bef

Browse files
committed
update README
1 parent 0380b23 commit 93f2bef

1 file changed

Lines changed: 59 additions & 12 deletions

File tree

README.md

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# gobetter - Go Builder Pattern Generator
22

3-
**gobetter** is a code generator that creates type-safe builder patterns for Go structs, enforcing mandatory fields at compile time through a fluent API similar to named arguments.
3+
**gobetter** is a code generator that creates type-safe builder patterns for Go structs, enforcing
4+
mandatory fields at compile time through a fluent API similar to named arguments.
45

5-
## Features
6+
## Features
67

78
- **Compile-time safety** - Missing mandatory fields cause compilation errors
89
- **IDE-friendly** - Excellent autocomplete support showing only the next required field
@@ -11,12 +12,12 @@
1112
- **Struct tag preservation** - Maintains JSON, validation, and other struct tags
1213
- **Flexible configuration** - Control visibility, optional fields, and generation scope
1314

14-
## 🎬 Demo
15+
**IDE Autocomplete (no plugin needed)** - Only shows the next mandatory field:
1516

16-
**IDE Autocomplete** - Only shows the next mandatory field:
1717
![Autocomplete](autocomplete.png)
1818

1919
**Compile-time Validation** - Missing fields cause compilation errors:
20+
2021
![Missing Field error](error_sample.png)
2122

2223
## The Problem
@@ -28,7 +29,7 @@ type Person struct {
2829
FirstName string
2930
LastName string
3031
Age int
31-
Description string // optional field
32+
Description string
3233
}
3334

3435
// Traditional struct initialization
@@ -40,20 +41,66 @@ person := Person{
4041
}
4142
```
4243

43-
**Problems with traditional approaches:**
44-
- ❌ Easy to forget required fields
45-
- ❌ No compile-time validation
46-
- ❌ Manual constructor functions need constant maintenance
47-
- ❌ Parameter order mistakes (no named parameters in Go)
44+
**Where this breaks down:**
45+
- Missing required fields still compile (zero values sneak in).
46+
- Refactors are risky: adding a required field means hunting every construction site.
47+
- Constructors are order‑sensitive and error‑prone; many code generators don’t emit them at all.
48+
- IDEs can’t guide the next required field.
4849

4950
## The Solution
5051

52+
```go
53+
p := NewPersonBuilder().
54+
FirstName("John").
55+
LastName("Doe").
56+
DOB(time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
57+
Build()
58+
```
59+
5160
**gobetter** generates type-safe builder patterns that:
5261
-**Enforce required fields** at compile time
5362
-**Prevent field order mistakes** through method chaining
5463
-**Auto-update** when you add/remove fields
5564
-**Provide excellent IDE support** with autocomplete
5665

66+
## Why builders instead of struct literals or `New...()` constructors?
67+
68+
### Plain struct literals / direct assignment
69+
70+
- **Silent omissions.** With keyed struct literals, leaving out a field is legal and compiles; the
71+
field is just the zero value. If that field is *logically required*, you won’t find out until
72+
runtime.
73+
- **Refactor pain.** When you add a new required field, you must manually audit every construction
74+
site. Miss one, and you ship a subtle bug. The step-builder makes this a **compile error** until
75+
the new step is provided.
76+
- **No guidance in IDEs.** Autocomplete can’t tell you what’s required next; the step-chain exposes
77+
exactly one valid next method.
78+
79+
### Hand-written `NewX(...)` constructors
80+
81+
- **Argument soup.** Go has no named parameters; long `NewX(a, b, c, d)` calls are order-sensitive
82+
and easy to mix up—especially when types repeat (`string, string, time.Time`). The compiler won’t
83+
catch swapped arguments of the same type.
84+
- **Generated code rarely ships constructors.** Tools like Swagger/OpenAPI or ORM generators
85+
typically emit structs without `New...` helpers. **gobetter** can be applied to those externally
86+
generated files (e.g., `-generate-for=exported`) to produce builders **without modifying the
87+
original code**.
88+
89+
### What you get with gobetter
90+
91+
- **Compile-time guarantees**: can’t build until all mandatory fields are provided.
92+
- **Refactor-friendly**: adding/removing required fields updates the chain; callers won’t compile
93+
until fixed.
94+
- **Great DX**: fluent steps + precise autocomplete; optionals can be skipped or added later.
95+
- **Inner struct support**: generates builders for inner structs with clean naming.
96+
97+
## How it works (in one line)
98+
99+
gobetter generates a chain of tiny step types (each `struct{ root *T }`) that expose only the next
100+
valid setter. Setters are trivial assignments that Go inlines, so no performance of memory penalty;
101+
the step values stay on the stack, and `Build()` returns the single `*T` you’re constructing. Net
102+
result: compile‑time required with essentially zero runtime overhead.
103+
57104
## Installation
58105

59106
Install **gobetter** as standalone utility:
@@ -129,7 +176,7 @@ fmt.Println(person.Score) // 85 (public field, no function needed)
129176
fmt.Println(person.Description) // "Software engineer"
130177
```
131178

132-
## 📝 Annotations Reference
179+
## Annotations Reference
133180

134181
| Annotation | Description | Example |
135182
|----------------------|------------------------------------------|-------------------------------------------|
@@ -139,7 +186,7 @@ fmt.Println(person.Description) // "Software engineer"
139186
| `//+gob:acronym` | Treat field as acronym (DOB vs Dob) | `dob string //+gob:getter +gob:acronym` |
140187
| `//+gob:_` | Mark field as optional (skip in builder) | `description string //+gob:_` |
141188

142-
## 🏗️ Nested Structs Support
189+
## Nested Structs Support
143190

144191
**gobetter** supports nested structs with clean naming and type aliases:
145192

0 commit comments

Comments
 (0)