Skip to content

Commit

Permalink
add: directive comment
Browse files Browse the repository at this point in the history
  • Loading branch information
Ja7ad committed May 27, 2023
1 parent c34f6a0 commit 7fe05eb
Showing 1 changed file with 91 additions and 9 deletions.
100 changes: 91 additions & 9 deletions content/chapter 4/4.19-commentary.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ weight: 7019
---

اصول کامنت‌نویسی در زبان گو
# تعریف
## 4.19.1 تعریف
«کامنت» به توضیحات‌ی گفته می‌شود که داخل کد، به‌قصد «یادآوری»، «جلب‌توجه مخاطب به موضوع‌(ها)ی خاص»، کمک به onboard شدن اعضاء جدید تیم و مانند اون نگارش می‌شود. در زبان گو، به شیوه‌های زیر کامنت می‌گذاریم:
- قرار دادن `//` در ابتدای سطر.
```go
Expand All @@ -29,16 +29,18 @@ gofmt -w main.go


{{< /hint >}}
# دیدگاه‌ها درباره «کامنت»
## 4.19.2 دیدگاه‌ها درباره «کامنت»
با توجه به این موضوع که در جوامع‌تخصصی توسعه نرم‌افزار، درارتباط با اصل وجود کامنت، مزایا/معایب و چگونگی استفاده از آن، مطالب گوناگون و بعضاً متضادی، حتی از جانب متخصصین، وجود دارد، در این قسمت سعی خواهیم کرد، تاجای‌ممکن پاسخ حساب‌شده‌ای به نیازمندی‌های مختلف در ارتباط با «کامنت‌گذاری» بدهیم.

# کامنت؛ خوب، بد، زشت
## 4.19.3 کامنت؛ خوب، بد، زشت
- `در کدهایی که بارها نسخه‌های متفاوتی از آن ایجاد شده و در طول زمان، نیازمندی‌ها عوض شده، کیفیت، کارایی و سرعت اجرا بهبود پیدا کرده، «کامنت» گزارش «چرایی» کد هست برای این: نیاز/کیفیت/کارایی/سرعت اجرا، برای اینکه همه این‌ها رو دوباره تجربه نکنند ...`
- `یک کد خوب، هیچ نیازی به کامنت ندارد، به‌زبان‌دیگر، اگر نیاز می‌بینید که برای کدی «کامنت» بنویسید، احتمالاً، کد خوبی ننوشتید ...`
- `یک ساختار جدید، ناشناخته و احتمالاً حجیم، به‌قدر‌کافی ماهیتاً اینقدر پیچیدگی دارد که اضافه شدن، یک توضیح به زبان کاملاً انسانی (داخل زبان کامپایلر/مفسری برای زبان ماشین)، نه‌تنها باعث روشن‌تر شدن آن نمی‌شود بلکه مسئله‌ی فهم منظور نگارنده «کامنت» به مجموعه مسائل قبلی اضافه می‌گردد. هیچ‌چیز بیشتر از یک کد پیچیده با کلی «کامنت‌های» پیچیده برای مخاطبی که انتظار روشن بودن چرایی و چگونگی کد را دارد، عذاب‌آور نیست ... `

همه این‌ها پاسخ‌های متفاوت‌ی است که توسعه‌دهندگان به موضوع «کامنت» می‌دهند. اما «اصولاً» کامنت پرفایده است یا بی‌فایده؟
# آنالیز محصول و محیط توسعه

## 4.19.4 آنالیز محصول و محیط توسعه

وقتی در ارتباط با کامنت صحبت می‌کنیم این خیلی مهم است که ما به‌تنهایی مشغول توسعه یک محصول هستیم یا در یک دپارتمان کوچک یا در یک ابَرپروژه ... آیا ما مجبور به تبعیت از یک‌سری دستورالعمل‌های کدنویسی هستیم یا می‌توانیم سلیقه‌شخصی خود را داشته باشیم؟ ...
- **شرایط تیم توسعه**.
- نحوه مدیریت(افراد/روش‌ها) پروژه در فرآیند توسعه کد.
Expand All @@ -56,9 +58,10 @@ gofmt -w main.go
نتیجه اینکه: ابتدا نیازمندی، توانایی و شرایط تیم/محصول را مشخص کنیم، و بعد تصمیم به چرایی و چگونگی کامنت‌نویسی اصولی بگیریم.
{{< /hint >}}

# انواع کامنت
## 4.19.5 انواع کامنت
- کامنت فایل/پکیج (Doc Comment)
این‌نوع کامنت‌ها درباره «چیستی» کل فایل یا پکیج توضیح دارد.

این‌نوع کامنت‌ها درباره «چیستی» کل فایل یا پکیج توضیح دارد.
```go
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
Expand All @@ -75,7 +78,7 @@ package builtin
مثال بالا از پکیج `builtin` درباره حق‌چاپ / تعریف اولیه پکیج و اینکه مستندات در `godoc` ارائه می‌شود، توضیح داده است.

