Dart / Integration: targets, resources, validation, and evidence / Lesson 15
Declare package assumptions and report checks honestly
Connect pubspec constraints, library boundaries, analysis, formatting, and deterministic behavior checks without inventing tool execution.
On this page
Lesson goals
- Explain why a package SDK range and language version must support the syntax being taught.
- Distinguish dependency resolution, static analysis, formatting, unit behavior, and platform execution evidence.
A package and a library are different boundaries
A package groups source, metadata, and dependencies under a pubspec. A library is Dart’s unit of privacy and can include a primary file and its parts. Underscore names are private to that library, not to the whole package and not just one class. Importing a package library makes its public API available; it does not grant access to private state. Organize lib, executable entry points, and tests according to the project’s conventions and actual responsibilities. Avoid exposing an unstable helper merely because another file needs it; decide whether it belongs in the same library or a deliberate public contract.
Declare a lower bound that can understand the source
The illustrative pubspec below uses a Dart 3 lower bound so records, patterns, and relevant class modifiers can be part of its language. The range is a teaching assumption, not a claim that every SDK in the range has executed every example or that a dependency graph has resolved. A real package must choose its minimum supported SDK and test that promise alongside its current toolchain. Platform APIs add another dimension: a valid Dart 3 package can still import a library unavailable on its browser target. State both language and platform assumptions explicitly.
name: batch_lab
publish_to: none
environment:
sdk: '>=3.0.0 <4.0.0'
This YAML declares a local teaching package and SDK range. It has no external dependencies, was not resolved by pub, and is not a verified compatibility matrix.
Static checks and formatting answer different questions
The analyzer checks types and configured diagnostics without proving every business behavior. Formatting normalizes source presentation; it does not establish authorization, correct counts, or safe resource ownership. Lint rules can improve consistency but should reflect the project’s supported tooling and policy. Do not silence a warning through dynamic or a cast without understanding the lost guarantee. A clean analysis result is useful only when the command actually ran against the relevant source and configuration. This course ran no Dart analysis, formatter, dependency solver, or test runner because Dart tooling was unavailable.
Use fixed boundaries for a behavior check
The standalone harness tests a simple cutoff rule before, at, and after its boundary. It throws StateError on mismatch instead of relying on assert being enabled. That makes the intended check explicit, but it remains unexecuted source here. A configured test framework can supply richer assertions, fixtures, and reporting; its dependency and platform support must be declared rather than assumed. Keep clocks, randomness, network calls, and mutable global state outside a pure policy check unless the test deliberately controls them. A test that repeats the implementation’s exact expression can miss the mistaken business rule both share.
bool beforeCutoff(int now, int cutoff) => now < cutoff;
void main() {
final cases = <int, bool>{9: true, 10: false, 11: false};
for (final entry in cases.entries) {
if (beforeCutoff(entry.key, 10) != entry.value) {
throw StateError('cutoff mismatch');
}
}
print('3 declared cases passed');
}
3 declared cases passed
Expected output is 3 declared cases passed if compiled and executed successfully. Equality is deliberately rejected. This is a predicted output, not a recorded passing test.
Preserve the scope of each evidence claim
A useful validation report records the SDK, target, dependency state, source revision, command, and observed result. Distinguish source review, syntax analysis, compilation, test execution, and platform integration. Testing one native VM program does not validate a browser import or every supported minimum SDK. A lockfile and a clean dependency resolution are also not a proof that the application behaves correctly. Run only appropriate isolated checks in the learner’s own project. The public course provides original teaching material and reasoning, not a fabricated certification, package publication, CI result, or production readiness assessment.
Common errors and fixes
The source uses Dart 3 patterns under an unsupported language lower bound.
- Why it happens
- The SDK language contract was not reviewed with the syntax change.
- How to fix it
- Choose and test a compatible minimum SDK and document the requirement.
- Prevent it next time
- Review pubspec constraints whenever adopting new language features.
Formatted source is reported as behaviorally correct.
- Why it happens
- Presentation normalization was confused with validation.
- How to fix it
- Run and report checks that target the actual behavior claim.
- Prevent it next time
- Label formatting, analysis, and test results separately.
A declared test output is described as an observed pass.
- Why it happens
- Reasoned expectation was mistaken for execution evidence.
- How to fix it
- State the missing tooling and retain the example as unexecuted.
- Prevent it next time
- Attach commands and captured results to every execution claim.
Check your understanding
1. Why should the cutoff harness test equality explicitly?
Show worked solution
The boundary distinguishes < from <= and often carries the real business decision. Ordinary earlier or later values can pass under both implementations. Record whether equality is allowed before writing the test, then use a fixed case to detect an accidental policy change. A passing harness is useful only after actual execution in the declared environment.
2. Does successful dependency resolution establish that dart:io code works in a browser?
Show worked solution
No. Resolution concerns declared dependencies and constraints, while platform library availability and compilation are separate checks. Declare the intended target, use appropriate platform abstractions, and compile or test the relevant implementation where tooling exists. Do not infer cross-platform compatibility from one successful package-management step.
Key takeaways
- Language constraints, platform support, and executed behavior need separate evidence.
- A precise report distinguishes proposed checks from recorded observations.