Design principles¶
The eight rules the codebase keeps to:
- No base classes. No inheritance. No registration. No config files. One exception,
named:
Outlet. Anything you write against a shape is a structuralProtocoland needs no base —Source,Target,VectorFilter.Outletis a base class because it is not a shape: it is sixty lines of running code — a paced daemon thread with compensated timing, a latest-wins slot, per-error-kind deduplication — and the alternative to inheriting it is copying it once per transport. Subclass it to add_send. Nothing else in the library asks you to subclass anything. - User code is plain functions:
extract(),train(),predict(). - Every public function has typed arguments and a typed return.
- One name, one meaning. No overloaded types.
- Errors tell you what to write, not what went wrong.
- The entire public API fits on one page.
- Each widget is a single public function, no inheritance. Implementation may be split into a private subpackage of
_<aspect>.pyhelpers (state, plot, controls) when a widget grows beyond ~200 LOC. Seewidgets/signals/viewer.pyplus its_state.py/_plot.py/_controls.pyhelpers for the reference pattern. Aim to keep the public entry file under 200 lines and any single helper under ~350. - Immediate-mode rendering. Widget state, when needed, is keyed by widget identity and lives in a private
_<widget>_state.pymodule.
These aren't aesthetic preferences. They're a hard contract: a library small enough to fit in one LLM context window, where every widget is a single function with no class hierarchy.