⚡ Stop writing validation code. Let the bytecode do it. 🚀 Vaadoo 0.0.1 is out! I just released Vaadoo, a Java bytecode enhancement tool that makes domain objects self-validating — without reflection, without runtime validation frameworks, and without boilerplate. 💡 Instead of writing validation logic everywhere, you declare intent: record User(@NotBlank String name, @PositiveOrZero int age) {} Vaadoo turns it into real, executable validation at build time. 🔥 Why this matters: - Clean domain models that enforce invariants directly - No reflection-based validation at runtime - No JSR 380 runtime dependency ⚙️ Works with: - Plain Java classes and records - With and without Lombok - Maven & Gradle (Byte Buddy-based build integration) 📦 Maven Central: <dependency> <groupId>io.github.pfichtner</groupId> <artifactId>vaadoo-bytebuddy</artifactId> <version>0.0.1</version> </dependency> 📦 GitHub: https://lnkd.in/dp8swsc2 💬 Curious what you think — especially from folks building domain-heavy systems.
Interesting approach Peter, but I’ll admit I’m a bit skeptical. This feels similar (to me) to things like Lombok, trading explicit, readable code for magic that happens somewhere else. The concern isn’t the goal (reducing boilerplate is great), it’s the cost: 👉 you lose visibility into what’s actually happening 👉 debugging gets harder when behavior lives in generated bytecode 👉 stack traces and validation paths can become less obvious For example, with explicit validation you control: the exact exception type the message (which can be very domain-specific) the precise line where things fail That’s incredibly valuable when something breaks in production. With bytecode enhancement, you’re trusting that all of that is handled the way you expect, and when it isn’t, you’re now debugging something you didn’t write and can’t easily see. Personally, I’d rather keep validation explicit and, if boilerplate is the issue, lean on code generation (even AI these days) to produce it, at least then the logic is still visible and traceable. Curious how you’re handling things like custom error messages and debuggability here?
Throw exceptions in constructor is bad idea. Validating of parameters should not be in constructor. Only job of constructor should be construct class instance. Data need be validated at data entry point. input_data = get_input_data(); validation_result = validate_input_data(); react_invalid_data(validation_result, input_data); // further all data is valid and no need for checking. User user = new User(input_data.user_name, input_data.user_age);
I see two major challenges. Especially with domain objects, for example, when they are populated by humans, it is necessary to check all invariants before throwing an exception. This prevents users from getting stuck in an endless loop of error messages and abandoning the process. Another issue lies in the use of ByteBuddy. This ties me to the ByteBuddy release cycles. Why not use the java.lang.classfile API instead?
Clean arch/ports and adapters fans r going to have a heart attack reading that hahaha
Or even better. Parse, don't validate. https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
Did it allow validate everytihng at once? Did it alow set an order of validatino or custom error message? .... stop saying people what to do...
How does your solution supplement JSR-380 ?
https://github.com/pfichtner/vaadoo/