Go والهندسة المعمارية السداسية: كتابة كود لا نخاف من تغييره

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

تعرف على: كودك معزول عن العالم الخارجي

\n\n

هل سبق لك أن أعدت كتابة منطق الأعمال فقط لأنك غيرت قاعدة البيانات من PostgreSQL إلى MongoDB؟ أو استيقظت في عرق بارد من فكرة أنك بحاجة لإضافة نقطة نهاية HTTP جديدة، بينما التطبيق بأكمله هو ملف main.go عملاق واحد بطول 3000 سطر؟

\n\n

إذا كانت الإجابة بنعم - مرحباً بك في النادي. إذا كانت لا - فإما أنك تكتب بلغة Go منذ فترة قصيرة، أو أنك تستخدم بالفعل الهندسة المعمارية السداسية (المعروفة أيضاً باسم Ports & Adapters).

\n\n

في هذه المقالة، سنشرح كيفية بناء تطبيق بلغة Go لا يخاف من التغيير. لا تغيير قاعدة البيانات، ولا الانتقال من REST إلى gRPC، ولا إطار عمل جديد سيجبرك على إعادة كتابة نواة النظام. فقط كود. فقط Go. بدون حشو.

\n\n

ما هي الهندسة المعمارية السداسية بكلمات بسيطة

\n\n

تخيل أن تطبيقك هو سفينة فضاء. في المركز - غرفة القيادة (منطق الأعمال). حولها - منافذ الالتحام. من خلال المنافذ تقوم بتوصيل وحدات مختلفة: المحركات (قاعدة البيانات)، أجهزة الاستشعار (طلبات HTTP)، الاتصال بالأرض (قوائم انتظار الرسائل).

\n\n

إذا قررت استبدال المحركات - فقط تفصل القديمة وتلصق الجديدة. غرفة القيادة لن تلاحظ حتى الاستبدال. هذا هو الهندسة المعمارية السداسية.

\n\n

المفاهيم الأساسية:

\n
    \n
  • Port (المنفذ) - واجهة تحدد كيف يمكن للعالم الخارجي التفاعل مع النواة. على سبيل المثال، UserRepository مع دوال Save و FindByID.
  • \n
  • Adapter (المحول) - تنفيذ محدد للمنفذ. يمكن أن يكون لمنفذ واحد محولات متعددة: PostgreSQLAdapter، InMemoryAdapter، MockAdapter للاختبارات.
  • \n
  • Core (النواة) - منطق الأعمال الذي لا يعرف شيئاً عن العالم الخارجي. يعمل فقط من خلال المنافذ.
  • \n
\n\n

هذا النهج يعطي ثلاث قدرات خارقة: قابلية الاختبار (للنواة بدون قاعدة بيانات)، المرونة (استبدال أي جزء)، وحدود مسؤولية واضحة.

\n\n

لماذا Go مثالية للهندسة المعمارية السداسية

\n\n

Go لا تفرض البرمجة كائنية التوجه، لكنها توفر الواجهات - الشيء الوحيد المطلوب لـ Ports & Adapters. الواجهات في Go ضمنية: الهيكل يلبي الواجهة تلقائياً إذا قام بتنفيذ دوالها. هذا يعني أنه يمكنك استبدال المحول دون تغيير سطر واحد في النواة.

\n\n

بالإضافة إلى ذلك، Go تُترجم إلى ملف ثنائي، مما يجعل الهندسة المعمارية مفيدة بشكل خاص للخدمات المصغرة. والاختبار المدمج واختبارات الأداء تسمح بالتحقق الفوري من عزل المكونات.

\n\n

هيكل المشروع: كيفية تنظيم المجلدات

\n\n

لا يوجد معيار واحد، لكن إليك مخططاً مثبتاً يستخدم في مشاريع الإنتاج:

\n\n
myapp/\n├── cmd/\n│   └── app/\n│       └── main.go          # نقطة الدخول، تجميع التبعيات\n├── internal/\n│   ├── core/\n│   │   ├── domain/          # الكيانات، كائنات القيمة\n│   │   ├── ports/           # الواجهات (المنافذ)\n│   │   └── services/        # منطق الأعمال (حالات الاستخدام)\n│   └── adapters/\n│       ├── api/             # محولات HTTP/gRPC\n│       ├── db/              # تطبيقات المستودعات\n│       └── mq/              # قوائم انتظار الرسائل\n└── go.mod\n
\n\n

هام: مجلد internal يمنع الاستيراد من الخارج - مثالي لحماية النواة. المحولات موجودة بشكل منفصل ويمكن استبدالها بسهولة.

\n\n

نكتب الكود: من الواجهات إلى التنفيذ

\n\n

لنقم بإنشاء خدمة بسيطة للعمل مع المستخدمين. نبدأ من النواة.

\n\n

الخطوة 1. المجال والمنافذ

\n\n
// internal/core/domain/user.go\npackage domain\n\nimport "time"\n\ntype User struct {\n    ID        string\n    Email     string\n    Name      string\n    CreatedAt time.Time\n}\n\n// internal/core/ports/repositories.go\npackage ports\n\nimport "myapp/internal/core/domain"\n\ntype UserRepository interface {\n    Save(user domain.User) error\n    FindByID(id string) (domain.User, error)\n    FindByEmail(email string) (domain.User, error)\                

المدونات

توصيات الكتب