Live data from Hacker News

Stop writing CLI validation. Parse it right the first time

hackers.pub

51–60 of 169 posts

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

#51
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…

Yes, both are writing code. But nearly all the time, the constraints you want to express can be expressed with zod, and in that case using zod means you write less code, and the code you do write is more correct. > Of course, you hope zod is robust, tested, supported, extensible, and has docs so you can understand how to express your domain in terms it can help you with. And you hope you don’t have to spend too much…

Sure... the laws of physics last broke backwards compatibility at the Big Bang, Zod last broke backwards compatibility a few months ago.

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

#52
post #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 th…

Actually, I think argparse falls into the same trap that the author is talking about. You can define lots of invariants in the parser, and say that these two arguments can't be passed together, or that this argument, if specified, requires these arguments to also be specified, etc. But the end result is a namespace with a bunch of key-value pairs on it, and argparse doesn't play well with typing systems like mypy or pyright. So the rest of the tool has to assume that the invariants were correctly specified up-front.

The result is that you often still this kind of defensive programming, where argparse ensures that an invariant holds, but other functions still check the same invariant later on because they might have been called a different way or just because the developer isn't sure whether everything was checked where they are in the program.

What I think the author is looking for is a combination of argparse and Pydantic, such that when you define a parser using argparse, it automatically creates the relevant Pydantic classes that define the type of the parsed arguments.

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

#54

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.

I think I've seen it done like that

  --option flag1,flag2
(Maybe with another separator, as long as it doesn't need to be escaped.)

Another possibility is to make the main option an argument, like the subcommands in git, systemctl, and others:

  command option --flag1 --flag2
This depends on the specifics, though.

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

#55
post #52
post #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 th…

Actually, I think argparse falls into the same trap that the author is talking about. You can define lots of invariants in the parser, and say that these two arguments can't be passed together, or that this argument, if specified, requires these arguments to also be specified, etc. But the end result is a namespace with a bunch of key-value pairs on it, and argparse doesn't play well with typing systems like mypy or…

Precisely my thought. I love argparse, but you can really back yourself into a corner if you aren’t careful.

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

#56

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.

Right, but that's validation, and this article is talking about parsing (not validating) into an already-correct structure by making invalid inputs unrepresentable.

So maybe the reason why they were able to reduce the code is because they lost the ability to do good error reporting.

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

#57

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?

I think you're looking at it too literally - what people usually mean with"making invalid state unrepresentable" is in the main application which has your domain code - which should be separate from your inputs

He even gives the example of zod, which is a validation library he defines to be a parser.

What he wants to say : "I don't want to write my own validation in a CLI, give me a good API already that first validates and then converts the inputs into my declared schema"

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

#59
post #6

Stopped reading after realising this is written by ChatGPT

Looked human-ish to me, what signs did you see?

I thought the style was like ChatGPT in a "clever, casual, snarky" prompt flavor as well. I see it a lot on LinkedIn especially in sentence structures like these:

"Invalid data? The parser rejects it. Done."

"That validation logic that used to be 30% of my CLI code? Gone."

"Mutually exclusive groups? Sure. Context-dependent options? Why not."

For me this really piled on at the end of the blog post. But maybe it's just personal style too.

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

#60

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?

If talking about UI, the flip side is not to harm the user's data. So despite containing errors it needs to representable, even if it can't be passed further along to back-end systems.

For parsing specifically, there's literature on error recovery to try to make progress past the error.

Post reply on HN