Software Interface Ideals and Order Preference
For a programmer there is an ideal ordered list of preferred interface types for software. What this means is that by default, with no other overriding constraints or concerns, and you're deciding what kind of UI to create first or next for a particular piece of software, or perhaps what will be the only kind, that you should give strong preference to certain types over others. Because if you do, certain benefits will fall out from that decision which will yield a significant net win in terms of architecture, efficiency, and the ability to maintain the software and add future features. That order, from best to worst, is the following:
CLI*
API**
web API (eg. RESTful HTTP with JSON)
web UI, no Flash, just pure HTML/CSS/JS/SVG
web UI, w/Flash
multi-platform desktop app UI (eg. Java Swing)
mono-platform desktop app UI (eg. Objective-C w/Cocoa for OS X)
This order is significant in several ways:
the interfaces higher on the list tend to "just work" on a much wider variety of platforms, out of the box, with little or no porting work, than those lower on the list
the interfaces lower on the list can often be built on top of those higher in the list
the interfaces lower on the list tend to be the most fad-ish and those higher on the list are more stable (worked 20 years ago probably still work 20 years in the future, etc.)
the interfaces higher on the list can be used/driven in a headless environment (no graphics, no monitor)
the interfaces lower on the list tend to require a mouse to navigate them whereas those near the top are usually completely keyboard-drivable
the interfaces higher on the list tend to be easier to test
the interfaces higher on the list tend to be easier to automate
the interfaces higher on the list tend to be easier to integrate with other software, whether beneath, above or along-side to them
the interfaces higher in the list are the most useful when are opaque immutable binaries, with no source code that you can inspect/modify/rebuild
the interfaces higher in the list have a higher ratio of substance to superficiality; those lower on the list have more accidental complexity and a greater ratio of framework-appeasing code/tasks to application-specific code/tasks
the interfaces higher in the list tend to use the least resources to accomplish a given task; those lower tend to use more resources, particularly on the client-side
the interfaces higher in the list tend to give the developer/publisher the most freedom, whereas those lower on the list tend to make you more dependent on a single vendor as gatekeeper who can pull the rug out from under you and/or make you deal with bureaucracy
more FOSS projects (free, open source software) are available in forms at the top of the list than at the bottom
it tends to be much easier to make interfaces near the top self-documenting than those near the bottom
given a legacy dependency on an interface type near the top it tends to be easier to write a new implementation to replace it, as a perfect drop-in workalike, than those near the bottom
interfaces near the top tend to be client screen resolution independent (scale free) than those at the bottom
when building an interface of a type near the bottom of this list, the developer is much more likely to encounter undocumented and unexpected quirks and problems in the platform API's and runtime implementations upon which he is dependent (especially anything related to video, graphics or sound)
apps built with interfaces near the bottom of the list tend to be more fragile with respect to host OS version changes by the OS vendor; often even so-called minor OS version bumps can cause glitches with your shipped app, and some customers will encounter them and be unhappy, requiring you to do more work just to get the experience back to where it was before (ie. a sprint just to stand still)
interfaces near the top can always be built with state-of-the-art high-level concise standard scripting languages whereas the interfaces near the bottom are more likely to require a retro low-level, ancient, verbose, proprietary compiled language, or, if not require them, make it harder to not use them; also you're more likely to be able to use a more exotic but sexy language (like Haskell) to write an app with an interface near the top of this list than an interface type near the bottom
interfaces near the top are more suitable for development using free low-cognitive-overhead tools like vi/emacs, REPLs or CLI toolchains; those at the bottom more suited for slow resource-hogging distraction-heavy GUI IDE's
the top 3 interfaces above all have diff-friendly output, the bottom 4 do not
NOTES:
* You could further subdivide the CLI case into CLI standalone process vs CLI client/server architecture w/multiple processes, but that goes beyond interface into implementation. I tend to start with a single process, monolithic architecture and later break out the implementation into separate client and server portions only when it makes sense. On a related note, in the CLI case, I further bias to starting with a Unix shell script, built on top of built-in shell commands and/or other CLI tools, and then resort to writing custom application code only when needed or it would be a significant net win in comparison. Even then, you can start with a shell script, have it wrap around calls to a custom application, and do progressive evolution of the implementation as needed. I also bias to starting with a scripting language (like bash), then interpreted (like Python), then compiled (like C) as last resort, unless other concerns like performance or minimizing resource usage matter more, AND are obvious at the present time. Some issues won't be obvious yet, and some roadblocks or bottlenecks may never occur. Cross those bridges when you get to them, if ever, not before.
** There is a good argument for ranking API above CLI in certain situations. You generally can't go wrong by having them as your top preferences, in either order. However, even if I build the CLI first, then later an API, I will in those cases refactor the CLI implementation so it becomes "on top of" the new API. Likewise, continuing this pattern, when it comes time to build a web API you should strive to build it on top of the programming API. And ideally the web UI (HTML, etc.) should be built on top of the web API and/or the programming API. This strategy minimizes DRY violations, maximizes platform flexibility and leverageability, while also helping to force or encourage good design choices on the part of the programmer. Vegetables: they're good for you, so eat them.
*** TODO decide how to add/treat REPLs; decide whether to include alternate media/interaction types like IVR, touch, Braille
UP