Starphix
Software Engineering / Sources
The Lab / Sources / Software Engineering / Languages/Language-Agnostic-Principles.md

Language-Agnostic Principles

Universal patterns that apply regardless of programming language.


Core Principles

Write Code for Humans First

  • Names reveal intent — calculateMonthlyPayment > calc(x, y)
  • Functions do one thing — Small, focused, composable
  • Types as documentation — Prefer expressive types over comments
  • Explicit over implicit — No magic; behavior visible from call site

Favor Composition Over Inheritance

  • Interfaces/protocols define contracts
  • Inject dependencies; don't hardcode
  • Decorate/wrap rather than subclass

Handle Errors as Values

  • Result/Option types > exceptions for expected failures
  • Exceptions only for truly exceptional (unrecoverable) cases
  • Fail fast with context; recover gracefully where possible

Manage State Explicitly

  • Immutable by default; mutate deliberately
  • Pure functions where possible; isolate side effects
  • State machines for complex workflows

Concurrency Without Shared Mutable State

  • Message passing / channels / actors
  • Immutable data structures
  • Structured concurrency (scoped tasks, cancellation)

Universal Patterns

Pattern Description
Repository Collection-like interface for data access
Unit of Work Track changes; commit atomically
Factory Encapsulate complex creation
Strategy Swap algorithms at runtime
Observer/Events Decouple producers from consumers
Decorator Add behavior without modifying core
Adapter Bridge incompatible interfaces
Circuit Breaker Fail fast under sustained errors
Retry with Backoff Handle transient failures
Saga Distributed transaction compensation

Cross-Language Concerns

Concern Guidance
Serialization Use schema-first (Protobuf, Avro, JSON Schema); version explicitly
API Contracts OpenAPI/gRPC; consumer-driven contracts (Pact)
Observability Structured logs (JSON); OpenTelemetry; correlation IDs
Configuration 12-factor: env vars for config, secrets in vault
Testing Pyramid: unit (70%) → integration (20%) → E2E (10%); contract tests at boundaries
Dependencies Lockfiles committed; private registry; SBOM generation
Security SAST in CI; dependency scanning; signed artifacts

Polyglot System Design

Service Boundaries = Language Boundaries

  • Each service owns its data + language choice
  • Communicate via well-defined contracts (gRPC, REST, async)
  • Shared libraries only for truly universal utilities

Shared Conventions Across Languages

  • Logging format — Same JSON schema, same field names
  • Error format — Consistent error codes, messages, retryability
  • Health checks — /health + /ready endpoints standard
  • Metrics — Prometheus exposition format; same naming conventions
  • Tracing — W3C TraceContext propagation everywhere

Language Selection Criteria

Factor Weight
Team expertise High
Ecosystem maturity (libs, tooling) High
Performance requirements Medium
Domain fit (data science, systems, web) Medium
Hiring pool Medium
Operational maturity (debugging, profiling) High
Long-term support High

  • TypeScript JavaScript — Modern JS/TS patterns
  • Python — Pythonic patterns, tooling
  • Go — Go idioms, concurrency
  • Rust — Ownership, borrowing, async
  • JVM Kotlin Scala — JVM ecosystem patterns
  • Architectural Styles — Modular monolith vs microservices
  • Design Patterns — Patterns across paradigms

Sources: Clean Code (Martin Fowler), Effective Software Architecture, Google Engineering Practices, Microsoft Patterns & Practices, Twelve-Factor App

From the Software Engineering research vault · CC BY 4.0 · all notes · raw markdown