-
-
Notifications
You must be signed in to change notification settings - Fork 115
feat: Add builder design pattern #396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
| --- | ||
| title: '9.1.6 الگو Builder' | ||
| slug: go-builder-pattern | ||
| weight: 172006 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
لطفا کد mermaid را بصورت زیر اضافه کنید:
{{< mermaid >}}
# put here...
{{< /mermaid >}}
| --- | ||
|
|
||
| الگو Builder... | ||
| ### توضیحات |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### توضیحات | |
| ## 9.1.6.1 توضیحات |
| الگوی بیلدر وقتی کمک کننده است که بخواهید یک شیء پیچیده با پارامترهای زیاد را مرحله به مرحله و خواناتر بسازید، بدون اینکه درگیر سازندههای طولانی و گیجکننده بشوید. | ||
| {{< /hint >}} | ||
|
|
||
| ### دیاگرام |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### دیاگرام | |
| ## 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### نمونه کد: ساخت پیکربندی پایگاه داده با Builder | |
| ## 9.1.6.3 مثال |
|
|
||
| وقتش رسیده که یک نمونهی واقعی را ببینیم. در کدی که در ادامه میآید، ما یک ساختار `DBConfig` داریم که تنظیمات اتصال به پایگاه داده را نگه میدارد. یک **Builder** به نام `DBBuilder` ایجاد کردهایم که به ما اجازه میدهد با استفاده از متدهای زنجیرهای (`SetUser`, `SetHost`, …) تنها فیلدهای مورد نیاز خود را مقداردهی کنیم و در پایان با فراخوانی `Build()` شیء نهایی را تحویل بگیریم. | ||
|
|
||
| <!-- markdownlint-disable MD010 MD037 MD012 --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <!-- markdownlint-disable MD010 MD037 MD012 --> |
Remove it
| } | ||
|
|
||
| {{< /play >}} | ||
| <!-- markdownlint-enable MD010 MD037 MD012 --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <!-- markdownlint-enable MD010 MD037 MD012 --> |
|
|
||
| در تابع `main` دو مثال واقعی وجود دارد: یکی برای MySQL که تمام فیلدهای مرتبط پر شده و دیگری برای SQLite که تنها مسیر فایل مشخص شده است. این روش باعث میشود کد خوانا، قابل گسترش و ایمن باشد و ساخت پیکربندیهای مختلف پایگاه داده ساده و منعطف انجام شود. این پیادهسازی در عین سادگی نشان میدهد که چگونه میتوان با استفاده از الگوی Builder از پیچیدگیهای ایجاد اشیای بزرگ و متنوع کاست. | ||
|
|
||
| ### کاربرد ها |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### کاربرد ها | |
| ## 9.1.6.4 کاربرد ها |
| 2. فرم یا UIهای پیچیده | ||
| 3. {{< tooltip text="لاگر" note="Logger" >}} | ||
|
|
||
| ### چه زمانی نباید از الگوی Builder استفاده کنیم؟ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### چه زمانی نباید از الگوی Builder استفاده کنیم؟ | |
| ### 9.1.6.4.1 چه زمانی نباید از الگوی Builder استفاده کنیم؟ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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... | ||
| ## 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 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