4 ms·
I think one aspect is that often we make decisions without fully understanding the consequences. The decision might be a conscious choice, but the consequences
by Sakos 2y ago
I think one aspect is that often we make decisions without fully understanding the consequences.
The decision might be a conscious choice, but the consequences of that choice may be unintended if it's a complex enough system and there's insufficient knowledge of the system to recognize all the potential consequences.
And sometimes (often?) it's not possible to know all the possible states a particular system can end up in. This is the whole point of paradigms like functional programming and ideas like immutable state. It's the recognition that even if we put in the most utmost care, there might be more possible states than we're able to comprehend and account for.
It might be possible, with a lot of care, for a solo programmer to control the state explosion associated with developing an application, but once there's more than one developer, once there's a team and an existing codebase (or code bases) that's been around for 20-30 years, it's impossible without doing NASA levels of verification.
And all of that is before considering how our decisions affect what decisions we can make in the future or how it shapes those decisions (as well as affecting the decisions of others that we may never meet).
- msephton 2y agoI absolutely agree with you on that. I had just edited my answer above to include a fi all paragraph basically saying the same thing. It doesn't need to be black or white, one or the other, it can be both or anything in between. The fact that one system might be too complex to contain doesn't rule out a much smaller system that can sit quite happily in the mind of a single person. I'd also like to thank you for bringing up the consequences of choice. Maybe I'll add that as an extra section at some point, as I feel I have a lot to say about it.
- Sakos 2y ago> The fact that one system might be too complex to contain doesn't rule out a much smaller system that can sit quite happily in the mind of a single person. Yes, definitely. Also that complex systems can be reduced to smaller and simpler ones where making a decision doesn't have to mean unleashing a cosmic horror. > I'd also like to thank you for bringing up the consequences of choice. Maybe I'll add that as an extra section at some point, as I feel I have a lot to say about it. Sounds great. I really enjoyed your post. I've often been in these situations where a customer will ask why a certain thing works a certain way and I'll overhear the discussion between the developers who, as it turns out, only inherited that decision from somebody else, but the response is all the same: "This is the intended behaviour". Even though nobody currently at the company ever intended it to behave that way. We might placate the customer by mentioning we might take a look at it in the future, but it's the same as a user accepting the defaults. The current owner accepts the current behaviour and becomes complicit in the design decision, even implicitly becoming the reason why it persists until the next owner (and probably every owner after that).
- prometheus76 2y agoI disagree with the part where you say "complex systems can be reduced to smaller and simpler ones where making a decision doesn't have to mean unleashing a cosmic horror." That's the whole problem with reductionist thinking, which fails when analyzing a chaotic system or a complex system. The behavior of the whole is greater than the sum of the parts because of hidden interactions between the smaller parts of the system. There are too many variables to account for, and small variations in initial conditions rapidly became very divergent outcomes. I get the sense that you may not have studied chaotic systems or complex systems in any level of detail. It might be a worthwhile effort to learn more about those systems, because they are essentially a refutation of reductionist thinking. You may understand your codebase completely, but I assure you, if you released it to a large enough group of people, they could find errors and bugs in your code because they will try things that would never occur to you. I am reminded of a video where a programmer spent three years training an ai model to beat an "impossible track" in trackmania, where he finds out that chaos built into the deterministic physics engine behind the game made his pursuit much more difficult. https://www.youtube.com/watch?v=kojH8a7BW04 https://www.youtube.com/watch?v=kojH8a7BW04
- Sakos 2y ago> That's the whole problem with reductionist thinking, which fails when analyzing a chaotic system or a complex system. The behavior of the whole is greater than the sum of the parts because of hidden interactions between the smaller parts of the system. There are too many variables to account for, and small variations in initial conditions rapidly became very divergent outcomes. > I get the sense that you may not have studied chaotic systems or complex systems in any level of detail. It might be a worthwhile effort to learn more about those systems, because they are essentially a refutation of reductionist thinking. There's a world of difference between a chaotic system like the weather and something designed and implemented by humans like a set of interconnected micro-services. I couldn't possibly hope to comprehend all the factors and variants and invariants in a weather system, but I can understand (to a certain degree) how services interact, how data flows through a human-built system, how data is represented and processed inside of a service. It's usually possible to improve parts of a system so you don't necessarily need to take the whole system's complexity into account in every decision you make. And I think we're all at least implicitly aware of it, or we wouldn't waste our time with worrying about abstraction, encapsulation, side-effects, coupling, or mutable state. We wouldn't have all these books about how to design software architecture or write clean, maintainable code. > There are too many variables to account for, and small variations in initial conditions rapidly became very divergent outcomes. If that were true, we might as well all pack up and give up. I can figure out what inputs might end up in a certain method and what outputs are possible for given inputs. And if I can't because of how the method is designed, then I can make changes that reduce the relevant state to the point where I can reason about them. There are countless variables in a system, sure, but the amount of variables at a particular point of a codebase that actually need to be accounted for are not necessarily countless. With the wrong architectural decisions, they can be countless, but that's why we avoid things like global mutable state. We are responsible for the complexity of a particular software system, which also means we have the ability to reduce or increase the complexity with the decisions we make. > I am reminded of a video where a programmer spent three years training an ai model to beat an "impossible track" in trackmania, where he finds out that chaos built into the deterministic physics engine behind the game made his pursuit much more difficult. Well, yeah, if that's the kind of system you're talking about, then sure. That's a complex system that can't be simplified or reduced, because you're literally trying to approximate real world physics. The purpose of that system is inexorably tied to its complexity. I don't envy programmers who have to deal with that form of system. > You may understand your codebase completely, but I assure you, if you released it to a large enough group of people, they could find errors and bugs in your code because they will try things that would never occur to you. I don't understand this argument. I might not be able to get rid of all bugs, but that wasn't a claim I ever made. We definitely can reduce the amount of bugs we have and the amount that we create with new code by making efforts to control the complexity affecting the code we write. > because of hidden interactions between the smaller parts of the system Going back one last time, yes, there are often hidden (or unknown) interactions between different parts of a system, but our only option isn't just to say, "well, I guess there's no way to deal with that, let's make that new feature and hope it works out". An important part of maintaining/improving a software system is uncovering these interactions and making them an explicit, visible part of the system (or removing them if they're unintended and unwanted), as well as evaluating the possible risks and consequences of decisions being made and how/when/where to mitigate them as best we can to the best of our current knowledge. Also an important part of designing these systems is reducing how different parts of a system are coupled to each other, isolating them from each other and localizing their effects as much as possible. You might not be able to reach some Platonic ideal of a simple non-complex system with no unintended interactions, but it is clearly possible to move a complex software system in that direction and there are plenty of benefits for doing so.