5 ms·
"The technique C# traditionally uses to deal with illegal states is called design by contract" That's not really true. Code contracts are just a library , it's
by mariusmg 11y ago
"The technique C# traditionally uses to deal with illegal states is called design by contract"
That's not really true. Code contracts are just a library , it's certainly not "traditional" in C# to use that to check for invalid state. Traditionally you just check the value before assignment. And if you do this your entire problem "goes away".
Gotta say this is one of the most contrived "F# is better than C#" example i ever saw.
- inglor 11y agoThis. The nullable field and an enum is hardly the standard way to do things in C#. That's like having NULLable fields everywhere in SQL. Assignment checking is pretty simple but would not work if you want to verify the correctness of the program in compile time. Which you can still do just fine in C#. You would use a class hirarchy with a `User` abstract class and `ActiveUser` and `DeletedUser` subclasses and use the type system to enforce the constraints. The syntax wouldn't even look worse.
- koyote 11y agoHow would you go about implementing activeUser.Delete()? I guess you would have to replace the object and return a new DeletedUser and then make sure that your activeUser object is not referenced anywhere else?
- inglor 11y ago> How would you go about implementing activeUser.Delete()? I guess you would have to replace the object. If we're talking about a functional style then yes, `User`s would be immutable object, changing them would return a new user. Doing `activeUser.Delete()` returns a new deleted user, doing `deletedUser.Undelete()` returns a new active user. I might go as far as creating the user as a value type (struct) but that's a bit unorthodox.
- mannykannot 11y ago> Doing `activeUser.Delete()` returns a new deleted user... But don't you now risk having two mutually contradictory objects representing one user?
- eropple 11y agoIt's a rare application where the gap between creating a new immutable object (aside: this is really annoyingly hard to write this quickly and cleanly in C#, it is my one serious beef with the language--looking forward to record classes!) and the GC of the old one matters materially. If they're not being shared across multiple requests, for example, it's pretty rare that the momentary superposition of deleted and not-deleted would be risky.
- Retra 11y agoOnly if you don't do it atomically. And while you can't guarantee atomic deletes, you can enforce them using the type system. Think of the following code: if (n != null) { n.do_something() } What happens if n gets deleted after the null check, but before the method invocation? So you are already assuming that you can do certain things atomically, even if, in theory, some external agent can write on your data. You manage that by protecting your data (with asynchronous tools or immutability), or by statically verifying your code.
- moron4hire 11y agoFor starters, I wouldn't, as I don't delete data.
- douche 11y agoYup, that would usually be the case. I seem to always end up doing "soft deletes", where there is some kind of IsDeleted flag in the database. Otherwise, you've got to trace out any foreign keys to delete dependent data, which is usually not something you want to do anyway, since it would throw off any metrics or destroy your compliance data.
- moron4hire 11y agoThe FK issue is just a matter of diligence. It's the metrics and compliance data that you mentioned that are important. You can't get data back.
- achr2 11y agoThis is why in most C# paradigms developers would never implement this type of state-based class model. You'd have a user class, with all the required methods that guard (at runtime) against invalid states and transition mutably as required. Most C# environments (UI, web frameworks) are not designed around functional concepts, especially immutable objects/collections.
- thomasahle 11y ago> Traditionally you just check the value before assignment. And if you do this your entire problem "goes away". I wouldn't say spreading null checks and forgetting them all over your code makes any problems "go away".
- mariusmg 11y agoYes, you're right. It's better to blindly do assignments and use code contracts to check the state after. Much cleaner. </sarcasm>