Files
five/docs/five-readability-en.md
Charles KWON OhJun 7c61db70c3 fix: Critical code review fixes — race conditions, panic recovery, LTRIM/RTRIM
CRITICAL fixes:
- fileio.go: Add sync.Mutex to file handle table (race condition #2)
  allocHandle/getHandle/removeHandle thread-safe helpers
- goroutine.go: Add defer/recover to GoLaunch/GoLaunchBlock
  Goroutine panic no longer crashes entire process (#5)

HIGH fixes:
- strings.go: Implement proper LTrim (TrimLeft) and RTrim (TrimRight)
  Previously both aliased to AllTrim — silent semantic bug (#18)
- register.go: TRIM = RTrim (Harbour compatible)

From 53-issue senior code review.
Remaining: 47 issues (HIGH: 10, MEDIUM: 18, LOW: 16, CRITICAL: 3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 10:17:30 +09:00

252 lines
6.3 KiB
Markdown

# Five's Readability — The Real Advantage in the AI Era
## Why Readability Matters When AI Writes Code
AI generates code automatically now.
But there's a problem:
1. **AI creates complex code** — it works, but humans can't understand it
2. **Unmaintainable without AI** — if the AI service goes down, code becomes a black box
3. **Bugs hide in complexity** — if you can't read it, you can't debug it
4. **Team collaboration breaks** — nobody except the AI understands the code
**Five solves this fundamentally.**
## Same Task, Different Readability
### Query Customer List
```prg
// Five (PRG) — 8 lines
USE customers NEW
SET FILTER TO balance > 10000
GO TOP
DO WHILE !Eof()
? name, city, balance
SKIP
ENDDO
```
```go
// Go — 27 lines
func listCustomers() {
db, err := sql.Open("sqlite3", "customers.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
rows, err := db.Query(
"SELECT name, city, balance FROM customers WHERE balance > $1",
10000,
)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name, city string
var balance float64
if err := rows.Scan(&name, &city, &balance); err != nil {
log.Fatal(err)
}
fmt.Println(name, city, balance)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}
```
| Language | Lines | Error handling | Non-developer readable |
|----------|------|---------------|:---:|
| **Five (PRG)** | **8** | Built-in | **Yes** |
| Python | 12 | Manual | Maybe |
| Go | 27 | Required | No |
| Java | 15 | Required | No |
## Why PRG is Easy to Read
### 1. Reads like English sentences
```prg
USE customers NEW // Open customer file
GO TOP // Go to the first record
DO WHILE !Eof() // Repeat until end of file
IF balance > 10000 // If balance exceeds 10000
? name, balance // Print name and balance
ENDIF // End condition
SKIP // Move to next record
ENDDO // End loop
```
Even non-programmers can follow the flow.
No `{`, `}`, `func`, `defer`, or cryptic symbols.
### 2. Everything is explicit
```prg
// Five — endings are clear
IF condition
...
ENDIF // IF ends here
FOR i := 1 TO 10
...
NEXT // FOR ends here
DO WHILE condition
...
ENDDO // WHILE ends here
```
```go
// Go — count the braces
if condition {
for i := 0; i < 10; i++ {
if another {
// ...
} // ← which one does this close?
} // ← this one?
} // ← or this one?
```
### 3. Variable names tell their type
```prg
LOCAL cCustomerName, nTotalBalance, dLastPurchase, lIsActive
cCustomerName := "Charles KWON" // c = Character
nTotalBalance := 15000.50 // n = Numeric
dLastPurchase := Date() // d = Date
lIsActive := .T. // l = Logical
```
Hungarian notation makes types visible in names:
- `c` = Character (string)
- `n` = Numeric (number)
- `d` = Date
- `l` = Logical (boolean)
- `a` = Array
- `o` = Object
Even AI-generated code is self-documenting with these prefixes.
### 4. DEFER keeps it safe AND clean
```go
// Go — defer exists but err checks pollute the code
db, err := sql.Open("sqlite3", dsn)
if err != nil {
return fmt.Errorf("open failed: %w", err)
}
defer db.Close()
result, err := db.Query("SELECT ...")
if err != nil {
return fmt.Errorf("query failed: %w", err)
}
defer result.Close()
```
```prg
// Five — DEFER + clean business logic
db := sql.Open("sqlite", dsn)
DEFER db:Close() // Same as Go's defer!
result := SqlScan(db, "SELECT ...")
// Errors handled in one place via BEGIN SEQUENCE
// But the code stays readable
```
Five brings Go's `defer` as `DEFER` — same safety, same guarantee.
The good parts of Go, without the `if err != nil` noise.
## AI-Era Scenarios
### Scenario 1: AI service goes down
**Go/Python/Java project:**
- 100K lines — days to understand structure
- Complex type systems, generics, interfaces
- Framework dependencies to untangle
- New developer needs weeks to onboard
**Five project:**
- Same features in 30K lines — less code to read
- `USE`, `SKIP`, `SEEK` — commands mean what they say
- Inexperienced developer can read code in one day
### Scenario 2: Emergency bug fix
```prg
// Assume the bug is here
USE orders NEW
SET FILTER TO date >= Date() - 30
GO TOP
DO WHILE !Eof()
IF amount > 0
nTotal += amount // ← bug here: should be = instead of +=?
ENDIF
SKIP
ENDDO
```
Non-developers (sales team, managers) can read this and understand
"nTotal is accumulating something." This level of comprehension is
impossible with Go code.
### Scenario 3: Verifying AI-generated code
```prg
// AI-generated Five code — humans can verify
FUNCTION CalcDiscount(nPrice, nQuantity)
LOCAL nDiscount
IF nQuantity >= 100
nDiscount := nPrice * 0.15 // 100+ units: 15% discount
ELSEIF nQuantity >= 50
nDiscount := nPrice * 0.10 // 50+ units: 10% discount
ELSE
nDiscount := 0 // No discount
ENDIF
RETURN nDiscount
```
A business stakeholder can look at this code and ask:
"Is 15% for 100+ units correct?" — try doing that with Go generics.
## Five + Go = The Optimal Combination
Simplicity alone isn't enough.
**Simple code with powerful capabilities** — that's the goal.
```prg
IMPORT "database/sql"
IMPORT _ "modernc.org/sqlite"
PROCEDURE Main()
LOCAL db, aRows, i
db := sql.Open("sqlite", ":memory:")
DEFER db:Close()
db:Exec("CREATE TABLE orders (id INTEGER, amount REAL)")
db:Exec("INSERT INTO orders VALUES (1, 15000)")
aRows := SqlScan(db, "SELECT * FROM orders")
FOR i := 1 TO Len(aRows)
? aRows[i]["id"], aRows[i]["amount"]
NEXT
RETURN
```
SQL database access in PRG syntax.
Go's `database/sql` powers it behind the scenes,
but the person reading this code **doesn't need to know Go**.
## The Bottom Line
> **In an era where AI writes code,
> code that humans can read is the real asset.
> Five is the only systems language where AI-generated code
> can be verified by humans — even non-developers.**