Skip to content

Restructure tutorial#66

Merged
darkleaf merged 44 commits into
masterfrom
doc
Jul 7, 2026
Merged

Restructure tutorial#66
darkleaf merged 44 commits into
masterfrom
doc

Conversation

@darkleaf

@darkleaf darkleaf commented Jun 3, 2026

Copy link
Copy Markdown
Owner

No description provided.

darkleaf and others added 30 commits June 3, 2026 23:29
- Rewrite tutorial chapters 1–11 with hooks, structured sections,
  and forward-references
- Add Why DI? as a top-level intro page
- Add How-to with Tips and Multi-arity services (moved from Tutorial)
- Add Reference section with a Middleware types stub
- Reorder cljdoc.edn TOC to match the new structure
- Update tutorial-to-md.sh to generate from how_to/ and reference/
- Update CI to commit the new doc subdirectories
- Add planning artifacts under doc/_journey.md and doc/_structure.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rewrite the last tutorial chapter: rename "Graceful stop" to
"Handling start failures", split the combined demo into two
focused tests (built-deps-are-stopped, stop-errors-are-suppressed),
and use inline ex-info throws instead of passing exceptions via
the registry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
File prefixes a..l now follow the v6 chapter order alphabetically:
a-your-first-system, b-dependencies, c-stopping-components,
d-interactive-development, e-registries, f-abstractions,
g-environment-variables, h-starting-many-keys, i-wiring-inside-data,
j-transforming-values, k-composition-with-update-key,
l-handling-start-failures.

Namespaces, internal cross-links, cljdoc.edn paths, and doc/example.md
and doc/why_di.md links are all updated. doc/example.md REPL-redef
link now points at "Interactive development" instead of "Intro" since
that material moved chapters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
defmulti-as-service is a recipe, not a tutorial step. Moved the
file to test/darkleaf/di/how_to/ with the matching namespace, and
trimmed the intro and optional-dep prose.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename "Add a side dependency" to "Side dependencies" and move
the file to test/darkleaf/di/how_to/. Reframe the recipe: tighten
the hook to migrations-as-the-canonical-case and add a "Why not
just list it as another root?" section that contrasts
add-side-dependency with the vector-form di/start, pointing at the
subsystem-registry pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename "Log" to "Logging system lifecycle" and move the file to
test/darkleaf/di/how_to/. Drop the "middleware" word in favour of
plainer phrasing about argument order, and add a short note about
why the test compares pr-str values.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename the chapter to "All public vars as a component" and move
the file to test/darkleaf/di/how_to/. Cascade the namespace
change through x_inspect_test.clj (which imports it) and the
ns-publics docstring in core.clj. Drop the "middleware" word in
the prose.

Also add the chapter to cljdoc.edn — it was missing from the TOC
since long before this restructure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename "Multi system" to "Multiple systems" and move the file to
test/darkleaf/di/how_to/. Replace the abstract intro with a
concrete scenario — several web apps sharing the same database
pool — and call out the identical-instance assertion inline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A Reference page is descriptive prose with example snippets, not
a literate test file. Move the stub to a tracked plain markdown
under doc/reference/middleware_types.md, drop the .clj wrapper,
drop /doc/reference/ from .gitignore so the page is committed
directly, and update the forward-links in the Registries,
Environment variables, and Composition tutorial chapters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bring the project notes in line with how the docs are organised
now:

- Mention doc/how_to/ (generated like tutorial/) and
  doc/reference/ (plain tracked markdown), plus the _journey.md /
  _structure.md planning artifacts.
- Update the article cross-link example from the old a_intro_test
  path to the renamed a_your_first_system_test, and document the
  full cljdoc URL format for article-to-API-var links.
- Add a new "Documentation conventions" section: audience, voice,
  terminology (no "middleware" in tutorial/how-to, math-style
  names, keyword-vs-symbol intent), directory layout, test idioms
  in chapter files (vs. strict regular tests), and when a
  Reference page earns its keep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename middleware_types.md to middleware_argument.md and rewrite it
