Standar Coding
Gaya Kode dan Konvensi
Mengikuti standar coding yang konsisten membuat codebase lebih mudah dibaca, dipelihara, dan dikontribusikan.
Standar Kode Go
Format Kode
Gunakan alat format Go standar:
# Format all code
gofmt -w .
# Use goimports for import organization
goimports -w .
Wajib: Semua kode Go harus lulus gofmt dan goimports sebelum commit.
Konvensi Penamaan
Paket:
- Huruf kecil, satu kata jika memungkinkan
package application,package events- Hindari underscore atau mixed caps
Nama Exported:
- PascalCase untuk tipe, fungsi, konstanta
type WebviewWindow struct,func NewApplication()
Nama Unexported:
- camelCase untuk tipe, fungsi, variabel internal
type windowImpl struct,func createWindow()
Interface:
- Dinamai berdasarkan perilaku:
Reader,Writer,Handler - Interface satu method: nama dengan akhiran
-er
// Good
type Closer interface {
Close() error
}
// Avoid
type CloseInterface interface {
Close() error
}Penanganan Error
Selalu periksa error:
// Good
result, err := doSomething()
if err != nil {
return fmt.Errorf("failed to do something: %w", err)
}
// Bad - ignoring errors
result, _ := doSomething()Gunakan error wrapping:
// Wrap errors to provide context
if err := validate(); err != nil {
return fmt.Errorf("validation failed: %w", err)
}Buat tipe error kustom jika diperlukan:
type ValidationError struct {
Field string
Value string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("invalid value %q for field %q", e.Value, e.Field)
}Komentar dan Dokumentasi
Komentar paket:
// Package application provides the core Wails application runtime.
//
// It handles window management, event dispatching, and service lifecycle.
package applicationDeklarasi exported:
// NewApplication creates a new Wails application with the given options.
//
// The application must be started with Run() or RunWithContext().
func NewApplication(opts Options) *Application {
// ...
}Komentar implementasi:
// processEvent handles incoming events from the runtime.
// It dispatches to registered handlers and manages event lifecycle.
func (a *Application) processEvent(event *Event) {
// Validate event before processing
if event == nil {
return
}
// Find and invoke handlers
// ...
}Struktur Fungsi dan Method
Jaga fungsi tetap fokus:
// Good - single responsibility
func (w *Window) setTitle(title string) {
w.title = title
w.updateNativeTitle()
}
// Bad - doing too much
func (w *Window) updateEverything() {
w.setTitle(w.title)
w.setSize(w.width, w.height)
w.setPosition(w.x, w.y)
// ... 20 more operations
}Gunakan early return:
// Good
func validate(input string) error {
if input == "" {
return errors.New("empty input")
}
if len(input) > 100 {
return errors.New("input too long")
}
return nil
}
// Avoid deep nestingConcurrency
Gunakan context untuk pembatalan:
func (a *Application) RunWithContext(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-a.done:
return nil
}
}Lindungi state bersama dengan mutex:
type SafeCounter struct {
mu sync.Mutex
count int
}
func (c *SafeCounter) Increment() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}Hindari goroutine leak:
// Good - goroutine has exit condition
func (a *Application) startWorker(ctx context.Context) {
go func() {
for {
select {
case <-ctx.Done():
return // Clean exit
case work := <-a.workChan:
a.process(work)
}
}
}()
}Testing
Penamaan file test:
// Implementation: window.go
// Tests: window_test.goTable-driven test:
func TestValidate(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
}{
{"empty input", "", true},
{"valid input", "hello", false},
{"too long", strings.Repeat("a", 101), true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validate(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}Standar JavaScript/TypeScript
Format Kode
Gunakan Prettier untuk format konsisten:
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
}Konvensi Penamaan
Variabel dan fungsi:
- camelCase:
const userName = "John"
Class dan tipe:
- PascalCase:
class WindowManager
Konstanta:
- UPPER_SNAKE_CASE:
const MAX_RETRIES = 3
TypeScript
Gunakan tipe eksplisit:
// Good
function greet(name: string): string {
return `Hello, ${name}`
}
// Avoid implicit any
function process(data) { // Bad
return data
}Definisikan interface:
interface WindowOptions {
title: string
width: number
height: number
}
function createWindow(options: WindowOptions): void {
// ...
}Format Pesan Commit
Gunakan Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>Tipe:
feat: Fitur barufix: Perbaikan bugdocs: Perubahan dokumentasirefactor: Refactoring kodetest: Menambah atau memperbarui teschore: Tugas maintenance
Contoh:
feat(window): add SetAlwaysOnTop method
Implement SetAlwaysOnTop for keeping windows above others.
Adds platform implementations for macOS, Windows, and Linux.
Closes #123fix(events): prevent event handler memory leak
Event listeners were not being properly cleaned up when
windows were closed. This adds explicit cleanup in the
window destructor.Panduan Pull Request
Sebelum Submit
- Kode lulus
gofmtdangoimports - Semua tes lulus (
go test ./...) - Kode baru memiliki tes
- Dokumentasi diperbarui jika diperlukan
- Pesan commit mengikuti konvensi
- Tidak ada konflik merge dengan
master
Template Deskripsi PR
## Description
Brief description of what this PR does.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
How was this tested?
## Checklist
- [ ] Tests pass
- [ ] Documentation updated
- [ ] No breaking changes (or documented)Proses Code Review
Sebagai Reviewer
- Bersikap konstruktif dan hormat
- Fokus pada kualitas kode, bukan preferensi pribadi
- Jelaskan mengapa perubahan disarankan
- Setujui setelah puas
Sebagai Author
- Tanggapi semua komentar
- Minta klarifikasi jika diperlukan
- Lakukan perubahan yang diminta atau jelaskan mengapa tidak
- Terbuka terhadap feedback
Praktik Terbaik
Performa
- Hindari optimisasi prematur
- Profil sebelum mengoptimalkan
- Gunakan benchmark untuk kode kritis performa
func BenchmarkProcess(b *testing.B) {
for i := 0; i < b.N; i++ {
process(testData)
}
}Keamanan
- Validasi semua input pengguna
- Sanitasi data sebelum ditampilkan
- Gunakan
crypto/randuntuk data acak - Jangan pernah log informasi sensitif
Dokumentasi
- Dokumentasikan API exported
- Sertakan contoh dalam dokumentasi
- Perbarui docs saat mengubah API
- Jaga README tetap mutakhir
Kode Spesifik Platform
Penamaan File
window.go // Common interface
window_darwin.go // macOS implementation
window_windows.go // Windows implementation
window_linux.go // Linux implementationBuild Tags
//go:build darwin
package application
// macOS-specific codeLinting
Jalankan linter sebelum commit:
# golangci-lint (recommended)
golangci-lint run
# Individual linters
go vet ./...
staticcheck ./...
Pertanyaan?
Jika Anda tidak yakin tentang standar apa pun:
- Periksa kode yang ada untuk contoh
- Tanya di Discord
- Buka diskusi di GitHub