Pola Arsitektur
Ikhtisar
Section titled “Ikhtisar”Pola terbukti untuk mengorganisasi aplikasi Wails Anda.
Pola Service Layer
Section titled “Pola Service Layer”Struktur
Section titled “Struktur”app/├── main.go├── services/│ ├── user_service.go│ ├── data_service.go│ └── file_service.go└── models/ └── user.goImplementasi
Section titled “Implementasi”// Service interfacetype UserService interface { Create(email, password string) (*User, error) GetByID(id int) (*User, error) Update(user *User) error Delete(id int) error}
// Implementationtype userService struct { app *application.App db *sql.DB}
func NewUserService(app *application.App, db *sql.DB) UserService { return &userService{app: app, db: db}}Pola Repository
Section titled “Pola Repository”Struktur
Section titled “Struktur”// Repository interfacetype UserRepository interface { Create(user *User) error FindByID(id int) (*User, error) Update(user *User) error Delete(id int) error}
// Service uses repositorytype UserService struct { repo UserRepository}
func (s *UserService) Create(email, password string) (*User, error) { user := &User{Email: email} return user, s.repo.Create(user)}Arsitektur Event-Driven
Section titled “Arsitektur Event-Driven”Event Bus
Section titled “Event Bus”type EventBus struct { app *application.App listeners map[string][]func(interface{}) mu sync.RWMutex}
func (eb *EventBus) Subscribe(event string, handler func(interface{})) { eb.mu.Lock() defer eb.mu.Unlock() eb.listeners[event] = append(eb.listeners[event], handler)}
func (eb *EventBus) Publish(event string, data interface{}) { eb.mu.RLock() handlers := eb.listeners[event] eb.mu.RUnlock()
for _, handler := range handlers { go handler(data) }}Penggunaan
Section titled “Penggunaan”// SubscribeeventBus.Subscribe("user.created", func(data interface{}) { user := data.(*User) sendWelcomeEmail(user)})
// PublisheventBus.Publish("user.created", user)Dependency Injection
Section titled “Dependency Injection”DI Manual
Section titled “DI Manual”type App struct { userService *UserService fileService *FileService db *sql.DB}
func NewApp() *App { db := openDatabase()
return &App{ db: db, userService: NewUserService(db), fileService: NewFileService(db), }}Menggunakan Wire
Section titled “Menggunakan Wire”//go:build wireinject
func InitializeApp() (*App, error) { wire.Build( openDatabase, NewUserService, NewFileService, NewApp, ) return nil, nil}Manajemen State
Section titled “Manajemen State”State Terpusat
Section titled “State Terpusat”type AppState struct { currentUser *User settings *Settings mu sync.RWMutex}
func (s *AppState) SetUser(user *User) { s.mu.Lock() defer s.mu.Unlock() s.currentUser = user}
func (s *AppState) GetUser() *User { s.mu.RLock() defer s.mu.RUnlock() return s.currentUser}Praktik Terbaik
Section titled “Praktik Terbaik”✅ Lakukan
Section titled “✅ Lakukan”- Pisahkan concern
- Gunakan interface
- Inject dependensi
- Tangani error dengan benar
- Jaga service tetap fokus
- Dokumentasikan arsitektur
❌ Jangan
Section titled “❌ Jangan”- Jangan buat god object
- Jangan coupling komponen terlalu ketat
- Jangan lewatkan penanganan error
- Jangan abaikan concurrency
- Jangan over-engineer
Langkah Selanjutnya
Section titled “Langkah Selanjutnya”- Keamanan - Praktik terbaik keamanan
- Praktik Terbaik - Praktik terbaik bindings