Live data from Hacker News

"Parse, don't validate" through the years with C++

derekrodriguez.dev

11–20 of 52 posts

Re: "Parse, don't validate" through the years with C++

#11
post #4

Author has used LLMs to generate Java code in C++. It detracts from his point.

What Java code?

Regardless of how they might have used LLMs, I tend to have an issue with this kind of complaint, given the C++ example code on the Design Patterns: Elements of Reusable Object-Oriented Software book, released in 1994, 2 years before Java was made public.

Or the examples from "Using the Booch Method: A Rational Approach", "Designing Object Oriented C++ Applications Using The Booch Method", or "Using the Booch Method: A Rational Approach".

Additional there are enough framework examples starting with Turbo Vision in 1990, MacAPP in 1989, OWL in 1991, MFC in 1992,....

Somehow a C++ style that was prevalent in the industry between 1990 and 1996, that I bet plenty of devs still have to maintain in 2026, has become "Java in C++".

Re: "Parse, don't validate" through the years with C++

#13

Disregarding the article for a second, has anyone else had the pattern that "parse don't validate" makes sense in object oriented style, but less sense in functional style programming? Like parsing and validating blurs into each other.

The tl;dr is that instead of representing emails as type String and manually sprinkling is_email(str) throughout your code, you represent as type Email, which has a function parse(String) -> Option. The type system then ensures the checks are present whenever they have to be, and nowhere else.

This is extremely natural to do in a language like Haskell or Rust. And incredibly unnatural to do in C++ for instance.

Re: "Parse, don't validate" through the years with C++

#15
post #13

Disregarding the article for a second, has anyone else had the pattern that "parse don't validate" makes sense in object oriented style, but less sense in functional style programming? Like parsing and validating blurs into each other.

The tl;dr is that instead of representing emails as type String and manually sprinkling is_email(str) throughout your code, you represent as type Email, which has a function parse(String) -> Option . The type system then ensures the checks are present whenever they have to be, and nowhere else. This is extremely natural to do in a language like Haskell or Rust. And incredibly unnatural to do in C++ for instance.

I hope this is not trolling so I'll bite. It is incredibly natural to represent an object, such as an email, as an Email class in object oriented languages like C++. It'd then have a constructor that accepts a string and constructs the email object from said string, or maybe a parse(string) -> Option thingy. The type system then ensures the checks are present whenever they have to be, and nowhere else.

Tl;dr: there's nothing extra that functional or OO programming give you here. Both allow you to represent the problem in a properly typed fashion. Why would you represent an email as a string unless you are a) deeply inexperienced or b) have some really good reason to drop all the benefits of a strongly typed language?

Re: "Parse, don't validate" through the years with C++

#16
The C++11 example is the weakest in the article by its own thesis. Public throwing constructor, no year check, no leap-year check, so Birthdate(0, 2, 30) constructs cleanly. The C++17/23 shape (private ctor + static factory) is the actual mechanical insight from King's essay. Make the constructor a function that can fail, so the type itself carries the proof.

Re: "Parse, don't validate" through the years with C++

#17

The C++11 example is the weakest in the article by its own thesis. Public throwing constructor, no year check, no leap-year check, so Birthdate(0, 2, 30) constructs cleanly. The C++17/23 shape (private ctor + static factory) is the actual mechanical insight from King's essay. Make the constructor a function that can fail, so the type itself carries the proof.

exactly, use std::expected as the return type, avoid exceptions, and make a failable factory constructor to build your type. Make invalid states unrepresentable!!!

Re: "Parse, don't validate" through the years with C++

#18
post #13

Earlier quoted context omitted.

The tl;dr is that instead of representing emails as type String and manually sprinkling is_email(str) throughout your code, you represent as type Email, which has a function parse(String) -> Option . The type system then ensures the checks are present whenever they have to be, and nowhere else. This is extremely natural to do in a language like Haskell or Rust. And incredibly unnatural to do in C++ for instance.

I hope this is not trolling so I'll bite. It is incredibly natural to represent an object, such as an email, as an Email class in object oriented languages like C++. It'd then have a constructor that accepts a string and constructs the email object from said string, or maybe a parse(string) -> Option thingy. The type system then ensures the checks are present whenever they have to be, and nowhere else. Tl;dr: there's…

I completely agree with you but I think sometimes folks carry some piece of data around as a string or int instead of something more concrete like a class or a strongly typed enum etc purely out of laziness!

Re: "Parse, don't validate" through the years with C++

#19

The C++11 example is the weakest in the article by its own thesis. Public throwing constructor, no year check, no leap-year check, so Birthdate(0, 2, 30) constructs cleanly. The C++17/23 shape (private ctor + static factory) is the actual mechanical insight from King's essay. Make the constructor a function that can fail, so the type itself carries the proof.

exactly, use std::expected as the return type, avoid exceptions, and make a failable factory constructor to build your type. Make invalid states unrepresentable!!!

Aren't you time-travelling? std::expected is C++23 (so available starting from 2025-2027 xd)

https://en.cppreference.com/cpp/utility/expected

Re: "Parse, don't validate" through the years with C++

#20
C is perfectly capable of type-driven design. He's already got the type (struct), and although C is a bit limited, he can:

* return pointer-or-null

* choose "invalid" sentinel values and then use birthdate_is_valid(...) to check validity.

* Add an is_valid bool field (or even an error enum like in the C++23 example)

* Add an out field in the constructor function for the error code (similar to how ObjC does things).

Post reply on HN