The Library and the Entry Point
Every project in this book separates two kinds of code into different files. A library does the actual work, with no file I/O, no console output, and no network call anywhere inside it. A thin entry point connects that library to the outside world. Chapter 1's word_stats.nex and nexwc.nex are the clearest example. Word_Stats never reads a file or prints anything. nexwc.nex does nothing but read arguments, call into Word_Stats, and print what comes back. Every later project repeats the split: Lru_Cache and its demo script, Dup_Finder and its scan/cancellation demos, Chat_Hub/Chat_Server and the two programs that run them.
The reason is almost entirely about what becomes easy to test. A pure library can be constructed, called, and asserted against directly, with nothing to set up and nothing to tear down. That's exactly what every project's check suite does. An entry point that touches a filesystem, a socket, or a console has real setup cost and real nondeterminism (a listening port, a file that has to exist first, a background thread). So this book keeps that code as small as possible, and tests it by hand where automating it would cost more than it would catch. Chapter 1 states that reasoning explicitly, and every later chapter's entry point gets the same treatment implicitly.
checks.nex
Every project's automated tests live in a file named checks.nex, run with nex checks.nex. Every one of them uses the identical, deliberately low-tech pattern: a small Checker class with one method, check(label, expected, actual), and a summary() that prints a pass/fail count at the end:
class Checker
create
make() do
passed := 0
failed := 0
end
feature
passed: Integer
failed: Integer
check(label: String, expected: String, actual: String) do
if expected = actual then
passed := passed + 1
print("PASS " + label)
else
failed := failed + 1
print("FAIL " + label + " expected=" + expected + " actual=" + actual)
end
end
summary() do
print("---")
print("" + passed + " passed, " + failed + " failed")
end
end
Nothing about this needs a testing framework, a build tool, or a dependency beyond the language itself. That matters for a book whose whole point is showing what Nex can build on its own. Every comparison happens as strings, which keeps every check's failure message self-explanatory (expected=X actual=Y, no framework-specific diff format to learn). That comes at a small, deliberate cost: every value under test gets an explicit "" + value or .to_string() at the call site. For a book about contracts, there's a fitting parallel here worth noticing. This pattern is itself a tiny, self-imposed contract: every check call promises a label, an expected value, and an actual value, and the summary at the end is the whole suite's own postcondition.
intern and Why Some Files Are Classes Anyway
Worth stating plainly here, not just where it first comes up in Chapter 5: intern <Name> uses <Name> to find a file (matched against the file's own snake_case name). It doesn't require a declaration literally named <Name> inside it. On the JVM backend every project in this book compiles to, an interned file hands over everything it declares at top level — every class, every free function — regardless of what any of them are named. A file of loose functions interns and runs exactly as well as a file built around a class of the expected name.
So Dup_Finder in Chapter 5 is a class for a different reason. Three functions merged straight into a caller's namespace would be three bare global names, free to collide with anything else the interning program (or some other interned module) happens to define. A class keeps them reachable only through an instance — finder.collect_files(...) can't be shadowed the way a loose collect_files could. Dashboard_Listeners in Chapter 8, on the other hand, never needed an anchor class at all. That file's real content is already four classes (Increment_Listener and the rest), and intern Dashboard_Listeners loads them regardless of whether anything in the file is literally named Dashboard_Listeners. The small anchor class this file used to carry served no mechanical purpose, and has been removed.