That can be a case of that yeah. Using your example, a lot of devs might use that email parsing logic in various independent components of the same system. Eg if you have a reporting component that sends you business reports, that component really shouldn’t be validating the structure of email addresses…if you need to refine the parsing logic now you’ve got to do coordinated deployments, possibly backfills, etc., whereas if you just treated it as an opaque string in that system you’d be better off.
This isn’t really a criticism of the approach, it’s super useful, just that it needs to be applied judiciously. “Parse all the things” isn’t always the best advice.
>that component really shouldn’t be validating the structure of email addresses
That's right, as the article says you no longer validate data, instead you parse data. Components don't take strings and validate them, they take an EMail address.
>If you need to refine the parsing logic now you’ve got to do coordinated deployments
If you need to refine the parsing logic, you modify the constructor of the EMail class to do whatever refinements you need.
I have no doubt you may have seen codebases that did something wrong, and that wrong thing may have been related to parsing or validation, but nothing you've said indicates that there is something wrong with replacing validation with parsing, so that code always operates on semantically meaningful data types that are valid by construction, instead of opaque binary blobs that need to constantly be properly interpreted in ad-hoc ways.
I guess what I'm saying is to be judicious about what invariants a particular piece of code should care about, within the context of the larger system.
> That's right, as the article says you no longer validate data, instead you parse data. Components don't take strings and validate them, they take an EMail address.
That doesn't solve the problem, by parsing it my code is caring about its syntax and structure, even if my use case doesn't require that. That creates coupling, and in a distributed system that kind of unnecessary coupling can create major headaches when trying to change things.
An even simpler example that many people can empathize with is using strict, closed enums in a distributed system (very easy to do with e.g. Java). Safely adding a new enum value is basically impossible at that point, until you make them "open" enums that can safely parse unknown values.
Again I am not disagreeing in principle, I am only saying that this has ergonomic problems in practice and is easy to misuse.
I see, that would be problematic indeed. I strongly believe in Bounded Contexts, a concept from Domain Driven Design. As for the Ubiquitous Language (ie: product & engineers naming things the same way, code included), parsing logic should also be segregated and specific to your domain. I would argue that you should have different parsers for different purposes even inside the same system, for example one could be applied to inputs coming from an User, while another could be applied to an API and one more when coming from a DB.
I think I would stress this point more in the README, thanks for sharing :thumbsup:
This isn’t really a criticism of the approach, it’s super useful, just that it needs to be applied judiciously. “Parse all the things” isn’t always the best advice.