Skip to content

Conversation

@Hossein-Fazel
Copy link
Contributor

@Hossein-Fazel Hossein-Fazel commented Sep 8, 2025

Add introduction for Builder design pattern
Add code example

Summary by CodeRabbit

  • Documentation
    • Replaced a brief placeholder with a comprehensive Persian guide to the Builder pattern.
    • Added expanded narrative, usage guidance, and clear examples illustrating chainable configuration and validation flows.
    • Included a sequence diagram (Mermaid) to show construction and error paths.
    • Clarified practical use cases and advised when not to apply the Builder pattern to avoid over‑engineering.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 8, 2025

Walkthrough

Documentation update: replaces a placeholder with a full Persian explanation of the Builder pattern, adds front matter mermaid: "true" and an unquoted title, includes a Mermaid diagram, a Go DBConfig/DBBuilder example with chainable setters and Build validations, usage demos (MySQL, SQLite), and guidance on when to use or avoid the pattern.

Changes

Cohort / File(s) Summary
Docs — Builder pattern chapter
content/chapter 9/creational patterns/9.1.6-builder.md
Replaced placeholder with a complete Persian write-up of the Builder pattern; added mermaid: "true" to front matter and removed quotes around the title; added sections: توضیحات, دیاگرام (Mermaid sequence), مثال (Go DBConfig / DBBuilder with chainable setters SetUser, SetPassword, SetHost, SetPort, SetDBName, SetFilePath, SetSSLMode and Build() validations for driver-specific rules and port range), usage demos for MySQL/SQLite, and guidance on when not to use Builder.

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
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • ja7ad

در فصلِ نه، خرگوش با قلمی سبک،
Builder ساخت کن، زنجیره‌وار و بی‌نگ؛
SetHost و SetPort، Build با سنجشِ درست،
MySQL یا SQLite، کانفیگ بر بست؛
هُرّا! کار تمام شد، خرگوش شاد و خوش‌دل. 🐇✨

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat: Add builder design pattern” clearly summarizes the primary change by indicating that the Builder pattern support is being introduced, and it is concise and directly tied to the content and code examples added in the documentation.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 example

Optionally 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

📥 Commits

Reviewing files that changed from the base of the PR and between f4ae625 and 57d91ac.

📒 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.

Comment on lines 38 to 161
{{< 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 >}}
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 8, 2025

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)

✅ Addressed in commits 754600f to 5dad35f

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between 57d91ac and a071f48.

📒 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)

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between a071f48 and 5dad35f.

📒 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)

Hossein-Fazel and others added 4 commits September 8, 2025 17:37
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>
@ja7ad
Copy link
Member

ja7ad commented Sep 8, 2025

لطفا سعی کنید طبق این ساختار این بخش را بنویسید درخصوص الگوها:

https://book.gofarsi.ir/chapter-9/concurrency-patterns/go-concurrency-pattern-wait-for-result/

  • توضیحات
  • دیاگرام
  • نمونه کد به همراه توضیح کد
  • کاربرد ها

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 URL

content/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

📥 Commits

Reviewing files that changed from the base of the PR and between f4ae625 and 74b0f5e.

📒 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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>" >}}
Copy link
Member

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...
### توضیحات
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### توضیحات
## 9.1.6.1 توضیحات

الگوی بیلدر وقتی کمک کننده است که بخواهید یک شیء پیچیده با پارامترهای زیاد را مرحله به مرحله و خواناتر بسازید، بدون اینکه درگیر سازنده‌های طولانی و گیج‌کننده بشوید.
{{< /hint >}}

### دیاگرام
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### دیاگرام
## 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### نمونه کد: ساخت پیکربندی پایگاه داده با Builder
## 9.1.6.3 مثال


وقتش رسیده که یک نمونه‌ی واقعی را ببینیم. در کدی که در ادامه می‌آید، ما یک ساختار `DBConfig` داریم که تنظیمات اتصال به پایگاه داده را نگه می‌دارد. یک **Builder** به نام `DBBuilder` ایجاد کرده‌ایم که به ما اجازه می‌دهد با استفاده از متدهای زنجیره‌ای (`SetUser`, `SetHost`, …) تنها فیلدهای مورد نیاز خود را مقداردهی کنیم و در پایان با فراخوانی `Build()` شیء نهایی را تحویل بگیریم.

<!-- markdownlint-disable MD010 MD037 MD012 -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<!-- markdownlint-disable MD010 MD037 MD012 -->

Remove it

}

{{< /play >}}
<!-- markdownlint-enable MD010 MD037 MD012 -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<!-- markdownlint-enable MD010 MD037 MD012 -->


در تابع `main` دو مثال واقعی وجود دارد: یکی برای MySQL که تمام فیلدهای مرتبط پر شده و دیگری برای SQLite که تنها مسیر فایل مشخص شده است. این روش باعث می‌شود کد خوانا، قابل گسترش و ایمن باشد و ساخت پیکربندی‌های مختلف پایگاه داده ساده و منعطف انجام شود. این پیاده‌سازی در عین سادگی نشان می‌دهد که چگونه می‌توان با استفاده از الگوی Builder از پیچیدگی‌های ایجاد اشیای بزرگ و متنوع کاست.

### کاربرد ها
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### کاربرد ها
## 9.1.6.4 کاربرد ها

2. فرم یا UI‌های پیچیده
3. {{< tooltip text="لاگر" note="Logger" >}}

### چه زمانی نباید از الگوی Builder استفاده کنیم؟
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### چه زمانی نباید از الگوی Builder استفاده کنیم؟
### 9.1.6.4.1 چه زمانی نباید از الگوی Builder استفاده کنیم؟

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 = nil avoids 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3249c89 and bfb86d9.

📒 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: true

Please 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 >}}.

Comment on lines +57 to +65
type DBConfig struct {
Driver string
User string
Password string
Host string
Port int
DBName string
FilePath string
SSLMode string
}

Copy link
Contributor

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.

Suggested change
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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 MD037

Surround 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

📥 Commits

Reviewing files that changed from the base of the PR and between bfb86d9 and 0625d6b.

📒 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.

Comment on lines 0 to 209
---
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 است و انعطاف‌پذیری کاهش می‌یابد.
Copy link
Contributor

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" || true

Length 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.

@Hossein-Fazel Hossein-Fazel requested a review from ja7ad September 10, 2025 06:56
@ja7ad ja7ad merged commit 207253c into GoFarsi:main Sep 10, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants