Skip to content

Code Patterns

Go idioms and patterns used throughout ELMOS.


Dependency Injection

ELMOS uses constructor injection for all domain services. The App struct wires everything:

// core/app/app.go
func New(exec executor.Executor, fs filesystem.FileSystem, cfg *config.Config) *App {
    ctx := elcontext.New(cfg, exec, fs)
    printer := ui.NewPrinter()
    tm := toolchain.NewManager(exec, fs, cfg, printer)

    return &App{
        Exec:          exec,
        FS:            fs,
        Config:        cfg,
        Context:       ctx,
        KernelBuilder: builder.NewKernelBuilder(exec, fs, cfg, ctx, tm),
        ModuleBuilder: builder.NewModuleBuilder(exec, fs, cfg, ctx, tm),
        QEMURunner:    emulator.NewQEMURunner(exec, fs, cfg, ctx),
        // ...
    }
}

Benefits:

  • Testable - inject mocks
  • Explicit dependencies
  • No global state

Interface Abstraction

Domain defines interfaces, infra implements:

// Domain expects:
type Executor interface {
    Run(ctx context.Context, name string, args ...string) error
    RunWithEnv(ctx context.Context, env []string, name string, args ...string) error
    Output(ctx context.Context, name string, args ...string) ([]byte, error)
}

// Infra provides:
type ShellExecutor struct{}  // Real implementation
type MockExecutor struct{}   // Test mock

This allows unit testing domain logic without real shell commands.


Error Handling

Custom Error Types

// core/context/errors.go
type contextError struct {
    code    string
    message string
    cause   error
}

func (e *contextError) Error() string { return e.message }
func (e *contextError) Unwrap() error { return e.cause }

Error Constructors

func ImageError(msg string, cause error) error {
    return &contextError{code: "IMAGE", message: msg, cause: cause}
}

func ConfigError(msg string, cause error) error {
    return &contextError{code: "CONFIG", message: msg, cause: cause}
}

Usage

if !ctx.IsMounted() {
    return ImageError("kernel volume not mounted", ErrNotMounted)
}

Configuration Pattern

Struct with Tags

// core/config/types.go
type Config struct {
    Image  ImageConfig  `mapstructure:"image"`
    Build  BuildConfig  `mapstructure:"build"`
    QEMU   QEMUConfig   `mapstructure:"qemu"`
    Paths  PathsConfig  `mapstructure:"paths"`
}

Computed Defaults

// core/config/loader.go
func applyComputedDefaults(cfg *Config) {
    if cfg.Paths.ProjectRoot == "" {
        cfg.Paths.ProjectRoot, _ = os.Getwd()
    }
    // Derive other paths from ProjectRoot...
}

Embedded Assets

Templates embedded at compile time:

// assets/embed.go
//go:embed templates/*
var Templates embed.FS

func GetModuleTemplate() ([]byte, error) {
    return Templates.ReadFile("templates/module/module.c.tmpl")
}

Used for scaffolding new modules/apps.


Command Registration

Grouped Commands

// core/app/commands/register.go
func Register(ctx *Context, root *cobra.Command) {
    // Core commands
    root.AddCommand(BuildInit(ctx))
    root.AddCommand(BuildDoctor(ctx))

    // Build commands
    root.AddCommand(BuildKernel(ctx))
    root.AddCommand(BuildModule(ctx))

    // Runtime commands
    root.AddCommand(BuildQEMU(ctx))
}

Command Context

All commands share a context:

type Context struct {
    Exec          executor.Executor
    FS            filesystem.FileSystem
    Config        *config.Config
    KernelBuilder *builder.KernelBuilder
    Printer       *ui.Printer
    // ...
}

Printer Pattern

Styled output with verbosity control:

// core/ui/printer.go
type Printer struct{}

func (p *Printer) Step(format string, args ...interface{})    // → prefix
func (p *Printer) Success(format string, args ...interface{}) // ✓ prefix
func (p *Printer) Error(format string, args ...interface{})   // ✗ prefix
func (p *Printer) Info(format string, args ...interface{})    // ℹ prefix
func (p *Printer) Warn(format string, args ...interface{})    // ⚠ prefix

Testing Patterns

Table-Driven Tests

func TestValidateMachine(t *testing.T) {
    tests := []struct {
        name    string
        machine string
        want    bool
    }{
        {"valid", "virt", true},
        {"invalid", "nonexistent", false},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            // ...
        })
    }
}

Mock Executor

type MockExecutor struct {
    outputs map[string][]byte
}

func (m *MockExecutor) Output(ctx context.Context, name string, args ...string) ([]byte, error) {
    return m.outputs[name], nil
}

Naming Conventions

Type Convention Example
Interface Noun Executor, FileSystem
Struct Noun KernelBuilder, QEMURunner
Constructor New* NewKernelBuilder()
Method Verb Build(), Run(), Configure()
Error *Error ImageError(), ConfigError()