🎯 Core Principles
All code in pkg/ must strictly adhere to:
- •
SOLID:
- •SRP: Each function/struct does ONE thing well.
- •OCP: Open for extension, closed for modification (use Interfaces).
- •LSP: Subtypes must be substitutable for base types.
- •ISP: Small, specific interfaces are better than large, general ones.
- •DIP: Depend on abstractions, not concretions.
- •
KISS (Keep It Simple, Stupid):
- •Avoid over-engineering.
- •Simple code is easier to debug and maintain.
- •
DRY (Don't Repeat Yourself):
- •Abstract common logic into reusable functions.
- •Single source of truth.
🏗️ OOP in Go
Use Go's idiomatic OOP features to ensure extensibility and clean code:
- •
Encapsulation:
- •Use private structs/fields (
lowerCase) for internal implementation. - •Expose only what is necessary via public methods (
PascalCase). - •Use
New...constructors to enforce initialization logic.
- •Use private structs/fields (
- •
Composition over Inheritance:
- •Embed structs to reuse behavior.
- •Use Interfaces to define behavior contracts.
- •
Polymorphism:
- •Accept Interfaces as function arguments, return Interfaces (or concrete types if strict).
📝 Coding Standards
- •Naming: Clear, descriptive names.
pkgfunctions are used everywhere, so ambiguity is expensive. - •Documentation: EVERY exported function/type MUST have a comment explaining what it does and why.
- •Coverage: Target >90% test coverage for
pkg. Bugs here propagate everywhere. - •Stability: Avoid breaking changes. Deprecate old methods before removing them.
Example
go
// ✅ GOOD: Defined Interface (DIP)
type Logger interface {
Info(msg string)
Error(msg string, err error)
}
// ✅ GOOD: Encapsulation & Composition
type FileLogger struct {
filterLevel string // Private
writer io.Writer
}
// Constructor
func NewFileLogger(w io.Writer) Logger {
return &FileLogger{
filterLevel: "INFO",
writer: w,
}
}
// Implementation
func (l *FileLogger) Info(msg string) {
// ... implementation
}