as a reference for the values di/start/inspect/->memoize accept:
function, map, sequence, nil, and java.util.function.Function. Add
the order/precedence rules, the ->memoize positioning constraint,
and a note on why dispatch is a cond over predicates rather than a
protocol. Update the cljdoc.edn TOC label to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Capture the lessons from the design-doc work as a "Recurring mistakes
to avoid" section, keyed on confident-but-wrong prose that is not
grounded in the code or the author's model. Add the terminology rule
that a key names a component, never a node, and point the reference
link at the renamed middleware_argument.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A conceptual overview of how DI is built. A factory is what a key
resolves to; a registry is a function from a key to a factory; a
middleware is registry -> registry composition. The article walks the
Factory protocol (dependencies/build/description), add-stop teardown,
the two meanings of nil and the ::di/nil sentinel, decorator-style
wrapping, di/inspect, and the running-system container, then closes on
why the model has stayed stable since the first release.

Link it into the cljdoc nav between Changelog and Tutorial.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Why DI? (doc/why_di.md) was written but never added to the navigation
tree. It sits at a different altitude than Design — user-facing
motivation vs how-it's-built — and the two cross-link, so Design did not
supersede it. Place it after Changelog, before Design: motivation, then
model, then the tutorial.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Design article (doc/design.md, added after the v6 plan) already
covers the protocol contract, 'most things are already factories', the
demolish -> add-stop history, the nil pitfall, and the decorator wrap —
exactly the material that would have justified a standalone Factory
reference page. Writing one on top of Design would duplicate both Design
and the docstring, which the conventions forbid. Reference drops from 3
pages to 2 (Inspect, Middleware types).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the return-value envelope: the vector of per-factory maps,
the :key/:dependencies/:description entries, and the ::di/root and
:undefined markers the walk itself contributes. Link the Factory
protocol for the :description shapes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename x_inspect_test.clj to reference/inspect_test.clj so the page
lives under Reference and is generated by tutorial-to-md.sh like the
tutorial/how-to chapters. Update the cljdoc nav, the .gitignore for
generated reference pages, and the cross-links in integrant.md and
log_test.clj. Document the two reference-page flavours in CLAUDE.md.

Drop the variable-factory-regression test from the page: it was born
in #33 to guard a custom Factory that did not implement the then
separate FactoryDescription protocol. #58 merged description into
Factory, so the case can no longer occur, and rendering a bare
regression block in the reference article added no value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The how-to's point is reusing one factory across several keys, not
databases as a topic. Rename the file and namespace to match, reframe
the intro around the pattern, and link the Factory protocol var.

