مبادئ SOLID في Go: من النظرية إلى التطبيق بلغة Golang

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

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

ابدأ الدورة

مبادئ SOLID في Go: النظرية والتطبيق من الألف إلى الياء



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



1. مبدأ المسؤولية الواحدة (SRP)



الجوهر: يجب أن يكون لكل وحدة أو هيكل أو دالة سبب واحد فقط للتغيير. بمعنى آخر، يجب أن تكون مسؤولة عن مهمة واحدة محددة بوضوح.



المشكلة: غالبًا ما يضع المطورون كل المنطق في هيكل واحد: التحقق، الحفظ في قاعدة البيانات، إرسال البريد الإلكتروني، تنسيق الرد. يؤدي هذا إلى "كائنات إلهية" يصعب اختبارها وتعديلها.



الحل في Go: قسّم المسؤولية بين هياكل وحزم مختلفة.



// ❌ سيء: هيكل واحد يفعل كل شيءtype UserService struct {    db *sql.DB    mailer *Mailer}

func (s *UserService) CreateUser(name, email string) error { // 1. التحقق if !strings.Contains(email, "@") { return errors.New("بريد إلكتروني غير صالح") } // 2. الحفظ في قاعدة البيانات _, err := s.db.Exec("INSERT INTO users (name, email) VALUES ($1, $2)", name, email) if err != nil { return err } // 3. إرسال بريد ترحيبي return s.mailer.Send(email, "مرحبًا!", "شكرًا لتسجيلك")}

// ✅ جيد: فصل المسؤولياتtype UserValidator struct{}func (v *UserValidator) Validate(email string) error { if !strings.Contains(email, "@") { return errors.New("بريد إلكتروني غير صالح") } return nil}

type UserRepository struct { db *sql.DB}func (r *UserRepository) Save(name, email string) error { _, err := r.db.Exec("INSERT INTO users (name, email) VALUES ($1, $2)", name, email) return err}

type WelcomeMailer struct { mailer *Mailer}func (m *WelcomeMailer) Send(email string) error { return m.mailer.Send(email, "مرحبًا!", "شكرًا لتسجيلك")}

type UserService struct { validator *UserValidator repo *UserRepository mailer *WelcomeMailer}

func (s *UserService) CreateUser(name, email string) error { if err := s.validator.Validate(email); err != nil { return err } if err := s.repo.Save(name, email); err != nil { return err } return s.mailer.Send(email)}


نصيحة عملية: إذا لم تستطع وصف ما تفعله دالتك أو طريقتك بإيجاز دون استخدام حرف العطف "و"، فمن المحتمل أن مبدأ SRP قد انتهك.



2. مبدأ مفتوح-مغلق (OCP)



الجوهر: يجب أن تكون الكيانات البرمجية (الهياكل، الدوال، الحزم) مفتوحة للتمديد ولكن مغلقة للتعديل. هذا يعني أنه يجب أن تكون قادرًا على إضافة سلوك جديد دون تغيير الكود الموجود.



الحل في Go: استخدم الواجهات لتجريد السلوك.



// ❌ سيء: عند إضافة نوع دفع جديد، يجب تعديل دالة ProcessPaymenttype PaymentProcessor struct{}

func (p *PaymentProcessor) Process(paymentType string, amount float64) { if paymentType == "credit_card" { // منطق لبطاقة الائتمان } else if paymentType == "paypal" { // منطق لـ PayPal } // عند إضافة "crypto" — يجب إضافة else if جديد}

// ✅ جيد: الواجهة تسمح بتوسيع الوظائف دون تغيير الكودtype PaymentMethod interface { Pay(amount float64) error}

type CreditCard struct{}func

المدونات

توصيات الكتب