Best Practices for Production Wolfram Code
Prerequisites: Testing and debugging
Notebooks are ideal for exploring. Code that others rely on needs the same discipline as in any language.
Structure
- Packages, not notebooks, for reusable code:
.wlfiles in a paclet, with public symbols documented by::usagemessages and helpers in a private context. - Pure functions of their inputs — avoid global variables; use
Modulefor locals and pass settings as options. - One job per function, small enough to test.
- Options for configurable behavior, the way built-ins work:
Options[describe] = {"Digits" -> 3};
describe[data_List, OptionsPattern[]] := With[{d = OptionValue["Digits"]},
<|"n" -> Length[data], "mean" -> N[Mean[data], d]|>]
describe[{1, 2, 3, 4}]
describe[{1, 2, 3, 4}, "Digits" -> 5]
<|n -> 4, mean -> 2.50|>
<|n -> 4, mean -> 2.5000|>
N[x, 3] gives an arbitrary-precision number with 3 digits, and the
notebook shows exactly those digits.
Validate inputs
- Use patterns and tests (
_Integer?Positive,_String,{__?NumericQ}) so bad input doesn't match — then add a catch-all definition that issues a clear message and returns aFailure. - At boundaries (APIs, forms, scripts), convert text with
Interpreter, neverToExpression.
Reliability
- Tests for every public function, run automatically with
TestReportin a script. - Exact where it matters, approximate where speed matters — and be
explicit with
N. - Reproducibility: seed random numbers with
SeedRandom, save external data you fetched, and record$Versionwith results. - Static checks: the
CodeInspectorpaclet (CodeInspect["file.wl"]) finds suspicious code, andCodeFormatterformats it.
Collaboration
- Keep
.wland.wltfiles in version control. Notebooks (.nb) are large expression files that diff poorly; if you keep them, clear outputs first. - Write documentation pages with the Documentation Tools paclet, or at least a README and usage messages.
Deployment and licensing
- Choose where code runs: the Wolfram Cloud (APIs, forms, scheduled tasks), the Wolfram Application Server, or the Wolfram Engine inside your own service.
- Check licensing early — the free Wolfram Engine is for development, and production use needs a license.
A final example
A small, production-style function: documented, validated, optional settings, and a failure path.
compoundValue::usage = "compoundValue[p, r, n] gives the value of principal p after n years at annual rate r.";
compoundValue::badrate = "Rate `1` should be between 0 and 1.";
compoundValue[p_?Positive, r_?NumericQ, n_Integer?NonNegative] :=
If[0 <= r <= 1,
Round[p (1 + r)^n, 0.01],
Message[compoundValue::badrate, r]; Failure["BadRate", <|"Rate" -> r|>]]
compoundValue[1000, 0.05, 10]
FailureQ[Quiet[compoundValue[1000, 5, 10]]]
1628.89
True
What's next
Try the Advanced Projects, then read What You Should Know Now — and What's Next for where to go from here.