On the templates tutorial the quality template and the readiness
justification that instantiates it shared a single file. That is fine for a demo, but a template only
earns its keep when it is shared: many arguments across a project should reuse the same quality
shape, and none of them wants a private copy of it.
The fix is separation of concerns: keep the reusable template in one file, keep each argument in
its own file, and let jPipe stitch them together. The load directive pulls a model out of another
file and into scope.
The load directive
Give the template a file of its own:
// quality.jd
template quality {
conclusion ready is "Version 2.0 is ready to ship"
strategy gates is "All release gates pass"
gates supports ready
@support tested is "Testing is demonstrated"
tested supports gates
@support documented is "Documentation is demonstrated"
documented supports gates
}
The readiness argument then lives in its own file. It loads quality.jd and instantiates the
template exactly as before; the only change is that quality now comes from another file:
// readiness.jd
load "quality.jd"
justification readiness implements quality {
sub-conclusion quality:tested is "The code is tested"
strategy testing is "The test suite passes with high coverage"
testing supports quality:tested
evidence suite is "The test suite passes"
suite supports testing
evidence coverage is "Coverage is above 80%"
coverage supports testing
sub-conclusion quality:documented is "The documentation is updated"
strategy docs is "The changelog and API docs are current"
docs supports quality:documented
evidence changelog is "The changelog is up to date"
changelog supports docs
}
load "quality.jd" imports every model declared in that file, resolved relative to the current
file. Compile readiness.jd and you get back the very
same argument you built on the
templates tutorial, only now the template is shared: a second file, say docs.jd, could load
"quality.jd" and instantiate quality with its own evidence, no copy-paste.
Binding a load with as
As a project grows you may load several files at once, and their model names can collide (two files
might each define a quality). Bind a file under a name with as, and everything it declares is
reachable through that prefix:
// readiness.jd
load "quality.jd" as templates
justification readiness implements templates:quality {
sub-conclusion templates:quality:tested is "The code is tested"
strategy testing is "The test suite passes with high coverage"
testing supports templates:quality:tested
evidence suite is "The test suite passes"
suite supports testing
evidence coverage is "Coverage is above 80%"
coverage supports testing
sub-conclusion templates:quality:documented is "The documentation is updated"
strategy docs is "The changelog and API docs are current"
docs supports templates:quality:documented
evidence changelog is "The changelog is up to date"
changelog supports docs
}
The template is now reached as templates:quality and its holes as templates:quality:tested: the
same qualified ids you already met, with the file’s
alias in front. Reach for as whenever a plain load would leave a name ambiguous.
The IDE’s Outline panel makes the split visible: everything imported from quality.jd sits under
the templates namespace, while the current file’s own models stay in the default namespace.
There, as on the templates page, the
readiness justification lists its inherited holes ((inherited) quality:tested, …) alongside the
elements it declares to fill them.
From many files to one argument
Splitting is what makes an argument modular: each file can be written, reviewed, and reused on its
own, while a shared template like quality keeps them all arguing to the same standard. load is
only the glue that lets one file see another; turning those loaded pieces into a single tree is the
job of jPipe’s composition operators, assemble and refine. Together they let a large assurance
case grow as a handful of small, focused files instead of one sprawling model.
Where to next?
- assemble independent arguments side by side under one shared conclusion.
- refine a single node by grafting a loaded model onto it.
- Make it executable binds each piece of evidence to a real check.
For larger, real-world models split across files, see the jpipe-examples repository.