Interface-Based Design
Interfeysga asoslangan dizayn
"Interface Design" kursida interfeyslarning texnik tomonlarini (kichik saqlash, qayerda e'lon qilish) ko'rgan edingiz. Endi shu bilimni arxitektura darajasida qo'llaymiz: butun dasturni bir-biriga bog'liq bo'lmagan, interfeys orqali gaplashadigan qismlarga bo'lish.
Buni elektr rozetkasiga o'xshating: rozetka "standart shakl"ni taqdim etadi, va siz unga choynak ham, kompyuter ham, telefon zaryadlagichi ham ulashingiz mumkin — rozetkaning o'zi ichida qanday qurilma borligini "bilishi" shart emas. Kodda ham xuddi shunday: bir qism (masalan Service) boshqa qismning (Logger) aniq turini emas, faqat uning "interfeysi"ni biladi.
package main
import "fmt"
type Logger interface {
Log(msg string)
}
type ConsoleLogger struct{}
func (c ConsoleLogger) Log(msg string) { fmt.Println("[LOG]", msg) }
type Service struct {
logger Logger
}
func NewService(logger Logger) *Service {
return &Service{logger: logger}
}
func (s *Service) DoWork() {
s.logger.Log("ish bajarildi")
}
func main() {
svc := NewService(ConsoleLogger{})
svc.DoWork()
}Service struct'i logger Logger maydoniga ega — aniq ConsoleLogger turiga emas, balki interfeysga. Bu shuni anglatadi: agar ertaga faylga yozadigan FileLogger yoki hech narsa qilmaydigan NoOpLogger yaratsangiz, Servicening kodini birorta ham qatorini o'zgartirmasdan ularni ishlata olasiz — faqat NewServicega boshqa argument berasiz.
Bu — real loyihalarda testlash uchun ham hayotiy ahamiyatga ega: testda haqiqiy ConsoleLogger o'rniga, xabarlarni shunchaki ro'yxatga yig'ib boradigan soxta logger berish mumkin ("Mocking Dependencies" darsida ko'rgan naqsh) — Servicening o'zi buni sezmaydi ham.
>_ Exercise
Ikkita implementatsiyaga ega Storage interfeysini yarating.
- •Storage interfeysini yozing: Save(key, value string)
- •MemoryStorage struct'i (map[string]string) yozing, Save metodi bilan
- •Cache struct'i (storage Storage maydoni) yozing, NewCache(s Storage) *Cache konstruktori bilan
- •Cache.Set(key, value string) metodi — ichki storage.Save'ni chaqirsin
- •NewCache(&MemoryStorage{data: map[string]string{}}) yaratib, Set("til", "go") chaqiring, so'ng MemoryStorage.data["til"]ni chop eting
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
Interfeysga asoslangan dizaynda komponentlar bir-birining aniq turini emas, faqat kerakli xatti-harakatni (interfeysni) bilishadi — bu ularni bog'liqlikdan xoli, mustaqil almashtirish mumkin qiladi.
NEXT UP
Dependency Injection
$ go run main.go
Kodingizni ishga tushiring