Problem statement
Design the object model and public APIs for a validation framework that checks whether an object satisfies a set of declared constraints and returns a structured report of every violation.
Operating context. One in-process library. A developer defines validation rules for a type: per-field constraints (not-null, length, range, pattern), cross-field rules (end-date after start-date), conditional rules (a field required only when another is set), and nested-object validation. A validation returns every violation, not just the first, and each violation carries a field path and a message. Validators are built once from composed rules and applied concurrently to many instances.
Out of scope. The annotation/attribute discovery mechanics of any runtime, internationalization/message-templating internals, input sanitization or coercion, asynchronous or remote validation (such as a uniqueness check against a database), and UI form binding.
What to produce. The class hierarchy (validator, constraint/rule, validation context, violation, the result report), the public APIs, and how rules compose and accumulate violations. Be explicit about: how new constraint kinds plug in, how nested and cross-field rules access sibling values, and how violations are accumulated with correct field paths.
Functional requirements
- Define per-field constraints (not-null, length, range, pattern) for a target type.
- Compose multiple constraints on one field and across multiple fields into a single validator.
- Evaluate an instance and return every violation — each with a field path and message — not just the first.
- Support cross-field and conditional rules that read sibling field values.
- Validate nested objects and collections by delegating to their own validators and prefixing the field path.
Non-functional requirements
- Validating an instance is linear in the number of applicable constraints and free of I/O.
- A built validator is immutable and safe to apply to many instances concurrently.
- New constraint kinds plug in behind one Constraint interface without editing the engine.
- Validators compose — a type's validator can embed another type's validator without duplication.
- The framework is unit-testable with plain objects and no framework or reflection context.
- Violations are accumulated deterministically with stable, dotted field paths for nested targets.
Topics
- System Design LLD
- Oop Solid
- Patterns Strategy
- Patterns Composite
- Patterns Builder