agentleFS
AnyOrgNameAnyOrgName/php-skills/skills/ai-rules/strategy-explicit-over-magic/SKILL.md

strategy-explicit-over-magic

Skill4 starsChanged 4 months agoMITView on GitHub

Prefer explicit, readable code over clever magic; declare real properties and methods instead of relying on dynamic properties, __call, or global state that hides what the code actually does. Use when the task asks for clear, readable, maintainable code, or the code will be read and extended by a team over time; the task is to untangle or clarify code that currently relies on magic methods, global state, or clever indirection; the design is tempted to use dynamic properties, __call, __get, or global state to avoid writing out explicit members. Keywords: strategy, explicit, magic, readable, dynamic, magic-methods, global-state, clever, obvious, clarity.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 6 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not fight a framework's own well-documented magic — such as an ORM's dynamic attributes — when using it is the established, expected …

    line 66
  2. Distinctive:

    Do not impose full explicitness ceremony on a tiny throwaway script that will run once and never be read again.

    line 68
  3. Distinctive:

    Never introduce dynamic properties, __call, or global state to save a few lines when an explicit property, method, or dependency would read …

    line 88
  4. Distinctive:

    Prefer declared properties, named methods, and passed-in dependencies so a reader can follow the data and control flow without running the …

    line 93
  5. Distinctive:

    Avoid global variables, singletons, and magic methods that let distant code change behavior invisibly.

    line 98
  6. Distinctive:

    Not applicable — no I/O, auth, or untrusted input.

    line 148

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- generated: do not edit — source: knowledge/atoms/ai-rules/strategy-explicit-over-magic/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->

Strategy — Explicit Over Magic

When to use

  • The task asks for clear, readable, maintainable code, or the code will be read and extended by a team over time.
  • The task is to untangle or clarify code that currently relies on magic methods, global state, or clever indirection.
  • The design is tempted to use dynamic properties, __call, __get, or global state to avoid writing out explicit members.

When NOT to use

  • Do not fight a framework's own well-documented magic — such as an ORM's dynamic attributes — when using it is the established, expected idiom.
  • Do not impose full explicitness ceremony on a tiny throwaway script that will run once and never be read again.

Core guidance

  • Declare real properties instead of dynamic ones — Declare each property the class uses with a type, rather than assigning arbitrary dynamic properties at runtime.
  • Keep control flow visible and traceable — Keep control flow explicit — return values, thrown exceptions, and direct calls — rather than triggering behavior through hidden hooks or side-effectful magic getters.
  • Inject dependencies instead of reaching for globals — Pass dependencies in through the constructor or method parameters rather than reaching for global variables, static singletons, or superglobals inside the body.
  • Name things after intent, not mechanism — Give variables, methods, and classes names that state what they mean, and prefer a slightly longer obvious construct over a terse clever one.
  • Write named methods instead of __call routing — Write out the methods a class supports as real named methods rather than routing unknown calls through __call or __callStatic.

Never

  • Never introduce dynamic properties, __call, or global state to save a few lines when an explicit property, method, or dependency would read clearly.

Prefer

  • Prefer declared properties, named methods, and passed-in dependencies so a reader can follow the data and control flow without running the code.

Avoid

  • Avoid global variables, singletons, and magic methods that let distant code change behavior invisibly; make every dependency and side effect visible at the call site.

Escalate to user when

  • Escalate to the user when a requirement seems to genuinely need a magic mechanism — a proxy, an ORM's __get, or a framework macro — and confirm the trade-off before relying on it.

Quick recipe

  1. Identify each magic mechanism in the code — dynamic properties, __call, globals, side-effectful accessors — and note the concrete members or dependencies it stands in for. (verify: You have a list of each magic point and the explicit property, method, or parameter it should become.)
  2. Replace each magic point with a declared property, a named method, or an injected dependency, and confirm behavior is unchanged with the existing tests. (verify: No dynamic property, __call route, or global read remains where an explicit member now exists, and the tests still pass.)

Anti-patterns

Anti-patternWhy it failsDo instead
Pulling config from a global singleton mid-logicThe hidden dependency makes the function impossible to understand or test in<br>isolation and couples it to global setup order.Accept the configuration or service as an explicit constructor or method<br>parameter so the dependency is visible and injectable.
A magic getter that performs side effectsReaders assume reading a property is cheap and pure; hiding a database call or<br>mutation there produces surprising cost and bugs.Expose the behavior as an explicitly named method whose name signals that work<br>happens, such as loadOrders rather than a magic orders property.
Stringly-typed dynamic dispatch on user dataDynamic dispatch on strings hides the set of valid actions from tooling and can<br>become an execution hole when the string is externally influenced.Use an explicit match or an allowlisted map from known keys to concrete handlers,<br>so the valid actions are visible and bounded.

See references/anti-patterns.md.

Common mistakes

  1. Global state makes behavior order-dependent — Reading and writing global or static state makes a function's result depend on what ran before it, not just its arguments. Fix: Pass the needed state in as parameters or injected dependencies so each call is self-contained and reproducible.
  2. __call hides the real API from tooling — Routing calls through __call means the class's real methods are invisible to autocomplete, refactoring tools, and static analysis. Fix: Declare each supported method explicitly; if a large surface must be generated, emit real method stubs rather than dispatching through __call.
  3. A typo silently creates a new dynamic property — With dynamic properties, a misspelled assignment quietly creates a new property instead of raising an error. Fix: Declare properties explicitly so a misspelled name is a clear error, and enable strict property handling where the runtime supports it.

Version notes

  • Explicit-over-magic discipline is version-agnostic (PHP >=7.4) — Preferring explicit code over magic is a strategy that applies to any PHP version; it constrains which mechanisms the agent leans on, not which language features exist, so it holds from PHP 7.4 upward.

Security

  • Not applicable — no I/O, auth, or untrusted input.

Testing

  • Activation and decision behavior are verified in eval/scenarios/ai-rules/strategy-explicit-over-magic.yaml.

Additional resources

  • references/anti-patterns.md
  • references/examples.md
  • references/pitfalls.md
  • references/recipes.md
  • references/version-differences.md

Knowledge graph

Related: ai-rules/strategy-minimal-diff, php/typed-properties

<!-- graph-fragment: graph/fragments/ai-rules/strategy-explicit-over-magic.yaml -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.