Skip to content

Instantly share code, notes, and snippets.

@MaxwellBo
Last active February 18, 2026 04:29
Show Gist options
  • Select an option

  • Save MaxwellBo/6bf85a7c872b3bc6d106a2875ec11446 to your computer and use it in GitHub Desktop.

Select an option

Save MaxwellBo/6bf85a7c872b3bc6d106a2875ec11446 to your computer and use it in GitHub Desktop.

Max's personal engineering philosphy

Engineering philosophy

Things I like

Things I don't like

  • Tailwind
  • Shell scripts
  • Python

General

  • Pass, don't validate (from https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)
  • Log, or rethrow an exception. Never both.
  • Fakes belong next to the real implementation (not in the test directory!) because they often contain a lot of implementation details. This allows the fake to be tested, dependency injected with less config, and exported to consumers of the API to use in their own tests
  • If you can get away with it, put tests alongside the implementation, like Rust, or Python doctests. Yes, fakes need to be tested too.
  • All test data must be generated using a Property Based Testing framework. All data types T should have an acompanying Arbitrary<T>.
  • Never call an implementation ...Impl. Given an interface Cache, don't call it CacheImpl! If it uses an in-memory hashmap, call it InMemoryCache. Someone can come along and create a RedisCache without renaming everything!
  • Interfaces should be reasonably small. If it gets too big (more than 5 methods?), split it. This will make it easier to write fakes.
  • Don't store booleans, store datetimes (from https://changelog.com/posts/you-might-as-well-timestamp-it)

Code dirty

from https://htmx.org/essays/codin-dirty/ and https://htmx.org/essays/locality-of-behaviour/

  1. Strive for Locality of Behaviour. Don't spread logic across multiple files if it can reasonably live together. "Spooky action at a distance" is a maintenance liability. When LoB conflicts with DRY or Separation of Concerns, use judgment — a violation a few lines away is far less severe than one in a separate file.
  2. Big functions are fine. A few large "crux" functions (up to 200–400 LOC) are acceptable and often preferable — they keep important logic visible and together rather than smeared across dozens of tiny abstractions. Support functions: ~10–20 LOC. Utilities: ~5–10 LOC. Don't split functions just to keep them small; only split for genuine reuse or clarity.
  3. Prefer integration tests over unit tests. Avoid heavy unit testing early on before abstractions have settled — it locks you into implementation details. Once the core API has crystallised, test it exhaustively at the integration level. Integration tests survive refactors; unit tests often don't. TDD is fine but apply it at the API level, not the unit level.
  4. Keep class/concept count low. Resist the urge to decompose everything into single-responsibility micro-classes. Fewer concepts = less cognitive overhead. It's fine for a class to serve multiple layers (e.g. an ORM model that also supports view logic). Prefer a longer if/else over unnecessary polymorphism and new abstractions.

Design philosophy

  • Emergent over prescribed aesthetics.
  • Expose state and inner workings.
  • Dense, not sparse.
  • Explicit is better than implicit.
  • Engineered for human vision and perception.
  • Regiment functionalism.
  • Performance is design.
  • Verbosity over opacity.
  • Ignore design trends. Timeless and unfashionable.
  • Flat, not hierarchical.
  • Diametrically opposite of minimalism, as complex as it needs to be.
  • Driven by objective reasoning and common sense.
  • Don't infantilize users.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment