I’ve seen the general idea here called “part blindness” before: https://www.hxa.name/notes/note-hxa7241-20131124T0927Z.html
It's just the second law of Thermodynamics at work, no ?
Also: forgot the evolution into its final form, which is a list of rule objects.
A practical example:
Your program starts out accepting a config file that looks like this:
enableLogging: true
Then it changes into: logLevel: WARN
Then that becomes: logging: {
level: WARN
file: system.log
}
Then: logging:
fileLogger: {
level: WARN
file: system.log
}
And finally: logging:
- fileLogger: {
level: WARN
file: system.log
}
- consoleLogger: {
level: DEBUG
}
Re:Anti-Pattern of the Day: Type Keys
by i_am_toaster on Monday January 02, 2023 @04:49PM
(#34224147)
The truth of this comment leaves me feeling somewhat emotionally violated.
Question is whether and to what extent you can shortcut that lifecycle, and whether it's worth trying.
Right. I tend to think you should just be aware of it, be deliberate in choosing where to situate your code on it, and be adept at refactoring code up the scale.
I think this evolution paradigm is useful to keep in mind when designing the API, but obviously each successive step is more computationally expensive and more complex (see: error-prone)
You should probably generally use the least advanced of these while maintaining a pathway for future refactors into more complex versions of this
• All booleans really want to be enums
• All enums really want to be rich data objects
• All rich data objects really want to be discriminated unions
That is, whenever you write some code which accepts a Boolean parameter that drives its behavior, at some point you will regret making it a bool and inevitably need to refactor it to be an enumeration type with more than two values. But then eventually you will realize that you have one behavior in your code that applies to more than one of those enum values (all the ‘type a’ cases but not the ‘type b’ cases), and you will want those enum values to themselves have a Boolean property telling you whether they are of type a or type b (and note that that Boolean will also be subject to this same golden rule in time)
Eventually you’ll find that those different enum values (the type a and type b ones) need different sets of dependent data (type a values all have a ‘target’ as well, but type b ones don’t, say) - so you end up needing a discriminated union to capture the various data objects involved.
All of which leads us to: every if statement and switch statement (over a parameter or input value) is a disguised match on a discriminated union type. Over time, this fate is inevitable.
And if your language doesn’t have discriminated unions, learn a pattern to fake them (usually it’s the abstract factory pattern).