Also fold in the pending cljdoc nav restructure: the tutorial's
Base/Advanced grouping becomes a flat Tutorial list plus a separate
How-to section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Uncomment the rename-deps example so the intent is readable, and add
the .disabled suffix. di/rename-deps is still commented out in core.clj,
so the file cannot run as a test yet — keep it out of the runner like
x_instrument_test.clj.disabled.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New How-to recipe that turns di/inspect output into Graphviz DOT
and renders it. The graphviz function takes inspect data (not a
root) so it composes with di/inspect. Includes a rendered SVG,
a cljdoc nav entry, and marks the plan item done in _structure.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mark the planned Tutorial/How-to/Reference changes as implemented in
_structure.md and _journey.md, and document the parked-draft and
doc/images conventions in CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Terminology: drop the outright ban on the word "middleware" in
tutorial/how-to chapters. It forced vague paraphrases ("shapes
di/start accepts") and contradicted the reference page's own title.
Instead introduce the term once, in the Registries chapter, then use
it plainly. Update CLAUDE.md convention accordingly.

Review fixes across the docs:
- Fix broken links to a non-existent middleware_types.md (now
  middleware_argument.md) in three tutorial chapters, and a dead
  anchor in middleware_argument.md (#middleware).
- Remove semicolons from prose (non-native-reader convention) in
  several chapters and articles.
- Drop a TODO comment that leaked into the published Tips article,
  and reframe its "group registries" tip around avoiding apply.

Remove the v6 planning artifacts (doc/_journey.md, doc/_structure.md)
and their CLAUDE.md pointers now that the restructure is done.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record the Docker-based local preview steps and the gotchas found
while previewing: articles come from a git revision (so the gitignored
generated *_test.md need a throwaway force-add commit), the jar must
be installed to ~/.m2, and images do not render under a local-path
ingest because the raw-URL rewrite points at the local git path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Grounded in the gmonit test-suite pattern: one memoized registry
for the whole suite, per-test overrides after it, a test-runner
wrapper that releases the cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Also make the co-author trailer name the actual model instead of a
hard-coded one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Also: a Tips section on conditional registry entries, the gmonit
patterns research notes, and new lessons in CLAUDE.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the documentation conventions and recurring-mistakes guides and
the detailed cljdoc command listings. Keep workflow rules, a condensed
cljdoc section (release flow, docs-update-without-release gotcha,
cross-link rules), release/build gotchas, and Clojars notes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
darkleaf and others added 11 commits July 3, 2026 19:06
Extend the Composition with update-key tutorial with a prose
paragraph: f and args accept any factory, e.g. di/ref for a
decorator with its own dependencies and di/template for an
assembled options map. Mark plan items 3 and 4 as done.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hand-written recipe: put descriptions on deps-map bindings (keys are
strings/keywords and can't hold metadata), then read them back via
di/inspect → ::di/variable → the var's :arglists → clojure.core/destructure.
Track the .md (gitignore) and add it to the cljdoc nav.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A hand-written registry middleware over p/Factory that wraps every
:service at build time — tracing as the example (NewRelic SDK with its
@Trace/reify-IFn tax), presented as the workable special case of the
removed di/instrument.

Co-Authored-By: Fable 5 <noreply@anthropic.com>
Keys are data — depend on 'other.ns/component without requiring the
namespace; DI loads it at start via requiring-resolve. The example
requires di itself with :as-alias, for the metadata keyword only.

Co-Authored-By: Fable 5 <noreply@anthropic.com>
Read an EDN map of env vars as the last registry element — it
overrides both earlier registries and the real environment, no dotenv
tooling needed. Same contract as System/getenv: string values,
env-parsing and :or defaults keep working.

Co-Authored-By: Fable 5 <noreply@anthropic.com>
- di/start docstring: replace the removed di/instrument in the example,
  balance parens
- di/stop docstring: document suppressed exceptions
- di/derive docstring: the source key is optional, f receives nil;
  drop the useless -> in the example
- di/add-side-dependency docstring: the example must be a component
- di/env-parsing docstring: nil when the variable is not set
- di/ns-publics docstring: keys are keywords, nil/unbound vars skipped
- tutorial c: ::di/stop implies a component, no explicit kind needed
- tutorial e: a registry group is sequential, not seqable
- tutorial g: fix the next-chapter pointer
- tutorial j: di/derive source key is optional, make f nil-safe
- multimethods how-to: explain di/derive and the di/ref indirection
- inspect: explain the #_#_:opts placeholder
- why_di: link the tutorial and how-to articles from each section
- instrumenting services: fix the Changelog link

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A side dependency that is built before the root and its
dependencies. The implicit root now has two internal keys,
::prepended-side-dependency and ::added-side-dependency; both
middlewares share one implementation and mark the pulled-in key
with ::di/side-dependency true, so di/inspect output for
add-side-dependency stays unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Migrations become the prepend example, the build order is stated
as a fact, and the example app runs Flyway before the server via
prepend-side-dependency.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Not listed in the cljdoc tree yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- why_di: a redefined service keeps the dependencies resolved at
  start; adding a dependency requires a restart
- di/log docstring: after-demolish! fires at stop; explain why the
  middleware should go last instead of demanding it
- tutorial l: list where each error lives — thrown build failure,
  its cause, suppressed stop errors
- tutorial e: the opening no longer denies that chapter b named
  the registry

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread doc/cljdoc.edn Outdated
darkleaf and others added 3 commits July 5, 2026 12:14
GITHUB_SHA is the commit the pushed tag points to, so the git
dependency snippet on cljdoc now works. Readme.md on master keeps
the placeholders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Frame it as two production examples — a JVM shutdown hook and
spootnik/signal — without recommending either.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@darkleaf darkleaf merged commit 442a26b into master Jul 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant