Live data from Hacker News

Stop writing CLI validation. Parse it right the first time

hackers.pub

41–50 of 169 posts

Re: Stop writing CLI validation. Parse it right the first time

#41
post #9

> Think about it. When you get JSON from an API, you don't just parse it as any and then write a bunch of if-statements. You use something like Zod to parse it directly into the shape you want. Invalid data? The parser rejects it. Done. Isn’t writing code and using zod the same thing? The difference being who wrote the code. Of course, you hope zod is robust, tested, supported, extensible, and has docs so you can und…

Yeah, the "parse, don't validate" advice seems vacuous to me because of this. Someone is doing that validation. I think the advice would perhaps be phrased better as "try to not reimplement popular libraries when you could just use them".

The difference between parse and validate is

    function parse(x: Foo): Bar { ... }

    const y = parse(x);
and

    function validate(x: Foo): void { ... }

    validate(x);
    const y = x as Bar;
Zod has a parser API, not a validator API.

Re: Stop writing CLI validation. Parse it right the first time

#42

I like this advice, and yeah, I always try to make illegal states unrepresentable, possibly even to a fault. The problem I run into here is - how do you create good error messages when you do this? If the user has passed you input with multiple problems, how do you build a list of everything that's wrong with it if the parser crashes out halfway through?

Most validation libraries worth their salt give you options to deal with this sort of thing? They'll hand you an aggregate error with an 'errors' array, or they'll let you write an error message "prettify-er" to make a particular validation error easier to read.

This work if all errors are self contained, stoping at the first one is fine too.

Re: Stop writing CLI validation. Parse it right the first time

#45
This kind of stuff is what makes me appreciate python's argparse.

It's a genuine pleasure to use, and I use it often.

If you dig a little deeper into it, it does all the type and value validation, file validation, it does required and mutually exclusive args, it does subargs. And it lets you do special cases of just about anything.

And of course it does the "normal" stuff like short + long args, boolean args, args that are lists, default values, and help strings.

Re: Stop writing CLI validation. Parse it right the first time

#47
post #9

> Think about it. When you get JSON from an API, you don't just parse it as any and then write a bunch of if-statements. You use something like Zod to parse it directly into the shape you want. Invalid data? The parser rejects it. Done. Isn’t writing code and using zod the same thing? The difference being who wrote the code. Of course, you hope zod is robust, tested, supported, extensible, and has docs so you can und…

Yeah, the "parse, don't validate" advice seems vacuous to me because of this. Someone is doing that validation. I think the advice would perhaps be phrased better as "try to not reimplement popular libraries when you could just use them".

Sibling says this with code, but to distil the advice: reflect the result of your validation in the type system.

Then instead of validating a loose type & still using the loose type, you're parsing it from a loose type into a strict type.

The key point is you never need to look at a loose type and think "I don't need to check this is valid, because it was checked before"; the type system tracks that for you.

Re: Stop writing CLI validation. Parse it right the first time

#48

Is there no getopt implementation for Typescript? The input this library tries to handle better looks to me like bad design. "options that depend on options" should not be a thing. Every option should be optional. Even if you have working code that can handle some complex situation, this doesn't make the situation any less unintuitive for the users. If you need more complex relationships, consider using arguments as…

> options that depend on options

What would you do for "top level option, which can be modified in two other ways"?

  (--option | --option-with-flag1 | --option-with-flag2 | --option-with-flag1-and-flag2)
would solve invalid representation, but is unwieldy.

Something that results in the usage string

  [--option [--flag1 --flag2]]

doesn't seem so bad at that point.

Re: Stop writing CLI validation. Parse it right the first time

#49

Is there no getopt implementation for Typescript? The input this library tries to handle better looks to me like bad design. "options that depend on options" should not be a thing. Every option should be optional. Even if you have working code that can handle some complex situation, this doesn't make the situation any less unintuitive for the users. If you need more complex relationships, consider using arguments as…

I think ultimately you're trying to tell a river that it's going the wrong way. Programs have had required options for decades at this point. I think they can make sense as alternatives to heterogeneously typed positional arguments. By making the user name them explicitly you remove ambiguity and let the user specify them in whatever order they please.

In Python this was a motivating factor for letting functions demand their arguments be passed as named keywords. Something like send("foo", "bar") is easier to understand and call correctly when you have to say send(channel="foo", message="bar")

Re: Stop writing CLI validation. Parse it right the first time

#50
post #9

> Think about it. When you get JSON from an API, you don't just parse it as any and then write a bunch of if-statements. You use something like Zod to parse it directly into the shape you want. Invalid data? The parser rejects it. Done. Isn’t writing code and using zod the same thing? The difference being who wrote the code. Of course, you hope zod is robust, tested, supported, extensible, and has docs so you can und…

I think the key part, although the author doesn't quite make it explicit, is that (a) the parsing happens all up front, rather than weaving validation and logic together, and (b) the parsing creates a new structure that encodes the invariants of the application, so that the rest of the application no longer needs to check anything.

Whether you do that with Zod or manually or whatever isn't important, the important thing is having a preprocessing step that transforms the data and doesn't just validate it.

Post reply on HN