Home

Engineering Principles

Principles guiding my approach to engineering and development.

Principles that guide my approach to building software and leading engineering teams. These have been refined through years of building systems that need to work reliably and teams that need to move quickly.

Code Quality & Design

Simplicity over cleverness - Write code that the next developer can understand quickly. Clever solutions often become maintenance nightmares.

Fail fast and explicitly - Make errors visible immediately rather than letting them propagate. Silent failures are debugging nightmares.

Composition over inheritance - Build systems from small, focused components rather than deep inheritance hierarchies. It’s easier to reason about and test.

Single responsibility principle - Each function, class, or service should have one clear purpose. When something does multiple things, it becomes harder to change and test.

Architecture & Systems

Boring technology wins - Choose proven, stable technologies over the latest shiny framework. Users care about working software, not the tech stack.

Design for failure - Systems will fail. Plan for graceful degradation, timeouts, retries, and circuit breakers from the start.

Services should be stateless - particularly in backend systems to reduce side effects and complexity. Less state means fewer bugs and easier reasoning. Persistence stores (databases, caches) handle state while services follow functional approaches. This also makes scaling, profiling and deployments simpler.

Measure before optimizing - Performance problems are often where we don’t expect them. Profile first, then optimize the actual bottlenecks.

Development Process

Automate repetitive tasks - If done more than twice, script it. Humans are bad at repetitive tasks and computers are good at them.

Version everything - Code, configuration, infrastructure, and documentation should all be versioned and reproducible.

Test the behavior, not the implementation - Tests should verify what the system does, not how it does it. Implementation details change; behavior should remain stable.

Deploy small changes frequently - Large deployments are risky. Small, frequent changes are easier to debug and roll back.

Team & Communication

Code is communication - Write code for humans first, computers second. Clear variable names and structure matter more than performance micro-optimizations.

Document decisions, not just code - Explain why choices were made, not just what the code does. Future maintainers need context.

Shared ownership of code - No single person should be the only one who understands a critical system. Knowledge silos are risk.

Pragmatic over perfect - Ship working software that solves real problems rather than perfect software that never gets used.

Leadership & Management

Lead by example - Write code, review pull requests, and solve technical problems alongside the team. Credibility comes from doing the work, not just directing it.

Remove blockers, don’t create them - A manager’s job is to clear the path for teams to do their best work. Every process should add value or be eliminated.

Invest in people - Career growth and skill development aren’t nice-to-haves. Teams with growing engineers build better software and stay longer.

Context over control - Give teams the information they need to make good decisions rather than micromanaging implementation choices.

Systems thinking - Technical debt, team dynamics, and process inefficiencies compound over time. Address root causes, not just symptoms.

Measure what matters - Track metrics that actually indicate team health and delivery effectiveness. Vanity metrics distract from real problems.

2025 Tawsif Aqib. All Rights Reserved.

Location: Eindhoven, Netherlands