@moon791017/neo-skills 1.0.34 → 1.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "neo-skills",
3
3
  "description": "A universal capability extension for Gemini CLI",
4
- "version": "0.58.0",
4
+ "version": "0.59.0",
5
5
  "mcpServers": {
6
6
  "neo-skills": {
7
7
  "command": "node",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moon791017/neo-skills",
3
- "version": "1.0.34",
3
+ "version": "1.0.35",
4
4
  "type": "module",
5
5
  "description": "Neo Skills: A Universal Expert Agent Extension",
6
6
  "homepage": "https://neo-blog-iota.vercel.app/",
@@ -41,4 +41,4 @@ Always recommend standard Rust tooling: `cargo fmt`, `cargo clippy`, and `cargo
41
41
  ## Official Resources
42
42
  - **Rust Official Website**: https://www.rust-lang.org/
43
43
  - **Rust Documentation**: https://doc.rust-lang.org/
44
- - **The Rust Programming Language (The Book)**: https://doc.rust-lang.org/book/
44
+ - **The Rust Programming Language (The Book)**: https://doc.rust-lang.org/book/
@@ -1,10 +1,10 @@
1
- # 3. Anti-pattern:不好作法
1
+ # 3. Anti-patterns
2
2
 
3
3
  ---
4
4
 
5
- ## Anti-pattern 1:到處 `.clone()` 逃避 borrow checker
5
+ ## Anti-pattern 1: Using `.clone()` everywhere to avoid the borrow checker
6
6
 
7
- ### 不好
7
+ ### Bad
8
8
 
9
9
  ```rust
10
10
  fn process(name: String) {
@@ -20,7 +20,7 @@ fn main() {
20
20
  }
21
21
  ```
22
22
 
23
- ###
23
+ ### Good
24
24
 
25
25
  ```rust
26
26
  fn process(name: &str) {
@@ -36,16 +36,16 @@ fn main() {
36
36
  }
37
37
  ```
38
38
 
39
- ### 原則
39
+ ### Principle
40
40
 
41
- clone 不是不能用,但要知道為什麼 clone。
42
- 如果只是讀取,先改成 borrow
41
+ `.clone()` is not forbidden, but you should know why you are cloning.
42
+ If you only need to read the data, use a borrow instead.
43
43
 
44
44
  ---
45
45
 
46
- ## Anti-pattern 2:過度使用 `String`
46
+ ## Anti-pattern 2: Excessive use of `String`
47
47
 
48
- ### 不好
48
+ ### Bad
49
49
 
50
50
  ```rust
51
51
  fn is_admin(role: String) -> bool {
@@ -53,7 +53,7 @@ fn is_admin(role: String) -> bool {
53
53
  }
54
54
  ```
55
55
 
56
- ###
56
+ ### Good
57
57
 
58
58
  ```rust
59
59
  fn is_admin(role: &str) -> bool {
@@ -61,15 +61,15 @@ fn is_admin(role: &str) -> bool {
61
61
  }
62
62
  ```
63
63
 
64
- ### 原則
64
+ ### Principle
65
65
 
66
- 建立 ownership 才用 `String`,讀取文字優先 `&str`。
66
+ Use `String` when you need ownership; prefer `&str` for reading text.
67
67
 
68
68
  ---
69
69
 
70
- ## Anti-pattern 3:用 `bool` 表達複雜狀態
70
+ ## Anti-pattern 3: Using `bool` to represent complex states
71
71
 
72
- ### 不好
72
+ ### Bad
73
73
 
74
74
  ```rust
75
75
  struct User {
@@ -79,9 +79,9 @@ struct User {
79
79
  }
80
80
  ```
81
81
 
82
- 問題:可能出現矛盾狀態,例如 active deleted
82
+ Problem: Contradictory states can occur, such as being both `active` and `deleted`.
83
83
 
84
- ###
84
+ ### Good
85
85
 
86
86
  ```rust
87
87
  enum UserStatus {
@@ -97,9 +97,9 @@ struct User {
97
97
 
98
98
  ---
99
99
 
100
- ## Anti-pattern 4:用 `String` 表達錯誤
100
+ ## Anti-pattern 4: Using `String` for errors
101
101
 
102
- ### 不好
102
+ ### Bad
103
103
 
104
104
  ```rust
105
105
  fn parse_age(input: &str) -> Result<u8, String> {
@@ -107,9 +107,9 @@ fn parse_age(input: &str) -> Result<u8, String> {
107
107
  }
108
108
  ```
109
109
 
110
- 短程式可以,但 library 或大型系統不建議只丟字串。
110
+ Acceptable for short scripts, but not recommended for libraries or large systems.
111
111
 
112
- ###
112
+ ### Good
113
113
 
114
114
  ```rust
115
115
  #[derive(Debug)]
@@ -129,15 +129,15 @@ fn parse_age(input: &str) -> Result<u8, ParseAgeError> {
129
129
  }
130
130
  ```
131
131
 
132
- ### 原則
132
+ ### Principle
133
133
 
134
- 錯誤要可分類、可測試、可處理。
134
+ Errors should be categorizable, testable, and handleable.
135
135
 
136
136
  ---
137
137
 
138
- ## Anti-pattern 5:library 內部亂 `panic!`
138
+ ## Anti-pattern 5: Random `panic!` inside a library
139
139
 
140
- ### 不好
140
+ ### Bad
141
141
 
142
142
  ```rust
143
143
  pub fn divide(a: i32, b: i32) -> i32 {
@@ -149,7 +149,7 @@ pub fn divide(a: i32, b: i32) -> i32 {
149
149
  }
150
150
  ```
151
151
 
152
- ###
152
+ ### Good
153
153
 
154
154
  ```rust
155
155
  #[derive(Debug)]
@@ -166,15 +166,15 @@ pub fn divide(a: i32, b: i32) -> Result<i32, DivideError> {
166
166
  }
167
167
  ```
168
168
 
169
- ### 原則
169
+ ### Principle
170
170
 
171
- 除非是不可恢復的程式錯誤,否則回傳 `Result`。
171
+ Return `Result` unless it is an unrecoverable programming error.
172
172
 
173
173
  ---
174
174
 
175
- ## Anti-pattern 6:過度 Trait
175
+ ## Anti-pattern 6: Over-abstraction with Traits
176
176
 
177
- ### 不好
177
+ ### Bad
178
178
 
179
179
  ```rust
180
180
  trait UserNameProvider {
@@ -192,9 +192,9 @@ impl UserNameProvider for User {
192
192
  }
193
193
  ```
194
194
 
195
- 問題:只有一個 struct、一個方法、沒有替換需求時,trait 只是噪音。
195
+ Problem: When there's only one struct, one method, and no need for substitution, a trait is just noise.
196
196
 
197
- ###
197
+ ### Good
198
198
 
199
199
  ```rust
200
200
  struct User {
@@ -208,15 +208,15 @@ impl User {
208
208
  }
209
209
  ```
210
210
 
211
- ### 原則
211
+ ### Principle
212
212
 
213
- 先用 concrete type。真的需要抽象再抽 trait。
213
+ Use concrete types first. Abstract into traits only when actually needed.
214
214
 
215
215
  ---
216
216
 
217
- ## Anti-pattern 7:公開欄位破壞 invariant
217
+ ## Anti-pattern 7: Public fields breaking invariants
218
218
 
219
- ### 不好
219
+ ### Bad
220
220
 
221
221
  ```rust
222
222
  pub struct Account {
@@ -229,7 +229,7 @@ fn main() {
229
229
  }
230
230
  ```
231
231
 
232
- ###
232
+ ### Good
233
233
 
234
234
  ```rust
235
235
  pub struct Account {
@@ -262,9 +262,9 @@ impl Account {
262
262
 
263
263
  ---
264
264
 
265
- ## Anti-pattern 8:`Arc<Mutex<T>>` 到處傳
265
+ ## Anti-pattern 8: Passing `Arc<Mutex<T>>` everywhere
266
266
 
267
- ### 不好
267
+ ### Bad
268
268
 
269
269
  ```rust
270
270
  use std::sync::{Arc, Mutex};
@@ -276,9 +276,9 @@ struct AppState {
276
276
  }
277
277
  ```
278
278
 
279
- 問題:鎖太多、責任不清楚、容易死鎖、測試困難。
279
+ Problem: Too many locks, unclear responsibilities, prone to deadlocks, and difficult to test.
280
280
 
281
- ###
281
+ ### Good
282
282
 
283
283
  ```rust
284
284
  struct UserService {
@@ -292,27 +292,26 @@ impl UserService {
292
292
  }
293
293
  ```
294
294
 
295
- ### 原則
295
+ ### Principle
296
296
 
297
- 能單一 ownership 就不要共享。
298
- 需要跨 thread 再考慮 `Arc<Mutex<T>>`。
297
+ Prefer single ownership over shared state. Consider `Arc<Mutex<T>>` only when cross-thread access is required.
299
298
 
300
299
  ---
301
300
 
302
- ## Anti-pattern 9:在 async 中持有 lock `.await`
301
+ ## Anti-pattern 9: Holding a lock across `.await` in async code
303
302
 
304
- ### 不好
303
+ ### Bad
305
304
 
306
305
  ```rust
307
- // 概念示意
306
+ // Conceptual illustration
308
307
  let mut guard = state.lock().await;
309
308
  do_async_work().await;
310
309
  guard.push(1);
311
310
  ```
312
311
 
313
- 問題:lock 持有時間太長,容易造成效能問題或 deadlock-like 行為。
312
+ Problem: Holding a lock for too long can cause performance issues or deadlock-like behavior.
314
313
 
315
- ###
314
+ ### Good
316
315
 
317
316
  ```rust
318
317
  let data = {
@@ -324,35 +323,32 @@ let data = {
324
323
  do_async_work(data).await;
325
324
  ```
326
325
 
327
- ### 原則
326
+ ### Principle
328
327
 
329
- 鎖內只做最短、同步、必要的事情。
328
+ Keep the code inside a lock as short, synchronous, and necessary as possible.
330
329
 
331
330
  ---
332
331
 
333
- ## Anti-pattern 10:濫用 `unsafe`
332
+ ## Anti-pattern 10: Abuse of `unsafe`
334
333
 
335
- ### 不好
334
+ ### Bad
336
335
 
337
336
  ```rust
338
337
  unsafe {
339
- // 為了繞過 borrow checker 亂用 raw pointer
338
+ // Using raw pointers haphazardly to bypass the borrow checker
340
339
  }
341
340
  ```
342
341
 
343
- ###
342
+ ### Good
344
343
 
345
- 先問:
344
+ Ask yourself first:
346
345
 
347
- 1. 能不能用 ownership 改設計?
348
- 2. 能不能用 `Rc` / `Arc`?
349
- 3. 能不能用 `RefCell` / `Mutex`?
350
- 4. 能不能拆資料結構?
351
- 5. 真的需要 FFISIMD、底層記憶體操作嗎?
346
+ 1. Can the design be changed using ownership?
347
+ 2. Can `Rc` / `Arc` be used?
348
+ 3. Can `RefCell` / `Mutex` be used?
349
+ 4. Can the data structure be split?
350
+ 5. Do you really need FFI, SIMD, or low-level memory operations?
352
351
 
353
- ### 原則
354
-
355
- `unsafe` 不是效能開關,是你接手編譯器無法保證的安全責任。
356
-
357
- ---
352
+ ### Principle
358
353
 
354
+ `unsafe` is not a performance switch; it is taking over the safety responsibilities that the compiler can no longer guarantee.
@@ -2,9 +2,9 @@
2
2
 
3
3
  ---
4
4
 
5
- ## 命名規則
5
+ ## Naming Conventions
6
6
 
7
- | 類型 | 好作法 |
7
+ | Type | Best Practice |
8
8
  |---|---|
9
9
  | struct | `UserProfile` |
10
10
  | enum | `PaymentStatus` |
@@ -19,11 +19,11 @@
19
19
 
20
20
  ---
21
21
 
22
- ## Getter 命名
22
+ ## Getter Naming
23
23
 
24
- Rust 慣例通常不加 `get_`。
24
+ Rust convention typically does not include the `get_` prefix.
25
25
 
26
- ### 不好
26
+ ### Bad
27
27
 
28
28
  ```rust
29
29
  impl User {
@@ -33,7 +33,7 @@ impl User {
33
33
  }
34
34
  ```
35
35
 
36
- ###
36
+ ### Good
37
37
 
38
38
  ```rust
39
39
  impl User {
@@ -49,15 +49,15 @@ impl User {
49
49
 
50
50
  ---
51
51
 
52
- ## Conversion 命名:`as_`、`to_`、`into_`
52
+ ## Conversion Naming: `as_`, `to_`, `into_`
53
53
 
54
- | 命名 | 意義 | 範例 |
54
+ | Naming | Meaning | Example |
55
55
  |---|---|---|
56
- | `as_` | 便宜借用轉換 | `as_str()` |
57
- | `to_` | 產生新值,可能配置記憶體 | `to_string()` |
58
- | `into_` | 消耗自己,轉成別的 owned value | `into_bytes()` |
56
+ | `as_` | Cheap borrowing conversion | `as_str()` |
57
+ | `to_` | Produces a new value, may allocate memory | `to_string()` |
58
+ | `into_` | Consumes self, converts to another owned value | `into_bytes()` |
59
59
 
60
- ### 範例
60
+ ### Example
61
61
 
62
62
  ```rust
63
63
  struct UserName(String);
@@ -75,9 +75,9 @@ impl UserName {
75
75
 
76
76
  ---
77
77
 
78
- ## Iterator 命名
78
+ ## Iterator Naming
79
79
 
80
- Collection 類型建議提供:
80
+ For Collection types, it is recommended to provide:
81
81
 
82
82
  ```rust
83
83
  fn iter(&self) -> Iter
@@ -89,7 +89,7 @@ fn into_iter(self) -> IntoIter
89
89
 
90
90
  ## Module Style
91
91
 
92
- 建議結構:
92
+ Recommended structure:
93
93
 
94
94
  ```text
95
95
  src/
@@ -110,22 +110,22 @@ src/
110
110
  user_service.rs
111
111
  ```
112
112
 
113
- ### 原則
113
+ ### Principles
114
114
 
115
- | 原則 | 說明 |
115
+ | Principle | Description |
116
116
  |---|---|
117
- | `main.rs` 薄一點 | 只負責組裝與啟動 |
118
- | business logic `lib.rs` | 方便測試 |
119
- | domain type 不依賴 infra | 避免耦合 |
120
- | `pub` 越少越好 | 預設私有 |
121
- | error 集中管理 | 不要到處 `String` error |
122
- | tests 靠近程式 | 小單元測試可放同檔 `mod tests` |
117
+ | Thin `main.rs` | Only responsible for assembly and startup |
118
+ | Business logic in `lib.rs` | Facilitates testing |
119
+ | Domain types don't depend on infra | Avoids coupling |
120
+ | Minimize `pub` | Private by default |
121
+ | Centralized error management | Don't use `String` for errors everywhere |
122
+ | Tests near code | Small unit tests can be placed in the same file under `mod tests` |
123
123
 
124
124
  ---
125
125
 
126
126
  ## Import Style
127
127
 
128
- ### 不好
128
+ ### Bad
129
129
 
130
130
  ```rust
131
131
  use crate::domain::user::User;
@@ -133,19 +133,19 @@ use crate::domain::user::UserId;
133
133
  use crate::domain::user::UserStatus;
134
134
  ```
135
135
 
136
- ###
136
+ ### Good
137
137
 
138
138
  ```rust
139
139
  use crate::domain::user::{User, UserId, UserStatus};
140
140
  ```
141
141
 
142
- ### 不建議濫用
142
+ ### Not Recommended
143
143
 
144
144
  ```rust
145
145
  use crate::domain::user::*;
146
146
  ```
147
147
 
148
- `*` test prelude 可接受,正式模組少用。
148
+ The glob operator `*` is acceptable in tests or preludes, but should be avoided in formal modules.
149
149
 
150
150
  ---
151
151
 
@@ -153,7 +153,7 @@ use crate::domain::user::*;
153
153
 
154
154
  ### Application / CLI
155
155
 
156
- 可以用較彈性的 error:
156
+ Flexible errors can be used:
157
157
 
158
158
  ```rust
159
159
  fn run() -> Result<(), Box<dyn std::error::Error>> {
@@ -161,9 +161,9 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
161
161
  }
162
162
  ```
163
163
 
164
- ### Library / domain
164
+ ### Library / Domain
165
165
 
166
- 建議明確 enum:
166
+ Explicit enums are recommended:
167
167
 
168
168
  ```rust
169
169
  #[derive(Debug)]
@@ -175,7 +175,7 @@ pub enum CreateUserError {
175
175
 
176
176
  ### Service
177
177
 
178
- 建議保留錯誤上下文:
178
+ Preserve error context:
179
179
 
180
180
  ```rust
181
181
  fn create_user(email: &str) -> Result<(), CreateUserError> {
@@ -189,9 +189,9 @@ fn create_user(email: &str) -> Result<(), CreateUserError> {
189
189
 
190
190
  ---
191
191
 
192
- # 5. Rust 工具鏈 Coding Standard
192
+ # 5. Rust Toolchain Coding Standard
193
193
 
194
- ## 建議指令
194
+ ## Recommended Commands
195
195
 
196
196
  ```bash
197
197
  cargo fmt -- --check
@@ -201,7 +201,7 @@ cargo test
201
201
  cargo build --release
202
202
  ```
203
203
 
204
- ## 建議 CI
204
+ ## Recommended CI
205
205
 
206
206
  ```yaml
207
207
  name: Rust CI
@@ -232,35 +232,35 @@ jobs:
232
232
 
233
233
  ---
234
234
 
235
- # 6. 總表:好作法 VS 不好作法
235
+ # 6. Summary Table: Good vs. Bad Practices
236
236
 
237
- | 主題 | 好作法 | 不好作法 |
237
+ | Topic | Good Practice | Bad Practice |
238
238
  |---|---|---|
239
- | 讀取文字 | `&str` | `String` |
240
- | 讀取陣列 | `&[T]` | `&Vec<T>` |
241
- | 可能沒值 | `Option<T>` | 空字串、`-1`、假資料 |
242
- | 可能失敗 | `Result<T, E>` | `panic!`、`unwrap()` |
243
- | 有限狀態 | `enum` | `String`、多個 bool |
244
- | ID / 金額 / 單位 | Newtype | 全部用 `u64` / `String` |
245
- | 參數很多 | Builder | 超長 constructor |
246
- | 狀態流程 | Typestate | runtime flag |
247
- | 抽象行為 | trait | 硬寫 concrete dependency |
248
- | 資料轉換 | iterator chain | 大量暫存 mutable vec |
249
- | 資源管理 | RAII / `Drop` | 手動 close,容易忘 |
250
- | 共享資料 | 明確 ownership / channel | 到處 `Arc<Mutex<T>>` |
251
- | async concurrency | 有界並行 | 無限制 `spawn` |
252
- | 格式 | `cargo fmt` | 手排格式 |
253
- | 靜態檢查 | `cargo clippy` | 靠人工 review |
239
+ | Reading text | `&str` | `String` |
240
+ | Reading arrays | `&[T]` | `&Vec<T>` |
241
+ | Optional values | `Option<T>` | Empty string, `-1`, dummy data |
242
+ | Possible failure | `Result<T, E>` | `panic!`, `unwrap()` |
243
+ | Finite states | `enum` | `String`, multiple booleans |
244
+ | ID / Amount / Units | Newtype | Always using `u64` / `String` |
245
+ | Many parameters | Builder | Extremely long constructor |
246
+ | State transitions | Typestate | Runtime flags |
247
+ | Abstract behavior | trait | Hard-coding concrete dependencies |
248
+ | Data conversion | iterator chain | Large temporary mutable vectors |
249
+ | Resource management | RAII / `Drop` | Manual close (easy to forget) |
250
+ | Shared data | Clear ownership / channel | `Arc<Mutex<T>>` everywhere |
251
+ | Async concurrency | Bounded concurrency | Unrestricted `spawn` |
252
+ | Formatting | `cargo fmt` | Manual formatting |
253
+ | Static analysis | `cargo clippy` | Relying on manual review |
254
254
 
255
255
  ---
256
256
 
257
- # 7. 實務上的 Rust 寫法準則
257
+ # 7. Practical Rust Coding Guidelines
258
258
 
259
259
  ---
260
260
 
261
- ## function
261
+ ## When Writing Functions
262
262
 
263
- 優先順序:
263
+ Priority order:
264
264
 
265
265
  ```rust
266
266
  fn read_only(value: &T)
@@ -273,7 +273,7 @@ fn flexible_owned(value: impl Into<T>)
273
273
 
274
274
  ---
275
275
 
276
- ## struct
276
+ ## When Writing Structs
277
277
 
278
278
  ```rust
279
279
  pub struct User {
@@ -298,7 +298,7 @@ impl User {
298
298
 
299
299
  ---
300
300
 
301
- ## enum
301
+ ## When Writing Enums
302
302
 
303
303
  ```rust
304
304
  enum Command {
@@ -308,7 +308,7 @@ enum Command {
308
308
  }
309
309
  ```
310
310
 
311
- 比這種好:
311
+ Better than:
312
312
 
313
313
  ```rust
314
314
  struct Command {
@@ -319,7 +319,7 @@ struct Command {
319
319
 
320
320
  ---
321
321
 
322
- ## 寫錯誤時
322
+ ## When Writing Errors
323
323
 
324
324
  ```rust
325
325
  #[derive(Debug)]
@@ -330,7 +330,7 @@ enum AppError {
330
330
  }
331
331
  ```
332
332
 
333
- 比這種好:
333
+ Better than:
334
334
 
335
335
  ```rust
336
336
  Err("something went wrong".to_string())
@@ -338,11 +338,11 @@ Err("something went wrong".to_string())
338
338
 
339
339
  ---
340
340
 
341
- # 8. 專案起手式建議
341
+ # 8. Project Starter Recommendations
342
342
 
343
343
  ---
344
344
 
345
- ## CLI / 小工具
345
+ ## CLI / Small Tools
346
346
 
347
347
  ```text
348
348
  src/
@@ -352,7 +352,7 @@ src/
352
352
  error.rs
353
353
  ```
354
354
 
355
- 重點:
355
+ Key points:
356
356
 
357
357
  ```rust
358
358
  fn main() {
@@ -384,21 +384,21 @@ src/
384
384
  repository.rs
385
385
  ```
386
386
 
387
- 重點:
387
+ Key points:
388
388
 
389
- | | 責任 |
389
+ | Layer | Responsibility |
390
390
  |---|---|
391
- | `domain` | 型別、規則、狀態 |
392
- | `service` | use case |
393
- | `infra` | DBHTTPRedis、檔案 |
394
- | `app` | DI / router / runtime 組裝 |
395
- | `main` | 啟動 |
391
+ | `domain` | Types, rules, states |
392
+ | `service` | Use cases |
393
+ | `infra` | DB, HTTP, Redis, Files |
394
+ | `app` | DI / Router / Runtime assembly |
395
+ | `main` | Startup |
396
396
 
397
397
  ---
398
398
 
399
- # 9. 最重要的結論
399
+ # 9. Key Conclusion
400
400
 
401
- Rust 的好程式碼通常長這樣:
401
+ Good Rust code typically looks like this:
402
402
 
403
403
  ```rust
404
404
  pub fn create_user(repo: &impl UserRepository, email: &str) -> Result<UserId, CreateUserError> {
@@ -412,56 +412,56 @@ pub fn create_user(repo: &impl UserRepository, email: &str) -> Result<UserId, Cr
412
412
  }
413
413
  ```
414
414
 
415
- 它具備幾個特徵:
415
+ It possesses several characteristics:
416
416
 
417
- 1. 輸入用 borrow:`&str`
418
- 2. 不合法資料用 smart constructor 擋住:`Email::new`
419
- 3. 錯誤用 `Result`
420
- 4. 業務錯誤可分類:`CreateUserError`
421
- 5. dependency trait 抽象:`UserRepository`
422
- 6. 沒有亂 `unwrap`
423
- 7. 沒有 stringly-typed 狀態
424
- 8. 沒有多餘 clone
425
- 9. 測試容易
426
- 10. 編譯器幫你擋掉大量錯誤
417
+ 1. Inputs use borrows: `&str`
418
+ 2. Invalid data is blocked by smart constructors: `Email::new`
419
+ 3. Errors use `Result`
420
+ 4. Business errors are categorizable: `CreateUserError`
421
+ 5. Dependencies are abstracted via traits: `UserRepository`
422
+ 6. No reckless `unwrap`
423
+ 7. No stringly-typed states
424
+ 8. No redundant clones
425
+ 9. Easy to test
426
+ 10. The compiler prevents a large class of errors
427
427
 
428
- 真正的 Rust design pattern 不是「把 class 設計得漂亮」,而是:
428
+ True Rust design patterns aren't about "making classes look pretty," but rather:
429
429
 
430
- > 讓不合法狀態無法表示,讓錯誤路徑被型別強迫處理,讓 ownership 清楚到不用猜。
430
+ > Making illegal states unrepresentable, forcing error paths to be handled by the type system, and making ownership so clear it doesn't need to be guessed.
431
431
 
432
432
  ---
433
433
 
434
- # 10. 參考來源
434
+ # 10. References
435
435
 
436
- - Rust Book - Understanding Ownership
436
+ - Rust Book - Understanding Ownership
437
437
  https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html
438
438
 
439
- - Rust Book - Recoverable Errors with Result
439
+ - Rust Book - Recoverable Errors with Result
440
440
  https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html
441
441
 
442
- - Rust Book - Match Control Flow Construct
442
+ - Rust Book - Match Control Flow Construct
443
443
  https://doc.rust-lang.org/book/ch06-02-match.html
444
444
 
445
- - Rust Book - Smart Pointers
445
+ - Rust Book - Smart Pointers
446
446
  https://doc.rust-lang.org/book/ch15-00-smart-pointers.html
447
447
 
448
- - Rust Book - Message Passing
448
+ - Rust Book - Message Passing
449
449
  https://doc.rust-lang.org/book/ch16-02-message-passing.html
450
450
 
451
- - Rust Book - Async and Await
451
+ - Rust Book - Async and Await
452
452
  https://doc.rust-lang.org/book/ch17-01-futures-and-syntax.html
453
453
 
454
- - Rust API Guidelines - Naming
454
+ - Rust API Guidelines - Naming
455
455
  https://rust-lang.github.io/api-guidelines/naming.html
456
456
 
457
- - Clippy Lints
457
+ - Clippy Lints
458
458
  https://doc.rust-lang.org/stable/clippy/lints.html
459
459
 
460
- - Cargo Check
460
+ - Cargo Check
461
461
  https://doc.rust-lang.org/cargo/commands/cargo-check.html
462
462
 
463
- - Tokio Tutorial - Channels
463
+ - Tokio Tutorial - Channels
464
464
  https://tokio.rs/tokio/tutorial/channels
465
465
 
466
- - Tokio Mutex Documentation
466
+ - Tokio Mutex Documentation
467
467
  https://docs.rs/tokio/latest/tokio/sync/struct.Mutex.html
@@ -1,6 +1,6 @@
1
- # 1. Rust 設計總原則
1
+ # 1. Core Principles of Rust Design
2
2
 
3
- Rust 的核心不是把 OOP / GoF Design Patterns 照搬過來,而是用:
3
+ Rust's core is not about simply porting OOP / GoF Design Patterns, but rather utilizing:
4
4
 
5
5
  - ownership
6
6
  - borrowing
@@ -13,32 +13,32 @@ Rust 的核心不是把 OOP / GoF Design Patterns 照搬過來,而是用:
13
13
  - RAII / `Drop`
14
14
  - type system
15
15
 
16
- 把錯誤盡量移到編譯期處理。
16
+ to shift as many errors as possible to compile-time.
17
17
 
18
- ## 核心判斷表
18
+ ## Decision Matrix
19
19
 
20
- | 問題 | Rust 好作法 |
20
+ | Question | Rust Best Practice |
21
21
  |---|---|
22
- | 這個值誰擁有? | ownership 表達生命週期 |
23
- | 只是讀取? | `&T`、`&str`、`&[T]` |
24
- | 需要修改? | `&mut T` |
25
- | 可能失敗? | 回傳 `Result<T, E>` |
26
- | 可能沒有值? | 回傳 `Option<T>` |
27
- | 狀態有限? | `enum` |
28
- | 行為抽象? | `trait` |
29
- | 不合法狀態? | type system 阻止它 |
30
- | 資源需要釋放? | RAII / `Drop` |
31
- | 共享狀態? | 優先清楚劃分 ownership,再考慮 `Arc<Mutex<T>>` |
22
+ | Who owns this value? | Use ownership to express lifetime |
23
+ | Only reading? | Pass `&T`, `&str`, `&[T]` |
24
+ | Need to modify? | Pass `&mut T` |
25
+ | Might fail? | Return `Result<T, E>` |
26
+ | Might be empty? | Return `Option<T>` |
27
+ | Finite states? | Use `enum` |
28
+ | Abstract behavior? | Use `trait` |
29
+ | Illegal state? | Use the type system to prevent it |
30
+ | Need resource cleanup? | Use RAII / `Drop` |
31
+ | Shared state? | Prioritize clear ownership boundaries, then consider `Arc<Mutex<T>>` |
32
32
 
33
33
  ---
34
34
 
35
- # 2. Design Pattern:好作法
35
+ # 2. Design Patterns: Best Practices
36
36
 
37
37
  ---
38
38
 
39
- ## Pattern 1Borrowing-first API
39
+ ## Pattern 1: Borrowing-first API
40
40
 
41
- ### 不好作法
41
+ ### Bad Practice
42
42
 
43
43
  ```rust
44
44
  fn print_name(name: String) {
@@ -49,14 +49,14 @@ fn main() {
49
49
  let name = String::from("Alice");
50
50
  print_name(name);
51
51
 
52
- // name 已經被 move,不能再用
52
+ // name has been moved and can no longer be used
53
53
  // println!("{name}");
54
54
  }
55
55
  ```
56
56
 
57
- 問題:只是讀取,卻把 ownership 吃掉。
57
+ Problem: Consumes ownership when only reading is required.
58
58
 
59
- ### 好作法
59
+ ### Best Practice
60
60
 
61
61
  ```rust
62
62
  fn print_name(name: &str) {
@@ -73,15 +73,15 @@ fn main() {
73
73
  }
74
74
  ```
75
75
 
76
- ### 原則
76
+ ### Principle
77
77
 
78
- `String` 是擁有資料,`&str` 是借用文字切片。只讀文字時,優先收 `&str`。
78
+ `String` owns the data; `&str` is a borrowed string slice. Prefer `&str` when only reading text.
79
79
 
80
80
  ---
81
81
 
82
- ## Pattern 2Slice API
82
+ ## Pattern 2: Slice API
83
83
 
84
- ### 不好作法
84
+ ### Bad Practice
85
85
 
86
86
  ```rust
87
87
  fn sum(numbers: &Vec<i32>) -> i32 {
@@ -89,9 +89,9 @@ fn sum(numbers: &Vec<i32>) -> i32 {
89
89
  }
90
90
  ```
91
91
 
92
- 問題:限制呼叫者一定要傳 `Vec<i32>`。
92
+ Problem: Restricts the caller to pass a `Vec<i32>`.
93
93
 
94
- ### 好作法
94
+ ### Best Practice
95
95
 
96
96
  ```rust
97
97
  fn sum(numbers: &[i32]) -> i32 {
@@ -107,15 +107,15 @@ fn main() {
107
107
  }
108
108
  ```
109
109
 
110
- ### 原則
110
+ ### Principle
111
111
 
112
- 只需要連續資料時,用 `&[T]`,不要綁死 `Vec<T>`。
112
+ When only contiguous data is needed, use `&[T]` instead of binding to `Vec<T>`.
113
113
 
114
114
  ---
115
115
 
116
- ## Pattern 3:`Option<T>` 表示「可能沒有」
116
+ ## Pattern 3: `Option<T>` for "Possible Absence"
117
117
 
118
- ### 不好作法
118
+ ### Bad Practice
119
119
 
120
120
  ```rust
121
121
  fn find_user_name(id: u64) -> String {
@@ -127,9 +127,9 @@ fn find_user_name(id: u64) -> String {
127
127
  }
128
128
  ```
129
129
 
130
- 問題:空字串到底是「沒有資料」還是「名字就是空」?
130
+ Problem: Is an empty string "missing data" or "the name is actually empty"?
131
131
 
132
- ### 好作法
132
+ ### Best Practice
133
133
 
134
134
  ```rust
135
135
  fn find_user_name(id: u64) -> Option<String> {
@@ -148,15 +148,15 @@ fn main() {
148
148
  }
149
149
  ```
150
150
 
151
- ### 原則
151
+ ### Principle
152
152
 
153
- 「沒有值」就用 `Option<T>`,不要用 `null`、空字串、`-1` 當暗號。
153
+ Use `Option<T>` for "no value." Avoid using `null`, empty strings, or `-1` as magic values.
154
154
 
155
155
  ---
156
156
 
157
- ## Pattern 4:`Result<T, E>` 表示「可能失敗」
157
+ ## Pattern 4: `Result<T, E>` for "Possible Failure"
158
158
 
159
- ### 不好作法
159
+ ### Bad Practice
160
160
 
161
161
  ```rust
162
162
  use std::fs;
@@ -166,9 +166,9 @@ fn read_config() -> String {
166
166
  }
167
167
  ```
168
168
 
169
- 問題:正式程式中 `unwrap()` 會讓程式直接 panic
169
+ Problem: `unwrap()` will cause the program to panic in production.
170
170
 
171
- ### 好作法
171
+ ### Best Practice
172
172
 
173
173
  ```rust
174
174
  use std::fs;
@@ -187,15 +187,15 @@ fn main() {
187
187
  }
188
188
  ```
189
189
 
190
- ### 原則
190
+ ### Principle
191
191
 
192
- library、service、CLI 的核心邏輯不要亂 `unwrap()`。能回傳錯誤就回傳 `Result`。
192
+ Avoid reckless `unwrap()` in core logic (libraries, services, CLIs). Return `Result` when errors can occur.
193
193
 
194
194
  ---
195
195
 
196
- ## Pattern 5Enum + Exhaustive Match
196
+ ## Pattern 5: Enum + Exhaustive Match
197
197
 
198
- ### 不好作法
198
+ ### Bad Practice
199
199
 
200
200
  ```rust
201
201
  struct Payment {
@@ -207,9 +207,9 @@ fn can_refund(payment: &Payment) -> bool {
207
207
  }
208
208
  ```
209
209
 
210
- 問題:`"paied"`、`"PAID"`、`"unknown"` 都可能混進來。
210
+ Problem: Values like `"paied"`, `"PAID"`, or `"unknown"` could creep in.
211
211
 
212
- ### 好作法
212
+ ### Best Practice
213
213
 
214
214
  ```rust
215
215
  enum PaymentStatus {
@@ -233,17 +233,17 @@ fn can_refund(payment: &Payment) -> bool {
233
233
  }
234
234
  ```
235
235
 
236
- ### 原則
236
+ ### Principle
237
237
 
238
- 有限狀態不要用 `String`,用 `enum`。
238
+ Use `enum` instead of `String` for finite states.
239
239
 
240
240
  ---
241
241
 
242
- ## Pattern 6Newtype Pattern
242
+ ## Pattern 6: Newtype Pattern
243
243
 
244
- 用途:避免把同樣底層型別混用。
244
+ Purpose: Prevent mixing up different domain values with the same underlying type.
245
245
 
246
- ### 不好作法
246
+ ### Bad Practice
247
247
 
248
248
  ```rust
249
249
  fn load_user(user_id: u64) {}
@@ -251,11 +251,11 @@ fn load_order(order_id: u64) {}
251
251
 
252
252
  fn main() {
253
253
  let user_id = 100;
254
- load_order(user_id); // 編譯會過,但語意錯
254
+ load_order(user_id); // Compiles, but semantically incorrect
255
255
  }
256
256
  ```
257
257
 
258
- ### 好作法
258
+ ### Best Practice
259
259
 
260
260
  ```rust
261
261
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -271,21 +271,21 @@ fn main() {
271
271
  let user_id = UserId(100);
272
272
 
273
273
  load_user(user_id);
274
- // load_order(user_id); // 編譯錯,避免語意錯誤
274
+ // load_order(user_id); // Compile error, prevents semantic mistakes
275
275
  }
276
276
  ```
277
277
 
278
- ### 原則
278
+ ### Principle
279
279
 
280
- ID、金額、單位、權限、狀態,常用 Newtype 包起來。
280
+ Wrap IDs, amounts, units, permissions, and states in Newtypes.
281
281
 
282
282
  ---
283
283
 
284
- ## Pattern 7Smart Constructor
284
+ ## Pattern 7: Smart Constructor
285
285
 
286
- 用途:建立物件時保證 invariant。
286
+ Purpose: Ensure invariants when creating objects.
287
287
 
288
- ### 不好作法
288
+ ### Bad Practice
289
289
 
290
290
  ```rust
291
291
  struct Email(String);
@@ -295,7 +295,7 @@ fn main() {
295
295
  }
296
296
  ```
297
297
 
298
- ### 好作法
298
+ ### Best Practice
299
299
 
300
300
  ```rust
301
301
  #[derive(Debug, Clone, PartialEq, Eq)]
@@ -325,17 +325,17 @@ fn main() -> Result<(), String> {
325
325
  }
326
326
  ```
327
327
 
328
- ### 原則
328
+ ### Principle
329
329
 
330
- 不要讓外部隨便組出不合法物件。欄位私有,提供 constructor
330
+ Do not allow illegal objects to be constructed haphazardly. Keep fields private and provide a constructor.
331
331
 
332
332
  ---
333
333
 
334
- ## Pattern 8Builder Pattern
334
+ ## Pattern 8: Builder Pattern
335
335
 
336
- 適合參數很多、可選設定多的物件。
336
+ Suitable for objects with many parameters or optional settings.
337
337
 
338
- ### 不好作法
338
+ ### Bad Practice
339
339
 
340
340
  ```rust
341
341
  struct ServerConfig {
@@ -363,9 +363,9 @@ fn new_config(
363
363
  }
364
364
  ```
365
365
 
366
- 問題:參數順序容易錯,擴充困難。
366
+ Problem: Parameter order is error-prone, and extension is difficult.
367
367
 
368
- ### 好作法
368
+ ### Best Practice
369
369
 
370
370
  ```rust
371
371
  #[derive(Debug)]
@@ -435,11 +435,11 @@ fn main() {
435
435
 
436
436
  ---
437
437
 
438
- ## Pattern 9Typestate Pattern
438
+ ## Pattern 9: Typestate Pattern
439
439
 
440
- 用途:把狀態流程放進型別系統,讓錯誤流程無法編譯。
440
+ Purpose: Incorporate state flows into the type system, making invalid state transitions uncompilable.
441
441
 
442
- ### 不好作法
442
+ ### Bad Practice
443
443
 
444
444
  ```rust
445
445
  struct Connection {
@@ -457,7 +457,7 @@ impl Connection {
457
457
  }
458
458
  ```
459
459
 
460
- ### 好作法
460
+ ### Best Practice
461
461
 
462
462
  ```rust
463
463
  struct Disconnected;
@@ -500,22 +500,22 @@ fn main() {
500
500
  }
501
501
  ```
502
502
 
503
- ### 原則
503
+ ### Principle
504
504
 
505
- 狀態流程固定時,Typestate 可以讓錯誤使用方式直接編譯失敗。
505
+ When state flows are fixed, Typestate can cause incorrect usage to fail at compile time.
506
506
 
507
507
  ---
508
508
 
509
- ## Pattern 10Trait 抽象
509
+ ## Pattern 10: Trait Abstraction
510
510
 
511
- Rust polymorphism 主要靠 trait。
511
+ Polymorphism in Rust primarily relies on traits.
512
512
 
513
- | 形式 | 寫法 | 適合 |
513
+ | Form | Syntax | Best For |
514
514
  |---|---|---|
515
- | Static dispatch | `T: Trait` | 編譯期決定型別,效能好 |
516
- | Dynamic dispatch | `dyn Trait` | runtime 才決定實作型別 |
515
+ | Static dispatch | `T: Trait` | Type decided at compile-time; better performance |
516
+ | Dynamic dispatch | `dyn Trait` | Implementation type decided at runtime |
517
517
 
518
- ### Static dispatch
518
+ ### Static Dispatch
519
519
 
520
520
  ```rust
521
521
  trait Repository {
@@ -535,7 +535,7 @@ fn create_user<R: Repository>(repo: &R, name: &str) {
535
535
  }
536
536
  ```
537
537
 
538
- ### Dynamic dispatch
538
+ ### Dynamic Dispatch
539
539
 
540
540
  ```rust
541
541
  trait Repository {
@@ -555,15 +555,15 @@ fn create_user(repo: &dyn Repository, name: &str) {
555
555
  }
556
556
  ```
557
557
 
558
- ### 建議
558
+ ### Recommendation
559
559
 
560
- 預設用 generic `T: Trait`。需要把不同實作放進同一個 collection,或 runtime 注入時,再用 `Box<dyn Trait>` / `&dyn Trait`。
560
+ Default to generic `T: Trait`. Use `Box<dyn Trait>` / `&dyn Trait` only when you need to put different implementations into the same collection or when runtime injection is required.
561
561
 
562
562
  ---
563
563
 
564
- ## Pattern 11Iterator Pattern
564
+ ## Pattern 11: Iterator Pattern
565
565
 
566
- ### 不好作法
566
+ ### Bad Practice
567
567
 
568
568
  ```rust
569
569
  fn active_names(users: Vec<User>) -> Vec<String> {
@@ -579,7 +579,7 @@ fn active_names(users: Vec<User>) -> Vec<String> {
579
579
  }
580
580
  ```
581
581
 
582
- ### 好作法
582
+ ### Best Practice
583
583
 
584
584
  ```rust
585
585
  struct User {
@@ -596,16 +596,15 @@ fn active_names(users: Vec<User>) -> Vec<String> {
596
596
  }
597
597
  ```
598
598
 
599
- ### 原則
599
+ ### Principle
600
600
 
601
- 資料轉換流程適合用 iterator chain。
602
- 但不要為了炫技把簡單邏輯寫到難懂。
601
+ Data transformation flows are well-suited for iterator chains. However, do not over-engineer simple logic to the point of being unreadable.
603
602
 
604
603
  ---
605
604
 
606
- ## Pattern 12RAII / Drop Guard
605
+ ## Pattern 12: RAII / Drop Guard
607
606
 
608
- 用途:DB transaction、file lock、mutex guard、temp file、resource cleanup
607
+ Purpose: DB transactions, file locks, mutex guards, temp files, resource cleanup.
609
608
 
610
609
  ```rust
611
610
  struct Transaction {
@@ -635,31 +634,30 @@ impl Drop for Transaction {
635
634
  fn main() {
636
635
  let tx = Transaction::new();
637
636
 
638
- // 如果中途 return panicDrop 會觸發 rollback
637
+ // If a return or panic occurs midway, Drop will trigger a rollback
639
638
  tx.commit();
640
639
  }
641
640
  ```
642
641
 
643
- ### 原則
642
+ ### Principle
644
643
 
645
- 資源取得與釋放綁在 object lifetime
646
- 值離開 scope 時,由 `Drop` 負責清理。
644
+ Resource acquisition and release are bound to object lifetime. Cleanup is handled by `Drop` when a value leaves scope.
647
645
 
648
646
  ---
649
647
 
650
- ## Pattern 13Smart Pointer 選擇
648
+ ## Pattern 13: Choosing Smart Pointers
651
649
 
652
- | 型別 | 用途 |
650
+ | Type | Purpose |
653
651
  |---|---|
654
- | `Box<T>` | heap allocationrecursive type、trait object ownership |
655
- | `Rc<T>` | 單執行緒 shared ownership |
656
- | `Arc<T>` | 多執行緒 shared ownership |
657
- | `RefCell<T>` | 單執行緒 interior mutabilityruntime borrow check |
658
- | `Mutex<T>` | 多執行緒可變共享資料 |
659
- | `RwLock<T>` | 多讀少寫 |
660
- | `Cow<'a, T>` | 可能借用,也可能需要 clone-on-write |
652
+ | `Box<T>` | Heap allocation, recursive types, trait object ownership |
653
+ | `Rc<T>` | Single-threaded shared ownership |
654
+ | `Arc<T>` | Multi-threaded shared ownership |
655
+ | `RefCell<T>` | Single-threaded interior mutability, runtime borrow check |
656
+ | `Mutex<T>` | Multi-threaded mutable shared data |
657
+ | `RwLock<T>` | Multiple readers, single writer |
658
+ | `Cow<'a, T>` | Clone-on-write; can be either borrowed or owned |
661
659
 
662
- ### 典型範例
660
+ ### Typical Example
663
661
 
664
662
  ```rust
665
663
  use std::sync::{Arc, Mutex};
@@ -687,21 +685,21 @@ fn main() {
687
685
  }
688
686
  ```
689
687
 
690
- ### 注意
688
+ ### Note
691
689
 
692
- `Arc<Mutex<T>>` 很常見,但不是預設答案。可以用 channel / actor ownership 時,通常更清楚。
690
+ `Arc<Mutex<T>>` is common but not the default answer. Using channels or an actor pattern to split ownership is often clearer.
693
691
 
694
692
  ---
695
693
 
696
- ## Pattern 14Message Passing / Actor-like Pattern
694
+ ## Pattern 14: Message Passing / Actor-like Pattern
697
695
 
698
- 適合:
696
+ Suitable for:
699
697
 
700
- - queue worker
701
- - background task
702
- - pipeline
703
- - command processor
704
- - proxy server
698
+ - Queue workers
699
+ - Background tasks
700
+ - Pipelines
701
+ - Command processors
702
+ - Proxy servers
705
703
 
706
704
  ```rust
707
705
  use std::sync::mpsc;
@@ -735,12 +733,12 @@ fn main() {
735
733
 
736
734
  ---
737
735
 
738
- ## Pattern 15Async Bounded Concurrency
736
+ ## Pattern 15: Async Bounded Concurrency
739
737
 
740
- ### 不好作法
738
+ ### Bad Practice
741
739
 
742
740
  ```rust
743
- // 概念示意:大量任務無限制 spawn
741
+ // Conceptual illustration: Spawning tasks without limits
744
742
  for item in items {
745
743
  tokio::spawn(async move {
746
744
  process(item).await;
@@ -748,9 +746,9 @@ for item in items {
748
746
  }
749
747
  ```
750
748
 
751
- 問題:可能打爆 CPU、記憶體、DB connection、API rate limit。
749
+ Problem: Can overwhelm CPU, memory, DB connections, or API rate limits.
752
750
 
753
- ### 好作法
751
+ ### Best Practice
754
752
 
755
753
  ```rust
756
754
  use std::sync::Arc;
@@ -781,9 +779,6 @@ async fn main() {
781
779
  }
782
780
  ```
783
781
 
784
- ### 原則
785
-
786
- Async 任務要有上限。不要無限制 `spawn`。
787
-
788
- ---
782
+ ### Principle
789
783
 
784
+ Async tasks should have a cap. Do not `spawn` without limits.