Relatedly, I have a simple new maths for counting complexity, so that you can compare two "complex" solutions and pick the less "complicated" one: https://github.com/treenotation/research/blob/master/papers/...
SVG form: https://treenotation.org/demos/complexityCanBeCounted.svg
If someone has a philosophical aversion to something like abstraction, then they will label it "complicated," but I use abstraction, all the time, to insert low-cost pivot points in a design. I just did it this morning, as I was developing a design to aggregate search results from multiple servers. My abstraction will afford myself, or other future developers, the ability to add more data sources in the future, in a low-risk fashion.
I also design frameworks in "layers," that often implement "philosophical realms," as opposed to practical ones. Think OSI layers.
That can mean that adding a new command to the REST API, for example, may require that I implement the actual leverage in a very low-level layer, then add support in subsequent layers to pass the command through.
That can add complexity, and quality problems. When I do something like that, I need to test carefully. The reason that I do that, is so, at an indeterminate point in the future, I can "swap out" entire layers, and replace them with newer tech. If I don't think that will be important, then I may want to rethink my design.
That is the philosophy behind the OSI layers. They allow drastically different (and interchangeable) implementation at each layer, with clear interface points, above and below.
Seems to have worked pretty good, so far.
I'm very much a practicum-oriented guy. Theory and academic purity are great, but it's important to ship, which is what I have been doing for thirty-plus years.
I have just found that it is important to do things like establish domains for things like layers, modules, objects, protocols, whatever, and then stick to it.
If my domain is erroneous, then I need to look at that. If not, then I need to stick with it. I tend to plan for the long game. I've written APIs and frameworks that last decades, and that requires planning for the unknown; always a challenge.
Is there overlap between your philosophical layers and practical utility? The kinds of things that have been required to change in my career so far were base assumptions in the business domain, which no amount of premature abstraction could have prepared me for.
I've never witnessed a need to "swap out" an entire layer. Have you? In what scenario did you need to swap out... what exactly? Did these philosophical abstractions turn out to be the correct ones when a need did arise? Did they make the transition to the new reality easier? Does the transition cost outweigh the slower development cost incurred from the abstractions' overhead?
I keep seeing people claim your approach is a good one, and I'm genuinely curious if there is any evidence backing it up. I'll gladly take anecdata.
Many times, but the code assets (and the examples) are not ones that I can share. Feel free to dismiss it, if you like. I won't lose sleep over it.
What I can share, is that I have written frameworks in technology that is either deliberately "low-tech," or that is something that I know will probably not age particularly well, so I make it easy to replace. One example that I can give, is the BAOBAB server, that I wrote a couple of years ago[0]. It has four layers, and the ANDISOL layer[1] is the one that acts as a programmatic façade to the SQL-based database layers, below. It is explicitly designed to be the "swap out" point for the system.
In reality, I would suspect that this would only be the first part of a swap that would eventually replace the BASALT layer[2], but it would allow a graduated, incremental replacement strategy (I have done these a number of times. They are not for the faint of heart).
For example, when I talked about adding a command to the API, I just added one a few days ago, where I added a call to return a fast list of user IDs and display names[7]. I needed this for a "look-ahead" text entry autofill, in a social media app that I'm building on top of BAOBAB.
I could have easily added this to BASALT, and that would have been that. It would have been fast, quite safe, and wouldn't have required the elaborate nested submodule synchronization that is required when I tweak BADGER[3].
The problem is, that the command was a low-level SQL call, at its heart, and those belong in BADGER or CHAMELEON[4]. They certainly should never be exposed above ANDISOL.
So I added it to BADGER, then implemented a "pass-through" in CHAMELEON, and in ANDISOL (what is exposed to BASALT). Since BADGER is nested inside of CHAMELEON, which is nested inside of COBRA[5], which is nested inside of ANDISOL, which is nested inside of BASALT, I had to bump each of their versions, and update the submodule (I despise Git submodules) chain for each.
This is a fairly trivial example, but I take things like modularity, and domains fairly seriously. Also, it's a good way to keep security[6] fairly high.
This may not have answered your question, but it might help you to see how I work.
[0] https://riftvalleysoftware.com/work/open-source-projects/#ba...
[1] https://open-source-docs.riftvalleysoftware.com/docs/baobab/...
[2] https://open-source-docs.riftvalleysoftware.com/docs/baobab/...
[3] https://open-source-docs.riftvalleysoftware.com/docs/baobab/...
[4] https://open-source-docs.riftvalleysoftware.com/docs/baobab/...
[5] https://open-source-docs.riftvalleysoftware.com/docs/baobab/...
[6] https://riftvalleysoftware.com/BAOBAB/PDFs/Security.pdf (Opens a PDF File)
[7] https://github.com/RiftValleySoftware/baobab/commit/d8316a1b...
I am not an expert at server tech. There's a good chance that we'll be hiring contractors to work on the server, once we get a bit more spending dosh.
What you're describing sounds like "essential complexity" vs. "accidental complexity." See "No Silver Bullet."
Sorry, this is pedantic, but using the incorrect terms adds accidental complexity to a topic that is already essentially complex. ;)
No. Complex is the opposite of simple. Complicated is the opposite of easy.
Simple and easy aren’t synonyms - see the talk by Rich Hickey linked in a sibling comment.
I understand there is no definitive source for English, but what is your source on that? Is it Rich Hickey? Because I don't think he has the authority to change the definitions of common English words.
The implementation of it may be amazing code, but none the less it makes the java compiler and runtime far more complicated that it would be if the feature were omitted.
So, again, I agree with you, but I also agree with the articles point that choosing features carefully is an important tool in controlling complexity.