0Pricing
Go Academy · درس

تركيب الواجهات وأفضل الممارسات

الواجهات الصغيرة وعكس اتجاه التبعيات

تركيب الواجهات وأفضل الممارسات درس مجاني في Go Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Go Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Go Academy 4 دروس في المجموع.

تركيب الواجهات

يمكن لواجهات Go تضمين واجهات أخرى لتركيب واجهات أكبر:

package main
import "io"

// io.ReadWriter composes Reader and Writer
type ReadWriter interface {
    io.Reader
    io.Writer
}

// Your own composition:
type Processor interface {
    io.Reader
    Process() error
    io.Closer
}

func main() { _ = (*Processor)(nil) }

مبدأ الواجهة الصغيرة

أقوى واجهات Go هي التي تحتوي على طريقة أو طريقتين. فهذا يزيد إلى أقصى حد عدد الأنواع التي يمكنها تحقيقها:

  • io.Reader — طريقة واحدة
  • io.Writer — طريقة واحدة
  • error — طريقة واحدة
  • fmt.Stringer — طريقة واحدة

يصعب إنشاء بدائل اختبار للواجهات الكبيرة واختبارها.

عكس الاعتماديات

اقبل الواجهات في معاملات الدوال بدلًا من الأنواع الملموسة. يفصل ذلك شفرتك عن تطبيقات محددة:

package main
import "fmt"

type Store interface {
    Get(key string) (string, bool)
    Set(key, val string)
}

func cache(s Store, key, value string) {
    if _, ok := s.Get(key); !ok {
        s.Set(key, value)
    }
}

type MapStore struct{ m map[string]string }
func (ms *MapStore) Get(k string) (string, bool) { v, ok := ms.m[k]; return v, ok }
func (ms *MapStore) Set(k, v string) { ms.m[k] = v }

func main() {
    s := &MapStore{m: map[string]string{}}
    cache(s, "x", "hello")
    v, _ := s.Get("x")
    fmt.Println(v)
}

فصل الواجهات

قسّم الواجهات الكبيرة إلى واجهات أصغر ومركّزة. تعتمد العملاء فقط على الطرق التي يستخدمونها:

package main

// Bad: large interface forces all methods
type BigStorage interface {
    Read(key string) string
    Write(key, val string)
    Delete(key string)
    List() []string
    Backup() error
}

// Good: small, focused interfaces
type Reader interface{ Read(key string) string }
type Writer interface{ Write(key, val string) }
type Lister interface{ List() []string }

func readAll(r Reader) {} // only needs Read

func main() { _ = readAll }

إرجاع الأنواع الملموسة

يجب أن تُرجع البُناة أنواعًا ملموسة، لا واجهات. ويمكن للمتصلين دائمًا إسناد نوع ملموس إلى متغير واجهة:

package main

type Logger interface{ Log(string) }
type ConsoleLogger struct{}
func (c *ConsoleLogger) Log(s string) {}

// Good: return concrete *ConsoleLogger
func NewConsoleLogger() *ConsoleLogger { return &ConsoleLogger{} }

// Avoid: return Logger (hides the concrete type)
// func NewConsoleLogger() Logger { return &ConsoleLogger{} }

func main() { _ = NewConsoleLogger() }

تضخم الواجهات

لا تنشئ واجهة لكل نوع «تحسبًا للحاجة إليها». أنشئ الواجهات فقط عندما:

  • تكون لديك تطبيقات متعددة الآن أو قريبًا
  • تحتاج إلى إنشاء بديل للاعتمادية في الاختبارات
  • تكون بصدد إنشاء مكتبة وتريد فصل المتصلين عن التطبيق

تضمين الواجهات للتوسعة

ضمّن واجهة لإضافة طرق اختيارية مع قيم افتراضية:

package main
import "fmt"

type Handler interface{ Handle(msg string) }
type NamedHandler interface {
    Handler
    Name() string
}

func dispatch(h Handler) {
    if nh, ok := h.(NamedHandler); ok {
        fmt.Printf("[%s] ", nh.Name())
    }
    h.Handle("event")
}

type MyHandler struct{}
func (m MyHandler) Handle(msg string)  { fmt.Println(msg) }
func (m MyHandler) Name() string       { return "my" }

func main() { dispatch(MyHandler{}) }

إنشاء بدائل اختبار باستخدام الواجهات

عرّف الاعتماديات كواجهات، وحقن البدائل في الاختبارات:

package main
import "fmt"

type Clock interface{ Now() int64 }

type MockClock struct{ T int64 }
func (m MockClock) Now() int64 { return m.T }

func isExpired(c Clock, expiresAt int64) bool {
    return c.Now() > expiresAt
}

func main() {
    mc := MockClock{T: 1000}
    fmt.Println(isExpired(mc, 500))  // true
    fmt.Println(isExpired(mc, 1500)) // false
}

تضمين الواجهات مقابل تضمين البنى لإعادة الاستخدام

استخدم تضمين الواجهات لتركيب واجهة برمجة التطبيقات، وتضمين البنى لإعادة استخدام الشفرة. فلكل منهما غرض مختلف، ولا ينبغي الخلط بينهما.

اكتشاف توافق الواجهة وقت الترجمة

استخدم فحصًا وقت الترجمة باستخدام معرّف فارغ للتحقق من أن نوعك يحقق واجهة:

package main

type Doer interface{ Do() }
type MyType struct{}
func (m *MyType) Do() {}

// Compile-time check — no runtime cost
var _ Doer = (*MyType)(nil)

func main() {}

تحقق سريع

متى ينبغي لك تعريف واجهة جديدة في Go؟

مراجعة: أفضل ممارسات الواجهات

أهم النقاط:

  • أبقِ الواجهات صغيرة — طريقة أو طريقتان
  • ركّب الواجهات من واجهات أصغر
  • اقبل الواجهات وأرجع أنواعًا ملموسة
  • أنشئ الواجهات من أجل قابلية الاختبار وتعدد التطبيقات
  • استخدم فحص الإسناد إلى معرّف فارغ وقت الترجمة

مهمة تدريبية

صمّم واجهة Notifier تحتوي على Notify(msg string) error. طبّقها في EmailNotifier وSMSNotifier. اكتب دالة broadcast ترسل إلى قيمة من النوع []Notifier.

الأسئلة الشائعة

هل درس «تركيب الواجهات وأفضل الممارسات» مجاني؟

نعم — نص درس «تركيب الواجهات وأفضل الممارسات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Go Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Go Academy 4 دروس في المجموع.

ماذا ستتعلم في «تركيب الواجهات وأفضل الممارسات»؟

الواجهات الصغيرة وعكس اتجاه التبعيات تتمرن على Go Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Go Academy؟

لا تُشترط خبرة سابقة. Go Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «تركيب الواجهات وأفضل الممارسات»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Go Academy هذا؟

نعم. كل درس في Go Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تعريف الواجهات وتنفيذها
  2. واجهات مكتبة Go القياسية الأساسية
  3. تأكيدات الأنواع وعبارات type switch
  4. تركيب الواجهات وأفضل الممارسات
← العودة إلى Go Academy