In software, if something is really easy to do, that seems great. You don’t have to spend a lot of time, effort, or thought on it.
But it is easy simply because the people who put it together made a lot of assumptions. These assumptions bound what it does. They place limits on it. Often very hard ones.
If those limits correspond to what you are doing, then awesome, it is easy. They’ve outlined the box; now all you have to do is drop in some obvious stuff, and you are done.
Well…
If you need to do something out of this box full of assumptions, then you are screwed. It won’t be easy anymore. You have to ‘go against the grain,’ and that is always painful and messy. You really should have stayed in the box.
But the box is usually too small. Way too small. It’s the size of time shrinking down the imaginations of the builders. Either they did not get that someone would go beyond their imaginations, or they just didn’t have time to accommodate it. If you go outside, it usually ends in tears.
So easy is only easy right up until it isn’t; then, it is extremely hard, maybe even impossible.
Which is why you have to be terrified of it. You get sucked in by it looking easy for trivial things, but when it gets real you are screwed. Easy is usually bad. Not if you have to whip out a quick demo and are willing to scribble within the lines, but the day after, when they tell you to make it real. It ain’t going to ever be real, and it certainly ain’t going to happen as quickly.
Real is hard work. Sloughing through the pain and details, fixing every little bit possible until the whole thing holds together and is serious. Real ain't easy.
Beware easy: it is a trap. Tempting enough to lure you in, but lethal enough to make you quickly regret it.
Software, the real stuff, is hard work. It’s always been hard work, and it will always be hard, even if we get nifty tools that help. They’ll only help a little bit, and to get them to do the real stuff, you really have to really understand them, their limits, and when to rely on them.
Software doesn’t take away your problems; it only ever shifts them. They are still there, just in a different form. You still have to understand how the solution works, how it solves other people’s problems, and what its limits are. There is no avoiding this; you can try to ignore it, but it will come back and haunt you.
Ignore the easy, trendy stuff. It will be gone in a few years and you don’t want to go with it. Take the hard road. Truly master it, down to the metal. Seek out that knowledge, collect it, and build on it. That is what will keep you going for as long as you want to keep going. There is no easy way around this.
Software is a static list of instructions, which we are constantly changing.
▼
Friday, April 11, 2025
Friday, April 4, 2025
Interface Consistency
A specific block of code running within a given context (state) is one piece of functionality.
That functionality can be triggered from all sorts of actions in the program.
It can be from a menu, a right click, a widget, hot-key, side-effect, etc.
The functionality is ‘complete’ and ‘consistent’ if and only if for all mediums where it might be triggered, it is triggerable and deterministic.
For example, there are 50 functions available in the menus, all of them can be triggered through a default hot key sequence, and all of the sequences can be rearranged. The set of available actions matches the two different entry points.
The tricky part is the implicit context.
If, say, as a result of a user action, one or more of the state variables is assigned as input to the functionality, then in higher global contexts, those assignments may no longer be applied.
For example, something is highlighted in an edit window, so it is passed into the functionality, but it is ignored by the global menu. Thus, the behavior of the hot key and the menu differ. Opps.
That is an inconsistency if the user does not expect it to be the case. From their perspective, they triggered the same function, and they expect the same results either way. The key is a shortcut to the menu, not its own interface paradigm.
In this way, the overall state of the application, the global state, is the one that users connect with. Any sort of localized state that behaves differently from that generally comes as a surprise. Surprises are not good. But it is easier for a programmer to write more localized code than it is for them to attach their work into that global context, so we see these types of violations frequently.
That functionality can be triggered from all sorts of actions in the program.
It can be from a menu, a right click, a widget, hot-key, side-effect, etc.
The functionality is ‘complete’ and ‘consistent’ if and only if for all mediums where it might be triggered, it is triggerable and deterministic.
For example, there are 50 functions available in the menus, all of them can be triggered through a default hot key sequence, and all of the sequences can be rearranged. The set of available actions matches the two different entry points.
The tricky part is the implicit context.
If, say, as a result of a user action, one or more of the state variables is assigned as input to the functionality, then in higher global contexts, those assignments may no longer be applied.
For example, something is highlighted in an edit window, so it is passed into the functionality, but it is ignored by the global menu. Thus, the behavior of the hot key and the menu differ. Opps.
That is an inconsistency if the user does not expect it to be the case. From their perspective, they triggered the same function, and they expect the same results either way. The key is a shortcut to the menu, not its own interface paradigm.
In this way, the overall state of the application, the global state, is the one that users connect with. Any sort of localized state that behaves differently from that generally comes as a surprise. Surprises are not good. But it is easier for a programmer to write more localized code than it is for them to attach their work into that global context, so we see these types of violations frequently.