3 ms·
"Making illegal states unrepresentable" is one of the worst possible pieces of advice I ever encountered. It sounds very reasonable, but as soon as you face th
by _pmf_ 5y ago
"Making illegal states unrepresentable" is one of the worst possible pieces of advice I ever encountered.
It sounds very reasonable, but as soon as you face the issue of communicating to the user or other components the fact that something is wrong and what is wrong, you'll discover that it is very hard to inform about illegal states if you cannot represent them.
- nivertech 5y agoThe reason to make them unrepresentable so you will be able to catch the case when the input was illegal. Otherwise you may never notice that illegal state was there in the first place. I encountered many systems that would take invalid inputs and produce invalid (but sometimes even valid) results [1]. Illegal internal states are even harder to catch. When using FSM / StateCharts I usually automatically print error to log (and crash) for all illegal state/event combinations in the State Transition Table, instead of silently ignoring them. [1] GIGO - Garbage In Garbage Out https://en.wikipedia.org/wiki/Garbage_in,_garbage_out https://en.wikipedia.org/wiki/Garbage_in,_garbage_out
- cloogshicer 5y agoThat's not what "Making illegal states unrepresentable" means. Let's say you're trying to parse a user object. Let's further say users always have to have a last name - a user without last name would be illegal state. Now if you're parsing some data for a user that really doesn't have a last name for some reason, there's two approaches to this problem - either you return a User with a null last name (which is essentially giving incorrect information to the caller). Or you make it impossible to set User.lastName to null (for example by making it an Optional) and fail with an error about what went wrong. Of course you wouldn't NEED to restrict User.lastName to never be null - but if you always fail with an error in that case anyways, why not? That way any consumer of the User object knows that the lastName will always be there and valid.
- HelloNurse 5y agoBut clearly, requiring a last name is wrong. If legitimate users can lack a last name, the system needs to work without last names: probably there should be a flexible "person's name" class that encapsulates first names, last names, titles etc. instead of attaching a raw last name to users.
- jdthedisciple 5y ago... more like a "getPersonName()" method instead of a whole 'nother class, init?
- HelloNurse 5y agoThe various parts of a person's name should be encapsulated in a specific class, and one of these objects, rather than a loose last name and other concrete fields, should be a mandatory attribute of a user object. There should be only one place for name-handling logic, and since other people types besides users could appear in the domain model (commercial customer, social network "friend", relative, etc.) the user class isn't that place.
- piaste 5y agoThe idea is that you have a clear, strongly-typed separation between unvalidated data and validated data. Unvalidated data (the DTO) is just the raw representation of whatever was inputed, read from storage, received from external services, etc. Any possible input should be acceptable and faithfully representable as a DTO. Then, by passing the DTO to a validation function, you return either a validated object (a model) which is in fact constrained to only contain a legal data state; or a set of validation errors which can be acted upon. Your business logic should operate only on validated objects, so that you can actually rely on your basic assumptions, and actual workflow rules (eg. "you can't checkout an empty cart") can be expressed and separated from trivial validation (eg. "quantity must be greater than 0").
- bigbizisverywyz 5y agoIs this not just as simple as recommending to use an input mask, or date picker or lookup list so it's impossible to end up with an invalid value in your system? I always took it as such.