- کامنت داخلی فانکشن/متد/بلوک/تایپ/متغیر/دستور و مانند آن (Ordinary Comments)
این‌نوع کامنت درباره «چرایی» آن قسمتِ خاص اشاره دارد.
این‌نوع کامنت درباره «چرایی» آن قسمتِ خاص اشاره دارد.

```go
// The delete built-in function deletes the element with the specified key
Expand All @@ -85,7 +88,8 @@ func delete(m map[Type]Type1, key Type)
```
در مثال بالا، توسط کامنت توضیح داده شده که وظیفه فانکشن-داخلی `delete` حذف المنت با کلید مشخص هست، و توضیح دقیق‌تر اینکه اگر المنت مربوط به کلید `nil` باشد یا وجود نداشته باشد، فانکشن `delete` هیچ عملیاتی انجام نمی‌دهد. (مثلاً خطا باز نمی‌گرداند − گزارش نمی‌کند و ...)

# اصول کامنت‌نویسی
## 4.19.6 اصول کامنت‌نویسی

یک کامنت خوب:

1. توضیح واضحات را نمی‌دهد.
Expand All @@ -105,7 +109,8 @@ func delete(m map[Type]Type1, key Type)
mc.buf.flip()
```

# به پرتگاه نزدیک می‌شوید!
## 4.19.7 به پرتگاه نزدیک می‌شوید!

- زامبی کد: به کدی می‌گویند که به دلیل عدم کارایی، اصلاح با کد جدید، و یا مشابه این موارد، بجای «حذف»، «کامنت» می‌شوند.
- کامنت اسپاگتی کد: به کامنت‌های دنباله‌داری گفته می‌شود که برای توضیح یک کدی که ساختار منظم و مشخصی ندارد، نگارش می‌شود.
- یکی دیگر از استفاده‌های کامنت، {{< tooltip text="وظیفه‌ی برنامه‌ریزی‌شده" note="ToDo" >}} می‌باشد که اگر کنترل نشود، یکی دیگر از عذاب‌های عظیم خواهد بود.
Expand All @@ -114,3 +119,80 @@ func delete(m map[Type]Type1, key Type)
- کامنت‌های شما، نباید تبدیل به «نویز» درکدنویسی دیگران شود. تعدد کامنت‌ها کد را تبدیل به کد کثیف می‌کند که خوانایی ضعیفی خواهد داشت.
- کامنت، جای دردل کردن، شکایت از مدیرپروژه، تعریف از خود و گفتگو نیست.

## 4.19.8 انواع directive comment

<span dir="ltr">**//go:generate**</span>: این نظر برای مشخص کردن یک دستور است که باید توسط ابزار go generate اجرا شود. این نظر معمولاً قبل از یک دستور تولید کد قرار داده می‌شود که به شما اجازه می‌دهد کد Go را به صورت خودکار تولید کنید.

<span dir="ltr">**//go:binary-only-package**</span>: این نظر برای اعلام این استفاده می‌شود که یک بسته باید به عنوان یک بسته فقط دودویی در نظر گرفته شود، به معنای این است که کد منبع بسته در دسترس نیست. این برای بسته‌هایی استفاده می‌شود که شامل کد‌های محصولی یا بسته‌های مشخص سیستم‌عامل هستند.

<span dir="ltr">**//go:build**</span>: این نظر برایمحدودیت‌های ساخت استفاده می‌شود. این به شما امکان می‌دهد که کنترل کنید که یک فایل باید بر اساس شرایط خاصی مانند سیستم عامل، معماری یا برچسب ساخت، در ساخت شامل شود یا خیر.

<span dir="ltr">**//go:cgo_...**</span>: چندین نظر دستوری وجود دارد که با cgo_ شروع می‌شوند، مانند //go:cgo_import_dynamic و //go:cgo_export_dynamic. این نظرات همراه با cgo استفاده می‌شوند، ابزاری که به کد Go اجازه می‌دهد تا به کد C و بالعکس برای فراخوانی دستورات استفاده شود. آن‌ها دستوراتی را به ابزار cgo ارائه می‌دهند که نحوه برخورد کد C را مشخص می‌کنند.

<span dir="ltr">**//go:noinline:**</span> این نظر برای مشخص کردن این استفاده می‌شود که یک تابع توسط کامپایلر به صورت inline نباید درج شود. Inline کردن یک تابع یک تکنیک بهینه‌سازی است که کد یک تابع به طور مستقیم در کد فراخواننده آن قرار می‌گیرد و هزینه فراخوانی تابع را حذف می‌کند. استفاده از این نظر از کامپایلر جلوگیری می‌کند تا برای تابع مشخص شده inline کردن انجام دهد.

<span dir="ltr">**//go:nosplit**</span>: این نظر برای مشخص کردن این استفاده می‌شود که یک تابع باید توسط برنامه‌ریز Go runtime اجرا شده (split) نشود. این معمولاً برای توابع سطح پایین استفاده می‌شود که نیاز به کنترل دقیق بر روی اجرای آن‌ها دارند و نباید وقفه داده شوند.

<span dir="ltr">**//go:linkname**</span>: این نظر برای برقراری ارتباط بین کد Go و نمادهای خارجی یا کد غیر Go استفاده می‌شود. این به شما اجازه می‌دهد تا به یک نماد با نام متفاوت یا از بسته‌ای دیگر ارجاع دهید.

<span dir="ltr">**//go:noescape**</span>: این نظر برای مشخص کردن این استفاده می‌شود که آرگومان‌های اشاره گر تابع escape نمی‌کنند، به معنایی که در طول عمر تابع ذخیره یاستفاده نمی‌شوند یا استفاده نمی‌شوند. این اطلاعات به کامپایلر اجازه می‌دهند که بهینه‌سازی‌های حافظه تابع را انجام دهد.

<span dir="ltr">**//go:embed**</span>: این نظر برای اضافه کردن فایل‌های استاتیک یا دایرکتوری‌ها به طور مستقیم به باینری Go در زمان کامپایل استفاده می‌شود. این فرآیند از جمله فرآیند بسته‌بندی و توزیع منابع با برنامه‌های Go خود است.

<span dir="ltr">**//go:generate go run**</span>: این نظر یک نوع دیگر از نظر //go:generate است. این نظر مشخص می‌کند که دستور زیر نظر باید توسط اجرای برنامه Go با استفاده از دستور go run اجرا شود.

<span dir="ltr">**//go:build ...**</span>: این نظر یک فرم گسترده‌تر از نظر build است. این به شما امکان می‌دهد شرایط ساخت را با استفاده از اپراتورهای منطقی بولی، پرانتز و نفی مشخص کنید. این امکانات بیشتری در کنترل کردن فایل‌هایی که در ساخت شامل می‌شوند، فراهم می‌کند.

<span dir="ltr">**//go:protofile**</span>: این نظر برای مشخص کردن پروتوباف فایل مرتبط با یک فایل منبع Go استفاده می‌شود. این معمولاً در کد Go استفاده می‌شود که شامل کد پروتوباف تولید شده است، اجازه می‌دهد که کامپایلر فایل‌های Go و پروتوباف رابه درستی به هم پیوند دهد.

<span dir="ltr">**//go:nowritebarrier**</span>: این نظر برای مشخص کردن این استفاده می‌شود که یک تابع بدون write barrier باید اجرا شود. Write barrier برای تعقیب و به‌روزرسانی اشاره‌گرها در زمان تخصیص و آزادسازی حافظه توسط garbage collector استفاده می‌شود. استفاده از این نظر ممکن است خطرناک باشد و تنها در موارد خاصی که مدیریت دستی حافظه لازم است، باید استفاده شود.

<span dir="ltr">**//go:norace**</span>: این نظر دستوری برای غیرفعال کردن ردیابی race برای یک تابع خاص است. ردیاب race یک ابزار در Go است که به شناسایی دسترسی همزمان به متغیرهای مشترک که ممکن است منجر به دور زدن داده‌ها (race condition) بشود، کمک می‌کند. این دستور می‌تواند هنگامی استفاده شود که از عدم وجود شرایط race برای یک تابع خاص اطمینان دارید.

<span dir="ltr">**//go:buildignore**</span>: این نظر دستوری برای حذف یک فایل از فرآیند ساخت استفاده می‌شود. این به سیستم ساخت Go می‌گوید که این فایل را نادیده بگیرد و در هنگام کامپایل بسته، شامل نشود.

<span dir="ltr">**//go:generate goimports**</span>: این نظر دستوری برای استفاده در ارتباط با دستور //go:generate استفاده می‌شود تا به صورت خودکار ابزار goimports اجرا شود. goimports به طور خودکار import statements را به روزرسانی و فرمت دهی می‌کند، اطمینان حاصل می‌کند که import های بسته درست هستند و import های بی‌استفاده را حذف می‌کند.

<span dir="ltr">**//go:embed pattern**</span>: این نظر دستوری یک فرم گسترده‌تر از //go:embed است و به شما اجازه می‌دهد الگویی را برای تطبیق با فایل‌ها یا دایرکتوری‌ها برای جاسازی در حالت تعبیه شده مشخص کنید. این امکانات، در انتخاب فایل‌ها یا دایرکتوری‌های خاص بیشتری ارائه می‌دهد.

<span dir="ltr">**//go:nolint**</span>: این نظر دستوری برای سرکوب خطاها و هشدارهای خاص لینتر برای یک خط کد خاص استفاده می‌شود. این اغلب هنگامی استفاده می‌شود که یک قانون لینتر یک false positive را سیگنال می‌دهد یا وقتی دلیل معتبری برای نادیده گرفتن یک مسئله لینتینگ موقتا وجود دارد.

<span dir="ltr">**//go:generate go test**</span>: این نظر دستوری برای استفاده در ارتباط با دستور //go:generate استفاده می‌شود تا به صورت خودکار دستور go test اجرا شود. این دستور معمولاً برای تولید و اجرای کد آزمایشی برای یک بسته استفاده می‌شود.

<span dir="ltr">**//go:uintptrescapes**</span>: این نظر دستوری برای نشان دادن این است که یک مقدار uintptr ممکن است به حافظه heap فرار کند. به طور پیش فرض، کامپایلر فرض می‌کند که مقدارهای uintptr فرار نمی‌کنند، اما استفاده از این دستور اجازه تجزیه و تحلیل فرار دقیق‌تر را می‌دهد.

<span dir="ltr">**//go:build !constraint**</span>: این نظر دستوری برای حذف یک فایل از فرآیند ساخت بر اساس شرط ساخت خاص استفاده می‌شود. این به شما اجازه می‌دهد یک شرط را مشخص کنید که برای شامل شدن فایل در فرآیند ساخت باید برآورده نشود.

<span dir="ltr">**//go:checkptr**</span>: این نظر دستوری برای فعال کردن بررسی‌های ایمنی اضافی برای اشاره‌گرها در کد استفاده می‌شود. این دستور به کامپایلر دستور می‌دهد تا بررسی‌های رانتایم اضافی را برای شناسایی عملیات اشاره‌گر ناموفق و مسائل امنیتی حافظه انجام دهد.

<span dir="ltr">**//go:nosplitcheck**</span>: این نظر دستوری برای غیرفعال کردن بررسی nosplit برای یک تابع استفاده می‌شود. بررسی nosplit بررسی می‌کند که یک تابع بدون پیش‌بینی از برنامه‌ای که در آینده اجرا می‌شود، بدون توقف توسط برنامه اجرا شود.استفاده از این دستور ممکن است خطرناک باشد و فقط در صورت ضرورت باید استفاده شود.

<span dir="ltr">**//go:noruntime**</span>: این نظر دستوری برای نشان دادن این است که یک بسته به Go runtime وابسته نیست. این به کامپایلر اطلاع می‌دهد که بسته می‌تواند در یک محیط استفاده شود که Go runtime در دسترس نیست یا نیاز نیست.

**مثال استفاده از directive comment:**


```go
package main
import "fmt"
//go:generate stringer -type=Age
type Age int
const (
CHILDERN Age = iota
ADOLESCENTS
ADULTS
)
func main() {
fmt.Println(CHILDERN.String())
}
```
در کد فوق ما یک directive comment اضافه کردیم حال کافیه با استفاده از دستور go generate متد استرینگ تایپ را جنریت کنیم.

```
go generate ./...
```

0 comments on commit 7fe05eb

Please sign in to comment.