> Using abstraction to manage complexity is fine. Obfuscation of complexity is not.<p>The post pushes these words around without giving any indication as to how to actually do anything. Seems like an example of moving definitions around.<p>The important thing when dealing with complexity is to decompose it into simpler parts that combine neatly. This is one meaning of 'good abstraction'. I don't like the word abstraction, as I also don't like the word refactor--they almost explicitly sound like arbitrary collecting/moving things about.<p>The word I use is 'factor'. I say I'm factoring the code. Then you have to be able to name which factor a particular piece of code has dealt with. If you can't answer that, you're just moving stuff. And once that's done, it shouldn't immediately need to be redone/refactored.<p>If something is complex because it has N dimensions, then try to create N components to deal with each factor as is possible rather than create refactorings that deal with some combinations of dimensions that follow chronological developments rather than structural ones with empty seams.
<a href="https://tools.ietf.org/html/rfc1925#page-2" rel="nofollow">https://tools.ietf.org/html/rfc1925#page-2</a><p>RFC 1925 "Fundamental Truths of Networking", section 2:<p><pre><code> (6) It is easier to move a problem around (for example, by moving
the problem to a different part of the overall network
architecture) than it is to solve it.
(6a) (corollary). It is always possible to add another level of
indirection.</code></pre>
A week or two ago, I was working with a colleague who wanted to get me set up to deploy my code to an AWS service he had provisioned for us. "I use this tool that makes it super-simple," he said. It's true, typing the command to deploy takes no time at all.<p>However.<p>It took an entire day's work to install the prerequisites. Docker. Node.js. The authenticator tool that for some reason needs an entire headless Chromium. The tool that actually does the deployment. Configuration files with magic strings in them. YAML. JSON. After a year and a half of fairly stable operation (at least as good as you can get from Windows 10), my work laptop now randomly bluescreens. Neither he nor I understands what most of this stuff does -- it's tribal knowledge he found on a corporate OneNote somewhere. I have no idea what we just automated away, or how difficult it would be to send my 500 lines of Python code to this cloud service by hand.<p>On the plus side, I can now deploy my code by typing ten characters in the console.
As a software architect, I can tell you that complexity is bad. For architects, there are two types of complexity; accidental complexity and essential complexity. The latter is inherent in the problem in that reducing essential complexity means that you are not solving the problem that you are supposed to be solving.<p>When I say problem, I don't just mean the functional requirements. I also mean the so-called non-functional requirements. If you are familiar with use cases or user stories, then you know of functional requirements. Non-functional requirements can take the form of Service Level Agreements but also include other metrics such as the costs to running the system and feature velocity.<p>Accidental complexity is unnecessary to solving the problem. It is a clear win to reduce that. Often you get to the point where you still have a lot of accidental complexity but cannot affordably reduce it any more. That is when you obscure complexity. That doesn't necessarily mean adding yet another layer of abstraction. It can also mean pushing the complexity from one already existing layer to another. This can be very helpful if the layer of abstraction that you are pushing the complexity too has a lower feature velocity than the layer that you are pushing it from. I have written on this subject over at <a href="https://www.infoq.com/articles/obscuring-complexity/" rel="nofollow">https://www.infoq.com/articles/obscuring-complexity/</a><p>In this scenario, I would argue that obscuring complexity is not harmful. In fact, it can be quite helpful.
The Arch Linux philosophy summarizes this concisely: "If you try to hide the complexity of the system, you'll end up with a more complex system"