feat: Add builder design pattern#396
Conversation
WalkthroughDocumentation update: replaces a placeholder with a full Persian explanation of the Builder pattern, adds front matter Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Client
participant Builder as DBBuilder
participant Config as DBConfig
Note over Client,Builder #D3E4CD: Chainable setters (SetHost/SetPort/SetUser/SetDBName/SetFilePath...)
Client->>Builder: NewDBBuilder(driver)
Client->>Builder: SetHost(host)
Client->>Builder: SetPort(port)
Client->>Builder: SetUser(user) / SetDBName(db) / SetFilePath(path)
Note over Builder,Config #FCE9D5: Build validates inputs (driver rules, port range)
Client->>Builder: Build()
Builder->>Builder: validate driver rules (user+dbname or filepath)
Builder->>Builder: validate port range
alt validations pass
Builder->>Config: return configured DBConfig
Client->>Config: use config (connect)
else validations fail
Builder-->>Client: return error
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
Pre-merge checks (3 passed)✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (9)
content/chapter 9/creational patterns/9.1.6-builder.md (9)
6-13: Use proper headings instead of bold; fix minor spacing.Convert the bold section title to a heading (resolves MD036) and remove the extra space after the tooltip in Line 7.
-**مقدمه** +### مقدمه-... ساخت{{< tooltip text="اشیاء" note="Objects" >}} پیچیده ... +... ساخت{{< tooltip text="اشیاء" note="Objects" >}} پیچیده ...
15-32: Normalize section heading and list indentation; avoid tabs.Switch the bold title to a heading and replace tab-indented sub-bullets with spaces to satisfy MD010/MD036.
-**چه زمانی نباید از الگوی Builder استفاده کنیم؟** +### چه زمانی نباید از الگوی Builder استفاده کنیم؟-1. **ساخت اشیاء ساده** - - اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد می کند. +1. **ساخت اشیاء ساده** + - اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند.(Apply the same “two spaces” indentation to the other sub-bullets in Lines 20–31.)
33-34: Remove extra blank lines.Collapse multiple consecutive blank lines to one (fixes MD012).
- - +
62-65: Trim driver input before lowercasing.Avoid treating " mysql " and "mysql" differently.
-func NewDBBuilder(driver string) *DBBuilder { - return &DBBuilder{config: DBConfig{Driver: strings.ToLower(driver)}} +func NewDBBuilder(driver string) *DBBuilder { + d := strings.ToLower(strings.TrimSpace(driver)) + return &DBBuilder{config: DBConfig{Driver: d}} }
85-91: Validate port range (1–65535), not just > 0.Prevents invalid socket values.
-func (b *DBBuilder) SetPort(port int) *DBBuilder { - if port <= 0 { - b.errs = append(b.errs, "port must be > 0") +func (b *DBBuilder) SetPort(port int) *DBBuilder { + if port < 1 || port > 65535 { + b.errs = append(b.errs, "port must be in [1, 65535]") } else { b.config.Port = port } return b }
109-129: Make aggregated error messages readable.Join errors with “; ” instead of printing the raw slice.
- if len(b.errs) > 0 { - return DBConfig{}, fmt.Errorf("invalid configuration: %v", b.errs) - } + if len(b.errs) > 0 { + return DBConfig{}, fmt.Errorf("invalid configuration: %s", strings.Join(b.errs, "; ")) + }
109-129: Clarify builder reuse semantics.If the builder is reused after a successful/failed Build, previously accumulated errors remain in b.errs. Either document single-use semantics or add a Reset() method/clear errs at Build start while re-validating state.
Would you like me to propose a Reset() method and update the prose to state “builder instances are single-use unless reset”?
134-151: Consistent casing and safer output.Use “MySQL”/“SQLite” consistently and avoid printing passwords in %+v dumps.
- // Mysql Example + // MySQL example ... - // Sqlite example + // SQLite exampleOptionally redact before printing:
- fmt.Printf("MySQL config: %+v\n", mysqlCfg) + red := mysqlCfg + red.Password = "****" + fmt.Printf("MySQL config: %+v\n", red)
41-55: Minor Go style: field grouping and comments.Optionally group related fields and add brief doc comments to exported types to align with Go conventions for tutorial code. Low priority.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
content/chapter 9/creational patterns/9.1.6-builder.md(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 9/creational patterns/9.1.6-builder.md
15-15: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
18-18: Hard tabs
Column: 1
(MD010, no-hard-tabs)
21-21: Hard tabs
Column: 1
(MD010, no-hard-tabs)
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
27-27: Hard tabs
Column: 1
(MD010, no-hard-tabs)
28-28: Hard tabs
Column: 1
(MD010, no-hard-tabs)
31-31: Hard tabs
Column: 1
(MD010, no-hard-tabs)
33-33: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
34-34: Multiple consecutive blank lines
Expected: 1; Actual: 3
(MD012, no-multiple-blanks)
42-42: Hard tabs
Column: 1
(MD010, no-hard-tabs)
43-43: Hard tabs
Column: 1
(MD010, no-hard-tabs)
47-47: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
49-49: Hard tabs
Column: 1
(MD010, no-hard-tabs)
50-50: Hard tabs
Column: 1
(MD010, no-hard-tabs)
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
53-53: Hard tabs
Column: 1
(MD010, no-hard-tabs)
54-54: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
66-66: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
67-67: Hard tabs
Column: 1
(MD010, no-hard-tabs)
68-68: Hard tabs
Column: 1
(MD010, no-hard-tabs)
69-69: Hard tabs
Column: 1
(MD010, no-hard-tabs)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
71-71: Hard tabs
Column: 1
(MD010, no-hard-tabs)
72-72: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
76-76: Hard tabs
Column: 1
(MD010, no-hard-tabs)
77-77: Hard tabs
Column: 1
(MD010, no-hard-tabs)
80-80: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
81-81: Hard tabs
Column: 1
(MD010, no-hard-tabs)
82-82: Hard tabs
Column: 1
(MD010, no-hard-tabs)
85-85: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
86-86: Hard tabs
Column: 1
(MD010, no-hard-tabs)
87-87: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Hard tabs
Column: 1
(MD010, no-hard-tabs)
89-89: Hard tabs
Column: 1
(MD010, no-hard-tabs)
90-90: Hard tabs
Column: 1
(MD010, no-hard-tabs)
91-91: Hard tabs
Column: 1
(MD010, no-hard-tabs)
94-94: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
95-95: Hard tabs
Column: 1
(MD010, no-hard-tabs)
96-96: Hard tabs
Column: 1
(MD010, no-hard-tabs)
99-99: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
100-100: Hard tabs
Column: 1
(MD010, no-hard-tabs)
101-101: Hard tabs
Column: 1
(MD010, no-hard-tabs)
104-104: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
105-105: Hard tabs
Column: 1
(MD010, no-hard-tabs)
106-106: Hard tabs
Column: 1
(MD010, no-hard-tabs)
110-110: Hard tabs
Column: 1
(MD010, no-hard-tabs)
111-111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
114-114: Hard tabs
Column: 1
(MD010, no-hard-tabs)
115-115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
116-116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
117-117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
118-118: Hard tabs
Column: 1
(MD010, no-hard-tabs)
119-119: Hard tabs
Column: 1
(MD010, no-hard-tabs)
120-120: Hard tabs
Column: 1
(MD010, no-hard-tabs)
121-121: Hard tabs
Column: 1
(MD010, no-hard-tabs)
122-122: Hard tabs
Column: 1
(MD010, no-hard-tabs)
123-123: Hard tabs
Column: 1
(MD010, no-hard-tabs)
124-124: Hard tabs
Column: 1
(MD010, no-hard-tabs)
126-126: Hard tabs
Column: 1
(MD010, no-hard-tabs)
127-127: Hard tabs
Column: 1
(MD010, no-hard-tabs)
128-128: Hard tabs
Column: 1
(MD010, no-hard-tabs)
129-129: Hard tabs
Column: 1
(MD010, no-hard-tabs)
134-134: Hard tabs
Column: 1
(MD010, no-hard-tabs)
135-135: Hard tabs
Column: 1
(MD010, no-hard-tabs)
136-136: Hard tabs
Column: 1
(MD010, no-hard-tabs)
137-137: Hard tabs
Column: 1
(MD010, no-hard-tabs)
138-138: Hard tabs
Column: 1
(MD010, no-hard-tabs)
139-139: Hard tabs
Column: 1
(MD010, no-hard-tabs)
140-140: Hard tabs
Column: 1
(MD010, no-hard-tabs)
141-141: Hard tabs
Column: 1
(MD010, no-hard-tabs)
143-143: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
146-146: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
152-152: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
158-158: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🔇 Additional comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
36-37: Nice, focused example and clear narrative.The example demonstrates chainable setters, driver-specific validation, and practical usage well for readers.
| {{< play >}} | ||
| package main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strings" | ||
| ) | ||
|
|
||
| type DBConfig struct { | ||
| Driver string | ||
| User string | ||
| Password string | ||
| Host string | ||
| Port int | ||
| DBName string | ||
| FilePath string | ||
| SSLMode string | ||
| } | ||
|
|
||
| type DBBuilder struct { | ||
| config DBConfig | ||
| errs []string | ||
| } | ||
|
|
||
| func NewDBBuilder(driver string) *DBBuilder { | ||
| return &DBBuilder{config: DBConfig{Driver: strings.ToLower(driver)}} | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetUser(user string) *DBBuilder { | ||
| if user == "" { | ||
| b.errs = append(b.errs, "user cannot be empty") | ||
| } else { | ||
| b.config.User = user | ||
| } | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetPassword(pass string) *DBBuilder { | ||
| b.config.Password = pass | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetHost(host string) *DBBuilder { | ||
| b.config.Host = host | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetPort(port int) *DBBuilder { | ||
| if port <= 0 { | ||
| b.errs = append(b.errs, "port must be > 0") | ||
| } else { | ||
| b.config.Port = port | ||
| } | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetDBName(db string) *DBBuilder { | ||
| b.config.DBName = db | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetFilePath(path string) *DBBuilder { | ||
| b.config.FilePath = path | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetSSLMode(mode string) *DBBuilder { | ||
| b.config.SSLMode = mode | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) Build() (DBConfig, error) { | ||
| switch b.config.Driver { | ||
| case "mysql", "postgres", "postgresql": | ||
| if b.config.User == "" { | ||
| b.errs = append(b.errs, "user is required for SQL drivers") | ||
| } | ||
| if b.config.DBName == "" { | ||
| b.errs = append(b.errs, "dbname is required for SQL drivers") | ||
| } | ||
| case "sqlite": | ||
| if b.config.FilePath == "" { | ||
| b.errs = append(b.errs, "file path is required for sqlite") | ||
| } | ||
| default: | ||
| b.errs = append(b.errs, fmt.Sprintf("unknown driver: %s", b.config.Driver)) | ||
| } | ||
|
|
||
| if len(b.errs) > 0 { | ||
| return DBConfig{}, fmt.Errorf("invalid configuration: %v", b.errs) | ||
| } | ||
| return b.config, nil | ||
| } | ||
|
|
||
| func main() { | ||
|
|
||
| // Mysql Example | ||
| mysqlCfg, err := NewDBBuilder("mysql"). | ||
| SetUser("admin"). | ||
| SetPassword("s3cr3t"). | ||
| SetHost("127.0.0.1"). | ||
| SetPort(3306). | ||
| SetDBName("shop"). | ||
| Build() | ||
|
|
||
| if err != nil { | ||
| fmt.Println("MySQL build error:", err) | ||
| } else { | ||
| fmt.Printf("MySQL config: %+v\n", mysqlCfg) | ||
| } | ||
|
|
||
| // Sqlite example | ||
| sqliteCfg, err := NewDBBuilder("sqlite"). | ||
| SetFilePath("/tmp/app.db"). | ||
| Build() | ||
|
|
||
| if err != nil { | ||
| fmt.Println("SQLite build error:", err) | ||
| } else { | ||
| fmt.Printf("SQLite config: %+v\n", sqliteCfg) | ||
| } | ||
| } | ||
|
|
||
| {{< /play >}} |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Silence markdownlint around the custom {{< play >}} block or fence as code.
markdownlint flags tabs and asterisks inside the Go code because the shortcode isn’t recognized as a code fence (MD010/MD037/MD012). Either disable rules around the block or convert to a fenced code block.
Option A — disable rules around the block:
+<!-- markdownlint-disable MD010 MD037 MD012 -->
{{< play >}}
...
{{< /play >}}
+<!-- markdownlint-enable MD010 MD037 MD012 -->Option B — replace shortcode with fenced code (only if site rendering remains acceptable):
-{{< play >}}
+```go
package main
...
}
-
-{{< /play >}}
+```🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
42-42: Hard tabs
Column: 1
(MD010, no-hard-tabs)
43-43: Hard tabs
Column: 1
(MD010, no-hard-tabs)
47-47: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
49-49: Hard tabs
Column: 1
(MD010, no-hard-tabs)
50-50: Hard tabs
Column: 1
(MD010, no-hard-tabs)
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
53-53: Hard tabs
Column: 1
(MD010, no-hard-tabs)
54-54: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
66-66: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
67-67: Hard tabs
Column: 1
(MD010, no-hard-tabs)
68-68: Hard tabs
Column: 1
(MD010, no-hard-tabs)
69-69: Hard tabs
Column: 1
(MD010, no-hard-tabs)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
71-71: Hard tabs
Column: 1
(MD010, no-hard-tabs)
72-72: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
76-76: Hard tabs
Column: 1
(MD010, no-hard-tabs)
77-77: Hard tabs
Column: 1
(MD010, no-hard-tabs)
80-80: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
81-81: Hard tabs
Column: 1
(MD010, no-hard-tabs)
82-82: Hard tabs
Column: 1
(MD010, no-hard-tabs)
85-85: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
86-86: Hard tabs
Column: 1
(MD010, no-hard-tabs)
87-87: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Hard tabs
Column: 1
(MD010, no-hard-tabs)
89-89: Hard tabs
Column: 1
(MD010, no-hard-tabs)
90-90: Hard tabs
Column: 1
(MD010, no-hard-tabs)
91-91: Hard tabs
Column: 1
(MD010, no-hard-tabs)
94-94: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
95-95: Hard tabs
Column: 1
(MD010, no-hard-tabs)
96-96: Hard tabs
Column: 1
(MD010, no-hard-tabs)
99-99: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
100-100: Hard tabs
Column: 1
(MD010, no-hard-tabs)
101-101: Hard tabs
Column: 1
(MD010, no-hard-tabs)
104-104: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
105-105: Hard tabs
Column: 1
(MD010, no-hard-tabs)
106-106: Hard tabs
Column: 1
(MD010, no-hard-tabs)
110-110: Hard tabs
Column: 1
(MD010, no-hard-tabs)
111-111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
114-114: Hard tabs
Column: 1
(MD010, no-hard-tabs)
115-115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
116-116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
117-117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
118-118: Hard tabs
Column: 1
(MD010, no-hard-tabs)
119-119: Hard tabs
Column: 1
(MD010, no-hard-tabs)
120-120: Hard tabs
Column: 1
(MD010, no-hard-tabs)
121-121: Hard tabs
Column: 1
(MD010, no-hard-tabs)
122-122: Hard tabs
Column: 1
(MD010, no-hard-tabs)
123-123: Hard tabs
Column: 1
(MD010, no-hard-tabs)
124-124: Hard tabs
Column: 1
(MD010, no-hard-tabs)
126-126: Hard tabs
Column: 1
(MD010, no-hard-tabs)
127-127: Hard tabs
Column: 1
(MD010, no-hard-tabs)
128-128: Hard tabs
Column: 1
(MD010, no-hard-tabs)
129-129: Hard tabs
Column: 1
(MD010, no-hard-tabs)
134-134: Hard tabs
Column: 1
(MD010, no-hard-tabs)
135-135: Hard tabs
Column: 1
(MD010, no-hard-tabs)
136-136: Hard tabs
Column: 1
(MD010, no-hard-tabs)
137-137: Hard tabs
Column: 1
(MD010, no-hard-tabs)
138-138: Hard tabs
Column: 1
(MD010, no-hard-tabs)
139-139: Hard tabs
Column: 1
(MD010, no-hard-tabs)
140-140: Hard tabs
Column: 1
(MD010, no-hard-tabs)
141-141: Hard tabs
Column: 1
(MD010, no-hard-tabs)
143-143: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
146-146: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
152-152: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
158-158: Hard tabs
Column: 1
(MD010, no-hard-tabs)
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
35-158: Silence markdownlint for the custom {{< play >}} block.Tabs and asterisks inside the Go code trigger MD010/MD037/MD012. Disable around the shortcode. (Same as prior suggestion.)
-{{< play >}} +<!-- markdownlint-disable MD010 MD037 MD012 --> +{{< play >}} ... -{{< /play >}} +{{< /play >}} +<!-- markdownlint-enable MD010 MD037 MD012 -->
🧹 Nitpick comments (9)
content/chapter 9/creational patterns/9.1.6-builder.md (9)
6-6: Fix MD022: blank line after heading.Add one blank line below the heading to satisfy markdownlint.
-### مقدمه +### مقدمه +
15-15: Fix MD022: blank line after heading.Add one blank line below the heading.
-### چه زمانی نباید از الگوی Builder استفاده کنیم؟ +### چه زمانی نباید از الگوی Builder استفاده کنیم؟ +
16-28: Normalize list formatting (MD029, MD004, MD007, MD030, MD032).Use 1/1/1 numbering, “+” for bullets, correct indentation (2 spaces), and surround lists with blank lines.
-1. **ساخت اشیاء ساده** - + - اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. - -2. **ملاحظات عملکردی** - - در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، به ویژه وقتی ساخت شیء مکرر است. - -3. **اشیاء immutable و ساده** - - اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. - -4. **افزایش پیچیدگی کد** - - ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. - - اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد. +1. **ساخت اشیاء ساده** + + اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. + +1. **ملاحظات عملکردی** + + در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، بهویژه وقتی ساخت شیء مکرر است. + +1. **اشیاء immutable و ساده** + + اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. + +1. **افزایش پیچیدگی کد** + + ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. + + اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد.
29-31: Start a new list with consistent style (MD032, MD004).Keep “1.” numbering and “+” for sub-points.
-1. **وابستگی زیاد به محصول** - - اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد. +1. **وابستگی زیاد به محصول** + + اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد.
64-71: Trim username and keep error if empty.Avoid accepting whitespace-only users.
func (b *DBBuilder) SetUser(user string) *DBBuilder { - if user == "" { + u := strings.TrimSpace(user) + if u == "" { b.errs = append(b.errs, "user cannot be empty") } else { - b.config.User = user + b.config.User = u } return b }
102-105: Validate SSL mode only when applicable.Optionally restrict values (e.g., disable, require, verify-ca, verify-full) for postgres to prevent invalid configs.
107-128: Reset error accumulator per build to avoid stale/duplicated errors.Errors from previous Build() calls can leak into the next one.
func (b *DBBuilder) Build() (DBConfig, error) { + // reset per-build to avoid leaking/duplicating previous errors + b.errs = nil switch b.config.Driver {
141-146: Avoid printing secrets in examples.Printing the whole struct exposes Password. Mask or omit it.
- fmt.Printf("MySQL config: %+v\n", mysqlCfg) + fmt.Printf( + "MySQL config: driver=%s user=%s host=%s port=%d db=%s\n", + mysqlCfg.Driver, mysqlCfg.User, mysqlCfg.Host, mysqlCfg.Port, mysqlCfg.DBName, + )
152-156: Consistent safe output for SQLite example.Avoid dumping full struct.
- fmt.Printf("SQLite config: %+v\n", sqliteCfg) + fmt.Printf("SQLite config: driver=%s file=%s\n", sqliteCfg.Driver, sqliteCfg.FilePath)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
content/chapter 9/creational patterns/9.1.6-builder.md(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 9/creational patterns/9.1.6-builder.md
6-6: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
15-15: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
16-16: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
16-16: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
17-17: Unordered list style
Expected: plus; Actual: dash
(MD004, ul-style)
17-17: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
17-17: Unordered list indentation
Expected: 2; Actual: 5
(MD007, ul-indent)
17-17: Spaces after list markers
Expected: 1; Actual: 2
(MD030, list-marker-space)
17-17: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
19-19: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1
(MD029, ol-prefix)
19-19: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
20-20: Unordered list style
Expected: plus; Actual: dash
(MD004, ul-style)
20-20: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
20-20: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
22-22: Ordered list item prefix
Expected: 1; Actual: 3; Style: 1/1/1
(MD029, ol-prefix)
22-22: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
23-23: Unordered list style
Expected: plus; Actual: dash
(MD004, ul-style)
23-23: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
23-23: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
25-25: Ordered list item prefix
Expected: 1; Actual: 4; Style: 1/1/1
(MD029, ol-prefix)
25-25: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
26-26: Unordered list style
Expected: plus; Actual: dash
(MD004, ul-style)
26-26: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
26-26: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
27-27: Unordered list style
Expected: plus; Actual: dash
(MD004, ul-style)
27-27: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
29-29: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
30-30: Unordered list style
Expected: plus; Actual: dash
(MD004, ul-style)
30-30: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
30-30: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
39-39: Hard tabs
Column: 1
(MD010, no-hard-tabs)
40-40: Hard tabs
Column: 1
(MD010, no-hard-tabs)
44-44: Hard tabs
Column: 1
(MD010, no-hard-tabs)
45-45: Hard tabs
Column: 1
(MD010, no-hard-tabs)
46-46: Hard tabs
Column: 1
(MD010, no-hard-tabs)
47-47: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
49-49: Hard tabs
Column: 1
(MD010, no-hard-tabs)
50-50: Hard tabs
Column: 1
(MD010, no-hard-tabs)
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
55-55: Hard tabs
Column: 1
(MD010, no-hard-tabs)
56-56: Hard tabs
Column: 1
(MD010, no-hard-tabs)
60-60: Hard tabs
Column: 1
(MD010, no-hard-tabs)
61-61: Hard tabs
Column: 1
(MD010, no-hard-tabs)
64-64: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
65-65: Hard tabs
Column: 1
(MD010, no-hard-tabs)
66-66: Hard tabs
Column: 1
(MD010, no-hard-tabs)
67-67: Hard tabs
Column: 1
(MD010, no-hard-tabs)
68-68: Hard tabs
Column: 1
(MD010, no-hard-tabs)
69-69: Hard tabs
Column: 1
(MD010, no-hard-tabs)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
73-73: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
74-74: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
78-78: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
79-79: Hard tabs
Column: 1
(MD010, no-hard-tabs)
80-80: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
84-84: Hard tabs
Column: 1
(MD010, no-hard-tabs)
85-85: Hard tabs
Column: 1
(MD010, no-hard-tabs)
86-86: Hard tabs
Column: 1
(MD010, no-hard-tabs)
87-87: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Hard tabs
Column: 1
(MD010, no-hard-tabs)
89-89: Hard tabs
Column: 1
(MD010, no-hard-tabs)
92-92: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
93-93: Hard tabs
Column: 1
(MD010, no-hard-tabs)
94-94: Hard tabs
Column: 1
(MD010, no-hard-tabs)
97-97: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
98-98: Hard tabs
Column: 1
(MD010, no-hard-tabs)
99-99: Hard tabs
Column: 1
(MD010, no-hard-tabs)
102-102: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
103-103: Hard tabs
Column: 1
(MD010, no-hard-tabs)
104-104: Hard tabs
Column: 1
(MD010, no-hard-tabs)
108-108: Hard tabs
Column: 1
(MD010, no-hard-tabs)
109-109: Hard tabs
Column: 1
(MD010, no-hard-tabs)
110-110: Hard tabs
Column: 1
(MD010, no-hard-tabs)
111-111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
114-114: Hard tabs
Column: 1
(MD010, no-hard-tabs)
115-115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
116-116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
117-117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
118-118: Hard tabs
Column: 1
(MD010, no-hard-tabs)
119-119: Hard tabs
Column: 1
(MD010, no-hard-tabs)
120-120: Hard tabs
Column: 1
(MD010, no-hard-tabs)
121-121: Hard tabs
Column: 1
(MD010, no-hard-tabs)
122-122: Hard tabs
Column: 1
(MD010, no-hard-tabs)
124-124: Hard tabs
Column: 1
(MD010, no-hard-tabs)
125-125: Hard tabs
Column: 1
(MD010, no-hard-tabs)
126-126: Hard tabs
Column: 1
(MD010, no-hard-tabs)
127-127: Hard tabs
Column: 1
(MD010, no-hard-tabs)
132-132: Hard tabs
Column: 1
(MD010, no-hard-tabs)
133-133: Hard tabs
Column: 1
(MD010, no-hard-tabs)
134-134: Hard tabs
Column: 1
(MD010, no-hard-tabs)
135-135: Hard tabs
Column: 1
(MD010, no-hard-tabs)
136-136: Hard tabs
Column: 1
(MD010, no-hard-tabs)
137-137: Hard tabs
Column: 1
(MD010, no-hard-tabs)
138-138: Hard tabs
Column: 1
(MD010, no-hard-tabs)
139-139: Hard tabs
Column: 1
(MD010, no-hard-tabs)
141-141: Hard tabs
Column: 1
(MD010, no-hard-tabs)
142-142: Hard tabs
Column: 1
(MD010, no-hard-tabs)
143-143: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
148-148: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
152-152: Hard tabs
Column: 1
(MD010, no-hard-tabs)
153-153: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
37-38: Good: lint suppression around the Hugo play block is in place.Disabling MD010/MD037/MD012 for the shortcode resolves earlier tab/emphasis noise inside the Go snippet.
Also applies to: 161-162
🧹 Nitpick comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
41-44: Optional: use errors.Join with []error for richer validation reporting.If you want idiomatic multi-error reporting (Go 1.20+), switch errs to []error and return errors.Join(errs...). This complements centralized validation.
import ( "fmt" + "errors" "strings" ) @@ type DBBuilder struct { config DBConfig - errs []string + errs []error } @@ - return DBConfig{}, fmt.Errorf("invalid configuration: %s", strings.Join(b.errs, "; ")) + return DBConfig{}, errors.Join(b.errs...) }And replace appends accordingly, e.g.,
- b.errs = append(b.errs, "user is required for SQL drivers") + b.errs = append(b.errs, errors.New("user is required for SQL drivers"))Also applies to: 57-60, 110-131
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
content/chapter 9/creational patterns/9.1.6-builder.md(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 9/creational patterns/9.1.6-builder.md
18-18: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
19-19: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
19-19: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
21-21: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1
(MD029, ol-prefix)
21-21: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
22-22: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
22-22: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
24-24: Ordered list item prefix
Expected: 1; Actual: 3; Style: 1/1/1
(MD029, ol-prefix)
24-24: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
25-25: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
25-25: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
27-27: Ordered list item prefix
Expected: 1; Actual: 4; Style: 1/1/1
(MD029, ol-prefix)
27-27: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
28-28: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
28-28: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
29-29: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
31-31: Ordered list item prefix
Expected: 1; Actual: 5; Style: 1/1/1
(MD029, ol-prefix)
31-31: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
32-32: Unordered list indentation
Expected: 0; Actual: 2
(MD007, ul-indent)
32-32: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
لطفا سعی کنید طبق این ساختار این بخش را بنویسید درخصوص الگوها: https://book.gofarsi.ir/chapter-9/concurrency-patterns/go-concurrency-pattern-wait-for-result/
|
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
content/chapter 9/creational patterns/9.1.6-builder.md (2)
5-6: Add a blank line after front matter to satisfy MD022.--- title: '9.1.6 الگو Builder' slug: go-builder-pattern weight: 172006 --- + ### توضیحات
170-191: Fix ordered list style and sub-item indentation; ensure blank lines around the list (MD029/MD007/MD032).### چه زمانی نباید از الگوی Builder استفاده کنیم؟ - -1. **ساخت اشیاء ساده** - - + اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. - -2. **ملاحظات عملکردی** - - + در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، بهویژه وقتی ساخت شیء مکرر است. - -3. **اشیاء immutable و ساده** - - + اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. - -4. **افزایش پیچیدگی کد** - - + ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. - + اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد. - -5. **وابستگی زیاد به محصول** - - + اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد. + +1. **ساخت اشیاء ساده** + + اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. + +1. **ملاحظات عملکردی** + + در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، بهویژه وقتی ساخت شیء مکرر است. + +1. **اشیاء immutable و ساده** + + اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. + +1. **افزایش پیچیدگی کد** + + ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. + + اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد. + +1. **وابستگی زیاد به محصول** + + اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد. +
🧹 Nitpick comments (3)
content/chapter 9/creational patterns/9.1.6-builder.md (3)
91-119: Minor builder cleanup: reset errs with nil and consider validating SSLMode for Postgres.func (b *DBBuilder) Build() (DBConfig, error) { - // reset previous validation state to avoid stale errors on repeated Build calls - b.errs = b.errs[:0] + // reset previous validation state to avoid stale errors on repeated Build calls + b.errs = nil @@ - case "mysql", "postgres", "postgresql": + case "mysql", "postgres", "postgresql": if b.config.User == "" { b.errs = append(b.errs, "user is required for SQL drivers") } if b.config.DBName == "" { b.errs = append(b.errs, "dbname is required for SQL drivers") } + // optional: validate SSL mode for postgres variants if set + if (b.config.Driver == "postgres" || b.config.Driver == "postgresql") && b.config.SSLMode != "" { + switch b.config.SSLMode { + case "disable", "require", "verify-ca", "verify-full": + default: + b.errs = append(b.errs, "invalid sslmode for postgres") + } + }
162-174: Persian typography nits.Prefer joined forms: «کاربردها», «پارامترهای», and using ZWNJ in compounds like «UIهای». Keeps editorial consistency.
18-18: Optional: Omit angle brackets from the UML shortcode URLcontent/chapter 9/creational patterns/9.1.6-builder.md:18
-{{< uml url="<https://viewer.diagrams.net/?tags=%7B%7D&lightbox=1…#R%3Cmxfile%3E…%3E>" >}} +{{< uml url="https://viewer.diagrams.net/?tags=%7B%7D&lightbox=1…#R%3Cmxfile%3E…%3E" >}}Removing the surrounding
<and>ensures the raw URL is passed correctly into the shortcode.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
content/chapter 9/creational patterns/9.1.6-builder.md(1 hunks)
🔇 Additional comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
6-21: Structure matches reviewer’s requested outline.You’ve covered توضیحات، دیاگرام، نمونه کد با توضیح، و کاربردها per the comment. Nice.
Also applies to: 160-170
| @@ -4,4 +4,186 @@ slug: go-builder-pattern | |||
| weight: 172006 | |||
There was a problem hiding this comment.
| weight: 172006 | |
| weight: 172006 | |
| mermaid: true |
|
|
||
| ### دیاگرام | ||
|
|
||
| {{< uml url="<https://mermaidchart.com/play?utm_source=mermaid_live_editor&utm_medium=share#pako:eNp9U02PmzAQ_SuW98JKNE0I2QQf9hDYVS-NVqp6qbg4eEKsgk0He_sR5b_XNhClq2Y5WB77zXvPw8yJVloAZbSHHxZUBYXkNfK2VIRwa7Sy7R4wRJXRSPJGgjI-7jgaWcmOK0O2VjYCkPCelLTYjmFJ3-JyrQ6ynmBD5FEet9MGiH6FSSOeSO-K5VOaF4zkRy4V3zdAejAGsPdpA_jD4-MIZ2QHPy8WIoHSUd7_H_kFzCfdm-joltuQF40m6txyG_K1d1K2f0-o2O54C5HY34Y8ywZeuDlGnVvu31ZlRMZjDe-e86esWLHhnLzyRgpuoCdSddbcKE3YRMHBeHZ9O3GQoWgEbeP4wrs-ir1y9onrgINzORp8n8WXjCBXNQxP4Y2ZLqVWvWuMPti8ZhkexwiCsahIFUKLIMilXULG5WlTgjM5okkEs3oW-0hBNfw0aNz1tfaBy-Zfbc8VSC_igKhD54MSpaIxrVEKygxaiGkL2HIf0pOHlNQcoYWSMrcVHL_7rj67HNf237RupzTUtj5SduDOUExt5ws1TtzlFJ0eYK6tMpQlSeCg7ER_uWiTztbJYvOQrLMke9isVzH9TdkymyWr-XyxSNN0ni0255j-CaLzmYPM3Zcs11m2SNdpTEFIN8ifh6kPw3_-CwjCWZE>" >}} |
There was a problem hiding this comment.
لطفا کد mermaid را بصورت زیر اضافه کنید:
{{< mermaid >}}
# put here...
{{< /mermaid >}}
| --- | ||
|
|
||
| الگو Builder... No newline at end of file | ||
| ### توضیحات |
There was a problem hiding this comment.
| ### توضیحات | |
| ## 9.1.6.1 توضیحات |
| الگوی بیلدر وقتی کمک کننده است که بخواهید یک شیء پیچیده با پارامترهای زیاد را مرحله به مرحله و خواناتر بسازید، بدون اینکه درگیر سازندههای طولانی و گیجکننده بشوید. | ||
| {{< /hint >}} | ||
|
|
||
| ### دیاگرام |
There was a problem hiding this comment.
| ### دیاگرام | |
| ## 9.1.6.2 دیاگرام |
|
|
||
| {{< uml url="<https://mermaidchart.com/play?utm_source=mermaid_live_editor&utm_medium=share#pako:eNp9U02PmzAQ_SuW98JKNE0I2QQf9hDYVS-NVqp6qbg4eEKsgk0He_sR5b_XNhClq2Y5WB77zXvPw8yJVloAZbSHHxZUBYXkNfK2VIRwa7Sy7R4wRJXRSPJGgjI-7jgaWcmOK0O2VjYCkPCelLTYjmFJ3-JyrQ6ynmBD5FEet9MGiH6FSSOeSO-K5VOaF4zkRy4V3zdAejAGsPdpA_jD4-MIZ2QHPy8WIoHSUd7_H_kFzCfdm-joltuQF40m6txyG_K1d1K2f0-o2O54C5HY34Y8ywZeuDlGnVvu31ZlRMZjDe-e86esWLHhnLzyRgpuoCdSddbcKE3YRMHBeHZ9O3GQoWgEbeP4wrs-ir1y9onrgINzORp8n8WXjCBXNQxP4Y2ZLqVWvWuMPti8ZhkexwiCsahIFUKLIMilXULG5WlTgjM5okkEs3oW-0hBNfw0aNz1tfaBy-Zfbc8VSC_igKhD54MSpaIxrVEKygxaiGkL2HIf0pOHlNQcoYWSMrcVHL_7rj67HNf237RupzTUtj5SduDOUExt5ws1TtzlFJ0eYK6tMpQlSeCg7ER_uWiTztbJYvOQrLMke9isVzH9TdkymyWr-XyxSNN0ni0255j-CaLzmYPM3Zcs11m2SNdpTEFIN8ifh6kPw3_-CwjCWZE>" >}} | ||
|
|
||
| ### نمونه کد: ساخت پیکربندی پایگاه داده با Builder |
There was a problem hiding this comment.
| ### نمونه کد: ساخت پیکربندی پایگاه داده با Builder | |
| ## 9.1.6.3 مثال |
|
|
||
| وقتش رسیده که یک نمونهی واقعی را ببینیم. در کدی که در ادامه میآید، ما یک ساختار `DBConfig` داریم که تنظیمات اتصال به پایگاه داده را نگه میدارد. یک **Builder** به نام `DBBuilder` ایجاد کردهایم که به ما اجازه میدهد با استفاده از متدهای زنجیرهای (`SetUser`, `SetHost`, …) تنها فیلدهای مورد نیاز خود را مقداردهی کنیم و در پایان با فراخوانی `Build()` شیء نهایی را تحویل بگیریم. | ||
|
|
||
| <!-- markdownlint-disable MD010 MD037 MD012 --> |
There was a problem hiding this comment.
| <!-- markdownlint-disable MD010 MD037 MD012 --> |
Remove it
| } | ||
|
|
||
| {{< /play >}} | ||
| <!-- markdownlint-enable MD010 MD037 MD012 --> |
There was a problem hiding this comment.
| <!-- markdownlint-enable MD010 MD037 MD012 --> |
|
|
||
| در تابع `main` دو مثال واقعی وجود دارد: یکی برای MySQL که تمام فیلدهای مرتبط پر شده و دیگری برای SQLite که تنها مسیر فایل مشخص شده است. این روش باعث میشود کد خوانا، قابل گسترش و ایمن باشد و ساخت پیکربندیهای مختلف پایگاه داده ساده و منعطف انجام شود. این پیادهسازی در عین سادگی نشان میدهد که چگونه میتوان با استفاده از الگوی Builder از پیچیدگیهای ایجاد اشیای بزرگ و متنوع کاست. | ||
|
|
||
| ### کاربرد ها |
There was a problem hiding this comment.
| ### کاربرد ها | |
| ## 9.1.6.4 کاربرد ها |
| 2. فرم یا UIهای پیچیده | ||
| 3. {{< tooltip text="لاگر" note="Logger" >}} | ||
|
|
||
| ### چه زمانی نباید از الگوی Builder استفاده کنیم؟ |
There was a problem hiding this comment.
| ### چه زمانی نباید از الگوی Builder استفاده کنیم؟ | |
| ### 9.1.6.4.1 چه زمانی نباید از الگوی Builder استفاده کنیم؟ |
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
49-173: Silence markdownlint around the {{< play >}} block (MD010/MD037).Tabs and asterisks in Go code are linted because shortcode isn’t a fence.
Apply:
+<!-- markdownlint-disable MD010 MD037 --> {{< play >}} ... {{< /play >}} +<!-- markdownlint-enable MD010 MD037 -->
🧹 Nitpick comments (4)
content/chapter 9/creational patterns/9.1.6-builder.md (4)
114-116: Prefer clearing errs with nil to drop backing array.
b.errs = nilavoids retaining capacity across builds.Apply:
- b.errs = b.errs[:0] + b.errs = nil
125-127: Accept common alias “sqlite3”.Many Go drivers use “sqlite3”. Support both.
Apply:
- case "sqlite": + case "sqlite", "sqlite3":
27-41: Localize Mermaid labels for consistency (optional).Diagram text is English; rest of doc is Persian.
Apply:
- Note over Client,Builder #D3E4CD: Chainable setters + Note over Client,Builder #D3E4CD: Setterهای زنجیرهای ... - Note over Builder,Config #FCE9D5: Build validates inputs + Note over Builder,Config #FCE9D5: اعتبارسنجی ورودیها در Build ... - Builder->>Builder: validate driver rules (user/dbname or filepath) + Builder->>Builder: بررسی قوانین هر درایور (کاربر/نامپایگاهداده یا مسیر فایل) - Builder->>Builder: validate port range + Builder->>Builder: بررسی بازه پورت - alt validations pass + alt اعتبارسنجی موفق - Builder->>Config: return configured DBConfig + Builder->>Config: بازگشت DBConfig پیکربندیشده - Client->>Config: use config (e.g., connect) + Client->>Config: استفاده از تنظیمات (مثلاً اتصال) - else validations fail + else اعتبارسنجی ناموفق - Builder-->>Client: return error + Builder-->>Client: بازگشت خطا
184-184: Fix double space.Minor typography nit.
Apply:
-در مواردی که اشیاء ما پارامترهای زیادی دارند و پیچیده هستند، +در مواردی که اشیاء ما پارامترهای زیادی دارند و پیچیده هستند،
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
content/chapter 9/creational patterns/9.1.6-builder.md(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 9/creational patterns/9.1.6-builder.md
20-20: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
44-44: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
53-53: Hard tabs
Column: 1
(MD010, no-hard-tabs)
54-54: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
60-60: Hard tabs
Column: 1
(MD010, no-hard-tabs)
61-61: Hard tabs
Column: 1
(MD010, no-hard-tabs)
62-62: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
64-64: Hard tabs
Column: 1
(MD010, no-hard-tabs)
65-65: Hard tabs
Column: 1
(MD010, no-hard-tabs)
69-69: Hard tabs
Column: 1
(MD010, no-hard-tabs)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
74-74: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
78-78: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
79-79: Hard tabs
Column: 1
(MD010, no-hard-tabs)
80-80: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
84-84: Hard tabs
Column: 1
(MD010, no-hard-tabs)
85-85: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
89-89: Hard tabs
Column: 1
(MD010, no-hard-tabs)
90-90: Hard tabs
Column: 1
(MD010, no-hard-tabs)
93-93: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
98-98: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
99-99: Hard tabs
Column: 1
(MD010, no-hard-tabs)
100-100: Hard tabs
Column: 1
(MD010, no-hard-tabs)
103-103: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
104-104: Hard tabs
Column: 1
(MD010, no-hard-tabs)
105-105: Hard tabs
Column: 1
(MD010, no-hard-tabs)
108-108: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
109-109: Hard tabs
Column: 1
(MD010, no-hard-tabs)
110-110: Hard tabs
Column: 1
(MD010, no-hard-tabs)
146-146: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
148-148: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
152-152: Hard tabs
Column: 1
(MD010, no-hard-tabs)
153-153: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
158-158: Hard tabs
Column: 1
(MD010, no-hard-tabs)
159-159: Hard tabs
Column: 1
(MD010, no-hard-tabs)
161-161: Hard tabs
Column: 1
(MD010, no-hard-tabs)
162-162: Hard tabs
Column: 1
(MD010, no-hard-tabs)
163-163: Hard tabs
Column: 1
(MD010, no-hard-tabs)
164-164: Hard tabs
Column: 1
(MD010, no-hard-tabs)
166-166: Hard tabs
Column: 1
(MD010, no-hard-tabs)
167-167: Hard tabs
Column: 1
(MD010, no-hard-tabs)
168-168: Hard tabs
Column: 1
(MD010, no-hard-tabs)
169-169: Hard tabs
Column: 1
(MD010, no-hard-tabs)
170-170: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🔇 Additional comments (3)
content/chapter 9/creational patterns/9.1.6-builder.md (3)
8-16: Structure and intro read well.Section 9.1.6.1 matches the requested structure and clearly motivates Builder.
5-5: Confirm front matter type for mermaid.If the site expects boolean, use unquoted
true.Apply:
-mermaid: "true" +mermaid: truePlease confirm with the site’s Hugo config; I can adjust if strings are required.
21-42: Diagram block matches requested wrapper.Mermaid is correctly wrapped with
{{< mermaid >}} ... {{< /mermaid >}}.
| type DBConfig struct { | ||
| Driver string | ||
| User string | ||
| Password string | ||
| Host string | ||
| Port int | ||
| DBName string | ||
| FilePath string | ||
| SSLMode string | ||
| } | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Redact secrets when printing config.
Printing %+v leaks Password in logs. Implement Stringer to omit sensitive fields.
Apply:
type DBConfig struct {
Driver string
User string
Password string
Host string
Port int
DBName string
FilePath string
SSLMode string
}
+// String implements fmt.Stringer and redacts sensitive fields.
+func (c DBConfig) String() string {
+ return fmt.Sprintf(
+ "DBConfig{Driver:%s, User:%s, Host:%s, Port:%d, DBName:%s, FilePath:%s, SSLMode:%s}",
+ c.Driver, c.User, c.Host, c.Port, c.DBName, c.FilePath, c.SSLMode,
+ )
+}Usage can stay as fmt.Printf("MySQL config: %+v\n", mysqlCfg); fmt will call String().
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| type DBConfig struct { | |
| Driver string | |
| User string | |
| Password string | |
| Host string | |
| Port int | |
| DBName string | |
| FilePath string | |
| SSLMode string | |
| } | |
| type DBConfig struct { | |
| Driver string | |
| User string | |
| Password string | |
| Host string | |
| Port int | |
| DBName string | |
| FilePath string | |
| SSLMode string | |
| } | |
| // String implements fmt.Stringer and redacts sensitive fields. | |
| func (c DBConfig) String() string { | |
| return fmt.Sprintf( | |
| "DBConfig{Driver:%s, User:%s, Host:%s, Port:%d, DBName:%s, FilePath:%s, SSLMode:%s}", | |
| c.Driver, c.User, c.Host, c.Port, c.DBName, c.FilePath, c.SSLMode, | |
| ) | |
| } |
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
60-60: Hard tabs
Column: 1
(MD010, no-hard-tabs)
61-61: Hard tabs
Column: 1
(MD010, no-hard-tabs)
62-62: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
64-64: Hard tabs
Column: 1
(MD010, no-hard-tabs)
65-65: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In content/chapter 9/creational patterns/9.1.6-builder.md around lines 57 to 67,
the DBConfig struct is being printed with fmt.Printf("%+v") which leaks
sensitive fields (Password, FilePath); implement the fmt.Stringer interface for
DBConfig (e.g., add a String() string receiver) that returns a formatted
representation omitting or redacting Password and any other secrets but
preserving the other fields so existing fmt.Printf("...%+v...", cfg) continues
to produce a readable output without exposing secrets.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
content/chapter 9/creational patterns/9.1.6-builder.md (1)
55-64: Avoid leaking secrets when printing config. Implement Stringer and keep using fmt.
fmt.Printf("%+v", cfg)will print Password. Provide a String() to redact sensitive fields; fmt will call it.type DBConfig struct { Driver string User string Password string Host string Port int DBName string FilePath string SSLMode string } +// String redacts sensitive fields to avoid leaking secrets in logs. +func (c DBConfig) String() string { + return fmt.Sprintf( + "DBConfig{Driver:%s, User:%s, Host:%s, Port:%d, DBName:%s, FilePath:%s, SSLMode:%s, Password:%s}", + c.Driver, c.User, c.Host, c.Port, c.DBName, c.FilePath, c.SSLMode, "[REDACTED]", + ) +}Also applies to: 153-157, 167-167
🧹 Nitpick comments (5)
content/chapter 9/creational patterns/9.1.6-builder.md (5)
5-5: YAML: use boolean for mermaid, not a string.Hugo front matter should be
mermaid: true(unquoted).-mermaid: "true" +mermaid: true
184-187: Normalize list numbering and indentation (MD029/MD007) and keep consistent “+” bullets.Use 1/1/1 for ordered lists and two-space-indented “+” for sub-items.
-1. کانکشن های دیتابیس -2. فرم یا UIهای پیچیده -3. {{< tooltip text="لاگر" note="Logger" >}} +1. کانکشنهای دیتابیس +1. فرم یا UIهای پیچیده +1. {{< tooltip text="لاگر" note="Logger" >}} -1. **ساخت اشیاء ساده** - - + اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. - -2. **ملاحظات عملکردی** - - + در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، بهویژه وقتی ساخت شیء مکرر است. - -3. **اشیاء immutable و ساده** - - + اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. - -4. **افزایش پیچیدگی کد** - - + ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. - + اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد. - -5. **وابستگی زیاد به محصول** - - + اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد. +1. **ساخت اشیاء ساده** + + اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. +1. **ملاحظات عملکردی** + + در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، بهویژه وقتی ساخت شیء مکرر است. +1. **اشیاء immutable و ساده** + + اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. +1. **افزایش پیچیدگی کد** + + ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. + + اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد. +1. **وابستگی زیاد به محصول** + + اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد.Also applies to: 190-209
111-140: Builder validation is clean and centralized — nice. Minor nit: consistent indentation.Logic is sound (resets errs; per-driver checks; port range). Fix a few mixed-space indent lines (e.g., Lines 91–94, 111–114) to keep Go code uniformly indented for readability in the rendered page.
Also applies to: 76-109, 91-94
47-171: Optional: provide runnable Go Playground alternative for contributors.If the site supports it, consider adding a fenced Go block copy below the play block for quick copy/paste while keeping the shortcode for live rendering.
47-48: Wrap the Hugo play shortcode with markdownlint-disable/enable for MD010 and MD037Surround lines 47–171 with:
--- content/chapter 9/creational patterns/9.1.6-builder.md @@ -46,7 +46,9 -{{< play >}} +<!-- markdownlint-disable MD010 MD037 --> +{{< play >}} @@ -171,7 +173,8 -{{< /play >}} +{{< /play >}} +<!-- markdownlint-enable MD010 MD037 -->Re-run
npx -y markdownlint-cli2 "content/chapter 9/creational patterns/9.1.6-builder.md"to confirm no MD010/MD037 errors inside the play block.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
content/chapter 9/creational patterns/9.1.6-builder.md(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 9/creational patterns/9.1.6-builder.md
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
56-56: Hard tabs
Column: 1
(MD010, no-hard-tabs)
57-57: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
60-60: Hard tabs
Column: 1
(MD010, no-hard-tabs)
61-61: Hard tabs
Column: 1
(MD010, no-hard-tabs)
62-62: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
67-67: Hard tabs
Column: 1
(MD010, no-hard-tabs)
68-68: Hard tabs
Column: 1
(MD010, no-hard-tabs)
72-72: Hard tabs
Column: 1
(MD010, no-hard-tabs)
73-73: Hard tabs
Column: 1
(MD010, no-hard-tabs)
76-76: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
77-77: Hard tabs
Column: 1
(MD010, no-hard-tabs)
78-78: Hard tabs
Column: 1
(MD010, no-hard-tabs)
81-81: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
82-82: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Hard tabs
Column: 1
(MD010, no-hard-tabs)
86-86: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
87-87: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Hard tabs
Column: 1
(MD010, no-hard-tabs)
91-91: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
96-96: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
97-97: Hard tabs
Column: 1
(MD010, no-hard-tabs)
98-98: Hard tabs
Column: 1
(MD010, no-hard-tabs)
101-101: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
102-102: Hard tabs
Column: 1
(MD010, no-hard-tabs)
103-103: Hard tabs
Column: 1
(MD010, no-hard-tabs)
106-106: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
107-107: Hard tabs
Column: 1
(MD010, no-hard-tabs)
108-108: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
146-146: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
148-148: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
153-153: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
159-159: Hard tabs
Column: 1
(MD010, no-hard-tabs)
160-160: Hard tabs
Column: 1
(MD010, no-hard-tabs)
161-161: Hard tabs
Column: 1
(MD010, no-hard-tabs)
162-162: Hard tabs
Column: 1
(MD010, no-hard-tabs)
164-164: Hard tabs
Column: 1
(MD010, no-hard-tabs)
165-165: Hard tabs
Column: 1
(MD010, no-hard-tabs)
166-166: Hard tabs
Column: 1
(MD010, no-hard-tabs)
167-167: Hard tabs
Column: 1
(MD010, no-hard-tabs)
168-168: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🔇 Additional comments (3)
content/chapter 9/creational patterns/9.1.6-builder.md (3)
8-16: Structure matches requested template — good job.Sections for توضیحات، دیاگرام، مثال، کاربردها are present and ordered.
Also applies to: 18-19, 43-46, 180-188
20-41: Mermaid block usage is correct per maintainer’s guidance.Shortcode wrapper is in place and separated by single blank lines.
1-6: Front matter: accept reviewer’s suggested weight; title/slug look fine.Only change needed is mermaid boolean noted above.
| --- | ||
| title: '9.1.6 الگو Builder' | ||
| title: 9.1.6 الگو Builder | ||
| slug: go-builder-pattern | ||
| weight: 172006 | ||
| mermaid: "true" | ||
| --- | ||
|
|
||
| الگو Builder... No newline at end of file | ||
| ## 9.1.6.1 توضیحات | ||
|
|
||
| در دنیای طراحی نرمافزار، یکی از چالشهای رایج، **ساخت{{< tooltip text="اشیاء" note="Objects" >}} پیچیده با پارامترهای متعدد و متنوع** است. فرض کنید قصد دارید یک شیء پیکربندی برای اتصال به {{< tooltip text="پایگاه داده" note="Database" >}} بسازید. بسته به نوع پایگاه داده ای که می خواهید (MySQL، PostgreSQL، SQLite و …)، ممکن است به مجموعهای متفاوت از پارامترها نیاز داشته باشید: نام کاربری و گذرواژه، میزبان و پورت، نام پایگاه داده یا حتی مسیر فایل. اگر بخواهیم همهی این موارد را با یک {{< tooltip text="سازنده" note="Constructor" >}} ساده مدیریت کنیم، به زودی با توابعی پر از پارامترهای اختیاری و ترتیبهای گیجکننده مواجه خواهیم شد. | ||
|
|
||
| اینجاست که **الگوی Builder** وارد عمل میشود. این الگو با تفکیک فرآیند ساخت از شیء نهایی، به ما اجازه میدهد تا اشیاء را به صورت **گام به گام، خوانا و قابل انعطاف** بسازیم. با استفاده از این الگو نگهداری کد سادهتر است و آن را برای توسعهدهندگان دیگر قابل فهمتر میکند. | ||
|
|
||
| {{< hint info >}} | ||
| الگوی بیلدر وقتی کمک کننده است که بخواهید یک شیء پیچیده با پارامترهای زیاد را مرحله به مرحله و خواناتر بسازید، بدون اینکه درگیر سازندههای طولانی و گیجکننده بشوید. | ||
| {{< /hint >}} | ||
|
|
||
| ## 9.1.6.2 دیاگرام | ||
|
|
||
| {{< mermaid >}} | ||
| sequenceDiagram | ||
| autonumber | ||
| actor Client | ||
| participant Builder as DBBuilder | ||
| participant Config as DBConfig | ||
| Note over Client,Builder #D3E4CD: Chainable setters | ||
| Client->>Builder: NewDBBuilder(driver) | ||
| Client->>Builder: SetHost(host) | ||
| Client->>Builder: SetPort(port) | ||
| Client->>Builder: SetUser(user) / SetDBName(db) / SetFilePath(path) | ||
| Note over Builder,Config #FCE9D5: Build validates inputs | ||
| Client->>Builder: Build() | ||
| Builder->>Builder: validate driver rules (user/dbname or filepath) | ||
| Builder->>Builder: validate port range | ||
| alt validations pass | ||
| Builder->>Config: return configured DBConfig | ||
| Client->>Config: use config (e.g., connect) | ||
| else validations fail | ||
| Builder-->>Client: return error | ||
| end | ||
| {{< /mermaid >}} | ||
|
|
||
| ## 9.1.6.3 مثال | ||
|
|
||
| وقتش رسیده که یک نمونهی واقعی را ببینیم. در کدی که در ادامه میآید، ما یک ساختار `DBConfig` داریم که تنظیمات اتصال به پایگاه داده را نگه میدارد. یک **Builder** به نام `DBBuilder` ایجاد کردهایم که به ما اجازه میدهد با استفاده از متدهای زنجیرهای (`SetUser`, `SetHost`, …) تنها فیلدهای مورد نیاز خود را مقداردهی کنیم و در پایان با فراخوانی `Build()` شیء نهایی را تحویل بگیریم. | ||
|
|
||
| {{< play >}} | ||
| package main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strings" | ||
| ) | ||
|
|
||
| type DBConfig struct { | ||
| Driver string | ||
| User string | ||
| Password string | ||
| Host string | ||
| Port int | ||
| DBName string | ||
| FilePath string | ||
| SSLMode string | ||
| } | ||
|
|
||
| type DBBuilder struct { | ||
| config DBConfig | ||
| errs []string | ||
| } | ||
|
|
||
| func NewDBBuilder(driver string) *DBBuilder { | ||
| d := strings.ToLower(strings.TrimSpace(driver)) | ||
| return &DBBuilder{config: DBConfig{Driver: d}} | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetUser(user string) *DBBuilder { | ||
| b.config.User = user | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetPassword(pass string) *DBBuilder { | ||
| b.config.Password = pass | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetHost(host string) *DBBuilder { | ||
| b.config.Host = host | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetPort(port int) *DBBuilder { | ||
| b.config.Port = port | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetDBName(db string) *DBBuilder { | ||
| b.config.DBName = db | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetFilePath(path string) *DBBuilder { | ||
| b.config.FilePath = path | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) SetSSLMode(mode string) *DBBuilder { | ||
| b.config.SSLMode = mode | ||
| return b | ||
| } | ||
|
|
||
| func (b *DBBuilder) Build() (DBConfig, error) { | ||
| // reset previous validation state to avoid stale errors on repeated Build calls | ||
| b.errs = b.errs[:0] | ||
|
|
||
| switch b.config.Driver { | ||
| case "mysql", "postgres", "postgresql": | ||
| if b.config.User == "" { | ||
| b.errs = append(b.errs, "user is required for SQL drivers") | ||
| } | ||
| if b.config.DBName == "" { | ||
| b.errs = append(b.errs, "dbname is required for SQL drivers") | ||
| } | ||
| case "sqlite": | ||
| if b.config.FilePath == "" { | ||
| b.errs = append(b.errs, "file path is required for sqlite") | ||
| } | ||
| default: | ||
| b.errs = append(b.errs, fmt.Sprintf("unknown driver: %s", b.config.Driver)) | ||
| } | ||
|
|
||
| // general validation | ||
| if b.config.Port != 0 && (b.config.Port < 1 || b.config.Port > 65535) { | ||
| b.errs = append(b.errs, "port must be in [1, 65535]") | ||
| } | ||
|
|
||
| if len(b.errs) > 0 { | ||
| return DBConfig{}, fmt.Errorf("invalid configuration: %s", strings.Join(b.errs, "; ")) | ||
| } | ||
| return b.config, nil | ||
| } | ||
|
|
||
| func main() { | ||
|
|
||
| // MySQL Example | ||
| mysqlCfg, err := NewDBBuilder("mysql"). | ||
| SetUser("admin"). | ||
| SetPassword("s3cr3t"). | ||
| SetHost("127.0.0.1"). | ||
| SetPort(3306). | ||
| SetDBName("shop"). | ||
| Build() | ||
|
|
||
| if err != nil { | ||
| fmt.Println("MySQL build error:", err) | ||
| } else { | ||
| fmt.Printf("MySQL config: %+v\n", mysqlCfg) | ||
| } | ||
|
|
||
| // SQLite example | ||
| sqliteCfg, err := NewDBBuilder("sqlite"). | ||
| SetFilePath("/tmp/app.db"). | ||
| Build() | ||
|
|
||
| if err != nil { | ||
| fmt.Println("SQLite build error:", err) | ||
| } else { | ||
| fmt.Printf("SQLite config: %+v\n", sqliteCfg) | ||
| } | ||
| } | ||
|
|
||
| {{< /play >}} | ||
|
|
||
| این کد، مفهوم الگوی بیلدر را در Go به شکلی بسیار ساده و شفاف پیادهسازی کرده است. | ||
| ساختار `DBConfig` شامل تمام فیلدهای لازم اتصال به پایگاه داده مثل نوع درایور، نام کاربری، رمز عبور، هاست، پورت، نام پایگاه داده، مسیر فایل (برای SQLite) و SSLMode است. `DBBuilder` یک سازنده مرحلهای است که این فیلدها را به صورت زنجیروار مقداردهی میکند. | ||
|
|
||
| متدهای `SetUser`، `SetPassword`، `SetHost` و بقیه، امکان پر کردن فیلدها به شکل خوانا و زنجیروار را فراهم میکنند. متد `Build` در پایان پیکربندی را اعتبارسنجی میکند، برای SQL فیلدهای `User` و `DBName` باید پر شوند، برای SQLite مسیر فایل الزامی است و پورت باید بین ۱ تا ۶۵۵۳۵ باشد. اگر خطایی باشد، ارور باز میگردد و در غیر این صورت پیکربندی معتبر تحویل داده میشود. | ||
|
|
||
| در تابع `main` دو مثال واقعی وجود دارد: یکی برای MySQL که تمام فیلدهای مرتبط پر شده و دیگری برای SQLite که تنها مسیر فایل مشخص شده است. این روش باعث میشود کد خوانا، قابل گسترش و ایمن باشد و ساخت پیکربندیهای مختلف پایگاه داده ساده و منعطف انجام شود. این پیادهسازی در عین سادگی نشان میدهد که چگونه میتوان با استفاده از الگوی Builder از پیچیدگیهای ایجاد اشیای بزرگ و متنوع کاست. | ||
|
|
||
| ## 9.1.6.4 کاربرد ها | ||
|
|
||
| در مواردی که اشیاء ما پارامترهای زیادی دارند و پیچیده هستند، استفاده از الگوی سازنده به کمک ما میآید. در مواردی مثل: | ||
|
|
||
| 1. کانکشن های دیتابیس | ||
| 2. فرم یا UIهای پیچیده | ||
| 3. {{< tooltip text="لاگر" note="Logger" >}} | ||
|
|
||
| ### 9.1.6.4.1 چه زمانی نباید از الگوی Builder استفاده کنیم؟ | ||
|
|
||
| 1. **ساخت اشیاء ساده** | ||
|
|
||
| + اگر شیء شما تنها چند پارامتر ساده دارد و ساخت آن راحت است، Builder پیچیدگی را زیاد میکند. | ||
|
|
||
| 2. **ملاحظات عملکردی** | ||
|
|
||
| + در برنامههایی که {{< tooltip text="کارایی" note="Performance" >}} مهم است، فراخوانیهای اضافی و ایجاد آبجکتهای موقت در Builder ممکن است باعث کاهش کارایی شود، بهویژه وقتی ساخت شیء مکرر است. | ||
|
|
||
| 3. **اشیاء immutable و ساده** | ||
|
|
||
| + اگر شیء ثابت و با فیلدهای نهایی است و ساخت آن ساده است، میتوان از سازندههای معمولی یا factory method استفاده کرد. | ||
|
|
||
| 4. **افزایش پیچیدگی کد** | ||
|
|
||
| + ایجاد یک Builder برای هر شیء پیچیده ممکن است کد را طولانی و پیچیده کند. | ||
| + اگر شیء نیاز به ساخت مرحلهای ندارد، Builder میتواند اضافه باشد. | ||
|
|
||
| 5. **وابستگی زیاد به محصول** | ||
|
|
||
| + اگر Builder و محصول خیلی به هم وابسته باشند، تغییر در محصول نیازمند تغییر در Builder است و انعطافپذیری کاهش مییابد. |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verification script to ensure all lint issues are gone after edits.
Run markdownlint and check for remaining errors; also grep for “Password” prints.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="content/chapter 9/creational patterns/9.1.6-builder.md"
# Lint
npx -y markdownlint-cli2 "$FILE"
# Ensure no %+v prints of configs without Stringer (defense-in-depth)
rg -n --no-heading -C0 '%\+v' "$FILE" || trueLength of output: 5980
Fix markdownlint errors in builder pattern docs
Replace all hard‐tab characters with spaces (MD010) and remove spaces inside emphasis markers (MD037) in content/chapter 9/creational patterns/9.1.6-builder.md.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
56-56: Hard tabs
Column: 1
(MD010, no-hard-tabs)
57-57: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
60-60: Hard tabs
Column: 1
(MD010, no-hard-tabs)
61-61: Hard tabs
Column: 1
(MD010, no-hard-tabs)
62-62: Hard tabs
Column: 1
(MD010, no-hard-tabs)
63-63: Hard tabs
Column: 1
(MD010, no-hard-tabs)
67-67: Hard tabs
Column: 1
(MD010, no-hard-tabs)
68-68: Hard tabs
Column: 1
(MD010, no-hard-tabs)
72-72: Hard tabs
Column: 1
(MD010, no-hard-tabs)
73-73: Hard tabs
Column: 1
(MD010, no-hard-tabs)
76-76: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
77-77: Hard tabs
Column: 1
(MD010, no-hard-tabs)
78-78: Hard tabs
Column: 1
(MD010, no-hard-tabs)
81-81: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
82-82: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Hard tabs
Column: 1
(MD010, no-hard-tabs)
86-86: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
87-87: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Hard tabs
Column: 1
(MD010, no-hard-tabs)
91-91: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
96-96: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
97-97: Hard tabs
Column: 1
(MD010, no-hard-tabs)
98-98: Hard tabs
Column: 1
(MD010, no-hard-tabs)
101-101: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
102-102: Hard tabs
Column: 1
(MD010, no-hard-tabs)
103-103: Hard tabs
Column: 1
(MD010, no-hard-tabs)
106-106: Spaces inside emphasis markers
(MD037, no-space-in-emphasis)
107-107: Hard tabs
Column: 1
(MD010, no-hard-tabs)
108-108: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
146-146: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
148-148: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
153-153: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
156-156: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
159-159: Hard tabs
Column: 1
(MD010, no-hard-tabs)
160-160: Hard tabs
Column: 1
(MD010, no-hard-tabs)
161-161: Hard tabs
Column: 1
(MD010, no-hard-tabs)
162-162: Hard tabs
Column: 1
(MD010, no-hard-tabs)
164-164: Hard tabs
Column: 1
(MD010, no-hard-tabs)
165-165: Hard tabs
Column: 1
(MD010, no-hard-tabs)
166-166: Hard tabs
Column: 1
(MD010, no-hard-tabs)
167-167: Hard tabs
Column: 1
(MD010, no-hard-tabs)
168-168: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In content/chapter 9/creational patterns/9.1.6-builder.md lines 1-209, the
markdown contains hard-tab characters triggering MD010 and extra spaces inside
emphasis markers triggering MD037; replace all hard tabs with spaces (use 2 or 4
spaces consistently) throughout the file and remove any spaces immediately
inside emphasis/italic/bold markers (e.g., change "* text *" or "** text **" to
"*text*" or "**text**"), then re-run markdownlint to confirm no MD010/MD037
violations remain.
Add introduction for Builder design pattern
Add code example
Summary by CodeRabbit