Scratch (3.0)
This assessment applies the coupling account — coupling as access to a shared resource, and the coupling floor [1], [2] — and the knowledge-embodiment theorem [3]; the language is assessed against its official reference [4].
1 Assessment
This page assesses Scratch in five parts: core coupling — what the language’s own constructs force; ecosystem coupling — what the surrounding platform, tooling, and community cost; engineering readiness — whether the artifact can be reproduced, verified, observed, worked in quickly, connected to other languages, and governed openly; the profile — the unscored facts a score cannot express; and the scoring detail — the mechanism marks and the arithmetic behind every score. A ✅ bullet marks a construct that helps. A ⚠️ or ❌ bullet marks a cost; the scoring model does not price every cost named here.
Core coupling 55/100 · Ecosystem coupling 65/100 · Engineering readiness 56/100
1.1 Core coupling
1.1.1 Type
- ❌ There is no static type check: A block accepts a value of any kind, and a mismatch appears only when the script runs (T1)
- ❌ No sum types: An alternative is not a declared type; the script tests a value with an
ifor a sensing condition (T4) - ❌ No generics: A list block is not parameterised by an element type (T5)
- ❌ One flat namespace for message names: Every message name is project-wide, so a name collision is a naming decision rather than a scope decision (T6)
- ❌ No null safety: A variable that was never set reads as an empty value, and a block that needs a value can run with none (T10)
- ❌ No module boundary: The project is one program, and a sprite exposes its blocks without a declared interface (T11)
1.1.2 Construction
- ❌ Global mutable state is the default: A variable created “for all sprites” is writable by every script in the project (C1)
- ❌ No immutability: A value in a variable can be changed by any script that names it (C2)
- ✅ A sprite is a self-contained unit: Costume, sound, and scripts live together, so one actor’s behaviour is defined in one place
- ✅ The event model separates the trigger from the action: The green flag, a key press, a sprite click, or a received message starts a script, and the script does not know who started it
- ✅ Cloning separates an instance from its definition:
create clone of myselfcopies a sprite’s scripts at run time, so a repeated actor is written once - ⚠️ A custom block is the only abstraction:
definegives a named sequence with inputs, and “run without screen refresh” is the one control over its granularity
1.1.3 Memory
- ✅ The runtime owns every object: No allocation and no deallocation block exists, and a sprite, a costume, or a clone is reclaimed automatically, so a script never names memory
- ✅ A clone can be deleted explicitly:
delete this clonebounds the number of live actors - ⚠️ The clone count is the practical limit: Scratch caps the number of clones, so a
foreverloop that clones without adeletereaches the cap rather than exhausting memory - ⚠️ The media assets are the project’s footprint: Costumes, backdrops, and sounds dominate the size and the load time of a project
1.1.4 Error
- ❌ There is no structured error path: No exception and no error value exists, and a failed block simply does not produce the expected effect (Er1)
- ❌ Nothing marks a failed operation: A block that cannot do what it says leaves the value unchanged or produces a placeholder, and the script continues (Er3)
- ❌ No composable result type: A block returns one value, and no value can carry the fact that an operation failed (Er4)
- ✅ The stage gives immediate feedback: An out-of-stage sprite is visibly off-stage, and a sensing block can test for a touch
- ⚠️ Debugging is by observation: There is no breakpoint, so the ordinary method is a variable monitor or a
sayblock
1.1.5 Concurrency
- ✅ Scripts are concurrent by default: Every hat block in the project runs in parallel, and no script starts or joins another by hand
- ⚠️ A broadcast is global: Any sprite can listen for any message, so a broadcast couples the sender to every listener in the project
- ✅ The scheduler is cooperative and single-threaded: The scripts advance one after another within a frame, so an interleaved update does not arise in the middle of a block
- ✅ A clone runs its own copy of the script:
when I start as a clonegives each instance an independent thread of control - ⚠️ A shared variable is updated by many scripts without a lock: Correctness depends on where each script yields, which the programmer must reason about
- ⚠️ One frame is the unit of timing: The green-flag scripts share the frame budget, so the loop rate is the scheduling contract
1.1.6 Platform
- ✅ The runtime is the same on every target: A project runs in the browser player and in the offline editor with the same blocks
- ✅ The sandbox bounds what a project can do: A project reaches no file system and no network, so its effect is confined to the runtime
- ✅ MIT Media Lab maintains the runtime and the community site: The editor, the player, and the sharing site come from one organisation
- ✅ The project file is an open document: A
.sb3project is a zip archive of JSON and assets, so a project can be read and converted - ⚠️ Cloud variables are a hosted service: They work only on the Scratch site, so a project that uses them depends on that host
- ⚠️ An extension changes the runtime’s surface: The Music, Pen, and video-sensing extensions, and the hardware extensions, add blocks the player must supply
1.1.7 Trade-offs (not coupling)
- Visual blocks trade expressiveness for legibility: The block shape carries the nesting rule, so a syntax error is not expressible — which is the design goal
- The block vocabulary is deliberately small: A small instruction set is the pedagogy, not an oversight
- The actor-based organisation mirrors the stage: A project is organised by sprite because the program is a scene
- The educational scope is a scope decision: The absence of files, network, and performance is the boundary of the design
- Sharing and remixing are community choices: The remix model is a policy of the site, not a property of the language
- Turbo Mode is an optional accelerator: It removes the frame wait, and the choice is the user’s
1.2 Ecosystem coupling
1.2.1 Performance
- ✅ The runtime executes the blocks directly: The player holds the block scripts and runs them, so there is no build step between the editor and the running project
- ✅ “Run without screen refresh” removes the frame yield: A custom block with that option runs to completion inside one frame, so a heavy computation can finish without waiting
- ✅ Turbo Mode removes the frame wait entirely: The option runs the project as fast as the runtime allows
- ⚠️ Animation is capped near the redraw rate: A loop yields each frame, so smooth motion is limited to the display rate
- ⚠️ A large script count degrades the frame: Every script shares one frame budget, so the project slows as the script count and the clone count grow
1.2.2 Ecosystem
- ❌ The ecosystem is the runtime and one community site: The blocks, the media library, and the sharing site are the whole environment, and there is no general package manager (Ec3)
- ✅ The adoption in education is very large: The project is used in K-12 classrooms worldwide
- ✅ A large public project corpus exists: Shared and remixed projects are a huge body of worked examples
- ✅ The media and sprite libraries are built in: Backdrops, costumes, and sounds ship with the editor
- ⚠️ Third-party players and add-ons are the extension point: TurboWarp, Scratch Addons, and the extension gallery live outside the official editor
1.2.3 Evolution
- ✅ The project format carries a version and a converter: An older project is converted when it is opened in the current editor
- ✅ MIT maintains the editor as a product: The runtime, the editor, and the site receive continuing updates
- ✅ The offline editor mirrors the online one: A project runs without a connection to the site
- ⚠️ A block set can change between editor releases: A removed or renamed block can leave an older project needing an edit
1.2.4 Domain
- ❌ The domain is one thing: teaching programming to beginners: The design goal is computational thinking, and everything outside it is out of scope (D1)
- ❌ It is not usable for a production application: There is no file access, no network, no performance target, and no general library (D2)
- ✅ The classroom fit is exemplary: Drag-and-drop, immediate feedback, and shareable projects match the teaching case
- ✅ It is the first language in many curricula: The adoption in schools is the evidence for the fit
- ⚠️ The move to a text language is the known gap: A learner must leave Scratch to continue, and the transfer is not automatic
1.2.5 Learning
- ✅ The curve is effectively zero: The interface is drag-and-drop, and there is no syntax to learn
- ✅ The block shape prevents the syntax error: A block that does not fit cannot be placed
- ✅ The stage returns immediate feedback: One click runs the project and shows the result
- ⚠️ The ceiling is low for a capable learner: After the core blocks there is little further depth
- ⚠️ “Run without screen refresh” is the one advanced idea: A heavy custom block must use it to finish inside a frame
1.2.6 Syntax
- ✅ The syntax is the block shape: An invalid nesting is impossible, because the editor accepts only a shape that fits
- ✅ The expression blocks nest visually: An operator block occupies an input slot, so the precedence is explicit without parentheses
- ✅ The blocks are named in the reader’s language: The editor localises the labels and the variable names
- ⚠️ A small computation becomes a tall column of blocks: The notation is compact per block and long per expression
- ⚠️ There is no text form in the editor: A script cannot be typed, searched, or diffed as text
1.2.7 Testing
- ❌ There is no test framework: No assertion and no runner exists, so a test is a manual run (G1)
- ❌ An error appears only when a script runs: A wrong block is found by executing the project (G3)
- ✅ The stage is a built-in observation harness: Motion, sound, and
sayshow the program state directly - ✅ A variable monitor exposes a value on the stage: Any variable can be shown and watched as it changes
- ⚠️ Verification is by inspection: The programmer checks the result by watching the project, not by a repeatable check
1.2.8 Security
- ✅ A project runs in a sandbox: No block opens a file or a socket, so a project reaches no file system and no network and its effect is confined to the runtime
- ✅ The runtime is the same for every project: A shared project cannot ship a native binary
- ⚠️ A cloud variable is shared global state: Every player of the project can write it, so a project that trusts it can be misled
- ⚠️ The community features are moderated, not secured: The safety of the sharing site is a policy of the site, not a property of the language
- ⚠️ A third-party player can add an unsafe surface: An alternative player or an add-on can extend the runtime beyond the sandbox
1.3 Engineering readiness
1.3.1 Reproducibility
- ✅ No charged mechanism in this dimension.
1.3.2 Supply chain
- ⚠️ Published packages carry no signed provenance by default.
1.3.3 Observability
- ⚠️ No stable tracing and metrics standard.
- ⚠️ The standard library has no structured logging.
1.3.4 Feedback
- ⚠️ No fast in-editor analysis.
1.3.5 Interop
- ❌ No general foreign-function interface.
- ⚠️ No maintained portable target.
1.3.6 Governance
- ⚠️ The specification is not public.
1.4 Profile
Unscored, and kept separate from every score on purpose. The profile records what a mechanism price cannot express: what a running program costs, how well a coding model and an agent work in the language, and whether a safety-critical path exists.
1.4.1 Energy and cost
What this axis asks: what does a running program cost in energy and time?
1.4.2 AI and agent readiness
What this axis asks: how well does a coding model and an agent work in this language?
- ❌ Sparse training data: models write it unreliably [7].
1.4.3 Safety certification
What this axis asks: is there a certified or standards-qualified path to a safety-critical system?
- ⚠️ No certified or standards-qualified path for safety-critical systems.
1.5 Scoring detail
1.5.1 Core coupling Dimensions
| Dimension | Mechanism | Description | Present | Cost |
|---|---|---|---|---|
| Type | T1 |
dynamic no static check | ✅ | −15 |
T2 |
weak static | — | 0 | |
T3 |
dynamic/duck dispatch | — | 0 | |
T4 |
no sum types | ✅ | −4 | |
T5 |
no generics | ✅ | −4 | |
T6 |
no namespaces | ✅ | −8 | |
T7 |
type erasure/reflection | — | 0 | |
T8 |
operator overloading | — | 0 | |
T9 |
inheritance required for polymorphism | — | 0 | |
T10 |
no null-safety | ✅ | −8 | |
T11 |
no module boundary | ✅ | −8 | |
T12 |
no effect tracking | ✅ | −8 | |
T13 |
async/sync colouring | — | 0 | |
T14 |
unchecked foreign boundary | — | 0 | |
| Type subtotal | −15 (−55) | |||
| Construction | C1 |
global mutable state by default | ✅ | −15 |
C2 |
no immutability by default | ✅ | −4 | |
C3 |
constructors coupled to allocation | — | 0 | |
C4 |
no constructor/validation | — | 0 | |
| Construction subtotal | −15 (−19) | |||
| Memory | M1 |
manual deallocation | — | 0 |
M2 |
GC non-deterministic pauses | — | 0 | |
M3 |
no RAII | — | 0 | |
M4 |
no ownership model | — | 0 | |
| Memory subtotal | 0 | |||
| Error | Er1 |
no structured path | ✅ | −15 |
Er2 |
unchecked exceptions only | — | 0 | |
Er3 |
errors ignored/non-exhaustive | ✅ | −4 | |
Er4 |
no composable result type | ✅ | −4 | |
| Error subtotal | −15 (−23) | |||
| Concurrency | K1 |
GIL/no parallel | — | 0 |
K2 |
shared mutable state default | — | 0 | |
K3 |
manual sync no race detection | — | 0 | |
K4 |
no structured concurrency | — | 0 | |
K5 |
no primitives | — | 0 | |
| Concurrency subtotal | 0 | |||
| Platform | P1 |
cannot function outside one vendor/domain | — | 0 |
P2 |
single-vendor but other uses | — | 0 | |
P3 |
legacy/discontinued platform | — | 0 | |
| Platform subtotal | 0 |
Core Dimensions score: 55/100 — total cost = −45 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).
1.5.2 Ecosystem coupling Dimensions
| Dimension | Mechanism | Description | Present | Cost |
|---|---|---|---|---|
| Performance | R1 |
interpreted no AOT/JIT | — | 0 |
R2 |
GC pauses | — | 0 | |
R3 |
JIT warmup | — | 0 | |
| Performance subtotal | 0 | |||
| Ecosystem | Ec1 |
no package manager | — | 0 |
Ec2 |
fragmented tooling | — | 0 | |
Ec3 |
small/niche/discontinued | ✅ | −8 | |
Ec4 |
proprietary | — | 0 | |
Ec5 |
platform-locked tooling | — | 0 | |
Ec6 |
monoculture | — | 0 | |
Ec7 |
legacy burden | — | 0 | |
| Ecosystem subtotal | −8 | |||
| Evolution | V1 |
breaking changes | — | 0 |
V2 |
frozen | — | 0 | |
V3 |
discontinued | — | 0 | |
V4 |
glacial standards | — | 0 | |
| Evolution subtotal | 0 | |||
| Domain | D1 |
domain/vendor lock-in | ✅ | −15 |
D2 |
poor domain fit | ✅ | −8 | |
D3 |
framework forces architecture | — | 0 | |
| Domain subtotal | −15 (−23) | |||
| Learning | L1 |
steep | — | 0 |
L2 |
large surface/multi-paradigm | — | 0 | |
L3 |
sparse docs | — | 0 | |
| Learning subtotal | 0 | |||
| Syntax | S1 |
verbose | — | 0 |
S2 |
inconsistent | — | 0 | |
S3 |
punctuation-heavy | — | 0 | |
| Syntax subtotal | 0 | |||
| Testing | G1 |
weak tooling | ✅ | −8 |
G2 |
poor debugging | — | 0 | |
G3 |
runtime-only errors | ✅ | −4 | |
| Testing subtotal | −12 | |||
| Security | Q1 |
memory-unsafe | — | 0 |
Q2 |
dynamic/weak typing risk | — | 0 | |
Q3 |
known vulnerability/injection | — | 0 | |
| Security subtotal | 0 |
Meta Dimensions score: 65/100 — total cost = −35 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).
1.5.3 Engineering readiness Dimensions
| Dimension | Mechanism | Description | Present | Cost |
|---|---|---|---|---|
| Reproducibility | Y1 |
build not reproducible | — | 0 |
Y2 |
dependencies not pinned | — | 0 | |
| Reproducibility subtotal | 0 | |||
| Supply chain | Y3 |
no signed provenance | ✅ | −8 |
Y4 |
registry without namespacing | — | 0 | |
| Supply chain subtotal | −8 | |||
| Observability | Y5 |
no stable tracing standard | ✅ | −8 |
Y6 |
no structured logging | ✅ | −4 | |
| Observability subtotal | −12 | |||
| Feedback | Y7 |
slow build | — | 0 |
Y8 |
no fast in-editor analysis | ✅ | −4 | |
| Feedback subtotal | −4 | |||
| Interop | Y9 |
no foreign-function interface | ✅ | −8 |
Y10 |
no portable target | ✅ | −4 | |
| Interop subtotal | −12 | |||
| Governance | Y11 |
single-vendor governance | — | 0 |
Y12 |
closed specification | ✅ | −8 | |
| Governance subtotal | −8 |
Readiness Dimensions score: 56/100 — total cost = −44 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).
Verdict: Scratch’s design yields moderate core coupling, and the marks fall where the pedagogy put them. Global variables are the project namespace, a broadcast reaches every sprite, and there is no type check, no structured error path, and no module boundary; the constrained environment keeps the consequence small. The visual block model removes the syntax error entirely, the event model separates a trigger from the action it starts, and a sprite is a self-contained unit. Main strengths: a zero learning curve, an exemplary classroom fit, very large K-12 adoption, and a sandbox that bounds what a project can do. Main weaknesses: it is not usable for a production application, the domain is a single one, the block vocabulary is shallow, and testing is by inspection.
The formal development. The definitions, theorems, and proofs behind this page are published in:
- On the Nature of Coupling: All Coupling as Shared Resource Access — Zenodo, 2026 — doi:10.5281/zenodo.21925122
- Coupling as a Consequence of Cohesion: Decomposition, the Coupling Floor, and Domain-Imposed Coupling — Zenodo, 2026 — doi:10.5281/zenodo.21925201
- On the Nature of Cohesion: Cohesion as Correctness Relative to a Partitioning Rule — Zenodo, 2026 — doi:10.5281/zenodo.21703193