3 ms·
This pattern is really only used with @Entity’s. Things that actually are mutable and rightfully need to be. With @Entity’s setters are exactly what you want be
by vips7L 2y ago
This pattern is really only used with @Entity’s. Things that actually are mutable and rightfully need to be. With @Entity’s setters are exactly what you want because it allows you to add validation, and check error states before persisting.
Arguing immutability for the sake of immutability is considered harmful imo. Only make things immutable when they actually are immutable or when concurrency is at play (which it probably isn’t, 99% of all code is single threaded).
- mrkeen 2y agoWhy not just prevent the construction of bad states instead of constructing bad states and later checking them?
- Benjammer 2y agoOften, imo, this depends on where you want to put the validation complexity. You can move validation to the front end and "prevent constructing bad states" through a combination of good UI and front end data validation, i.e. validate all the pieces of an entity to make sure the eventual Entity will be valid. But the opposite trade off would be to keep your front end simple, and have the data represent anything that is possible in the UI, and then you can validate anywhere in your stack that you want or where it makes sense for any engineering reason. You can still validate the UI models on the front end before sending them over the wire. You can validate at the endpoint and return HTTP codes. You can run logic in your database to massage/correct/fix the data any way you want. You could even throw things into a queue for post-processing later on, or send to another server for processing, whatever you want. In theory it sounds great to say "just prevent construction of bad states," but this is a complex problem in professional software that involves coordination between programmers, designers, and product managers to get the UI features into the right place where preventing the construction of bad states doesn't lead to a frustrating UI experience for users. It's often far simpler, more pragmatic, and less complex in terms of coupling in both software and humans to just accept whatever state the UI gives you and figure things out somewhere else where you aren't bothering your users so much.
- mrkeen 2y ago> Often, imo, this depends on where you want to put the validation complexity. You can move validation to the front end This has nothing to do with the frontend/backend split since a server will receive arbitrary requests, not just the ones you hope you programmed the frontend to send. > In theory it sounds great to say "just prevent construction of bad states," but this is a complex problem in professional software Defeatism. If you have a User in your domain, and your domain dictates that Users have a UserId, simply do not allow construction of a User without a UserId. What's a UserId? Is it a String, or is it a UUID? If you think the King James Bible translated into Chinese makes for a good UserId, then a String is a perfectly good representation for that. Otherwise pick something more suitable.
- Benjammer 2y agoI mean I was just trying to have a conversation you don't have to try and roast me with quote-quips and absurdist comparisons... What is happening to this platform these days?
- mrkeen 2y agoI grounded it. Any problem can be swept away with "you don't know what you're talking about", "you'll come around to my way of thinking when you're older", "X has nothing to do with Y", etc. So, make things real with an example.
- vips7L 2y agoI think that makes a bad assumption that _you are constructing bad states_ when that isn’t true. You most likely don’t have all the data you need at construction time and the state of the object is still valid. Some data can be null, but later when it is set you want to validate that the data is correct. For instance when making a person or user you most likely only have their email when you initially create them and then it’s the users job to complete the rest of the data at a later time. Some might want to fill in their age or some might want to fill in their sex. You may never get this data because it’s optional, but when you set it you’ll want to validate it. And as always in programming _it depends_. It depends on your workflow, requirements, and domain. Being dogmatic about anything is just going to result in worse code.
- cess11 2y agoUse a builder flow, only construct when you have everything you need, don't have any setters, only getters. That's what I do, anyway.
- vips7L 2y agoI personally don’t really like builders. They work in some situations. But if I’m pulling the record from the DB and I only need to set some data on it that is overkill and more complex than need be. The object is already constructed in a valid state.
- mrkeen 2y ago> The object is already constructed in a valid state. But that's the entire value proposition of do-not-allow-construction-of-invalid-state! If a User is actually a User, then you can say "the object is already constructed in a valid state". If you decide to be 'less dogmatic' and instead construct Users-which-may-or-may-not-be-users-just-throw-an-ex-if-theyre-no-good, then you cannot say that the object is already constructed in a valid state.
- vips7L 2y ago
- alserio 2y agoEntities are also the one place where you would need a way to express instance private state and not class private state.