AzLearn

مختبر ترتيب الحزم

Package Layout Lab

مشروع ~28 دقيقة

مختبر ترتيب الحزم — Package Layout Lab

ترتيب الحزم ليس زينة. هو طريقة لتوضيح ما يمكن استخدامه من الخارج، وما يجب أن يبقى داخل التطبيق.

في Go، اسم الحزمة ومكانها جزء من التصميم. عندما يرى مطور مساراً مثل invoice يتوقع منطق المجال، وعندما يرى cmd/invoicer يتوقع نقطة تشغيل، وعندما يرى internal/formatter يعرف أن هذه تفاصيل لا تستخدم من خارج المشروع. هذا الوضوح يقلل النقاشات لاحقاً، ويمنع تسرب تفاصيل صغيرة إلى واجهة عامة يصعب تغييرها.

هذا المختبر لا يطلب منك إنشاء ملفات حقيقية داخل المتصفح. هو يدربك على قرار التقسيم: ما الذي يستحق أن يكون public؟ ما الذي يبقى داخلياً؟ وما الذي يخص أمر التشغيل فقط؟ إذا تعلمت هذه الأسئلة الآن، ستكتب مشاريع Go أكبر دون أن تتحول إلى ملف واحد ضخم أو عشرات الحزم المربكة.

السيناريو

لديك خدمة صغيرة ترسل فواتير. تريد فصل:

  • invoice كحزمة مجال تحتوي الأنواع والدوال العامة.
  • internal/formatter كتفصيل داخلي لتنسيق النص.
  • cmd/invoicer كنقطة تشغيل.

شكل مقترح

invoicer/
  go.mod
  cmd/
    invoicer/
      main.go
  invoice/
    invoice.go
  internal/
    formatter/
      money.go

ما الذي يكون exported؟

اجعل الأشياء التي يحتاجها مستخدم الحزمة فقط بحرف كبير:

package invoice

type Invoice struct {
    Number string
    Total  int
}

func New(number string, total int) Invoice {
    return Invoice{Number: number, Total: total}
}

أما تفاصيل التنسيق الداخلية فتستطيع أن تبقى في internal.

هذا مثال سريع يوضح الفرق بين اسم exported واسم داخلي داخل ملف واحد:

main.go

في حزمة حقيقية، Invoice وNew قد يكونان exported لأن كوداً خارج الحزمة يحتاج إنشاء فاتورة. أما formatHalalas فقد تبقى داخلية لأنها تفصيل عرض يمكن تغييره. لا تجعل كل شيء بحرف كبير فقط لتسهيل الوصول؛ كل اسم exported يصبح وعداً للآخرين أنك لن تغيره بسهولة.

تحدي المختبر

هذا التحدي يحاكي قرار التقسيم. أكمل الدوال لتطبع خطة الحزم الصحيحة.

تحدي — Challenge

معيار القبول

اسأل نفسك قبل إنشاء أي package:

  • هل لها مسؤولية واحدة واضحة؟
  • هل اسمها يشرح الاستخدام؟
  • هل ما صدرته فعلاً يحتاجه كود خارج الحزمة؟
  • هل التفاصيل الحساسة أو المتغيرة موضوعة داخل internal؟

أخطاء شائعة في التقسيم

أول خطأ هو إنشاء package لكل ملف. كثرة الحزم الصغيرة بلا حدود واضحة تجعل المشروع أصعب، لا أسهل. ثاني خطأ هو وضع منطق المجال داخل cmd لأن main.go كان المكان الأسرع. cmd يجب أن يركب البرنامج ويستدعي الحزم، لا أن يحمل كل قواعد الفواتير. ثالث خطأ هو تصدير كل دالة وكل type. التصدير الواسع يجعل refactor لاحقاً مؤلماً لأنك لا تعرف من يعتمد على ماذا.

استخدم internal عندما تريد حماية تفاصيل المشروع من الاستخدام الخارجي. هذه ليست مجرد اتفاقية؛ Go يفرضها على مستوى الاستيراد. أي كود خارج الجذر المناسب لا يستطيع import حزمة داخل internal. لذلك هي أداة جيدة للأشياء التي تريد حرية تغييرها، مثل formatters أو adapters داخلية.

خلاصة

ترتيب الحزم الجيد يشرح نية المشروع قبل قراءة التنفيذ. invoice تحمل لغة المجال، internal/formatter تخفي التفاصيل المتغيرة، وcmd/invoicer يشغل البرنامج. إذا حافظت على هذه الحدود، سيصبح المشروع قابلاً للنمو: تضيف أمر CLI جديداً، أو HTTP server، أو طريقة عرض مختلفة دون نسخ منطق الفاتورة في كل مكان.