1. 31
  1. 7

    I enjoyed the progression from Amdahl’s Law to Brook’s to Conway’s, but I find the conclusion of the talk to be too weak to be worth using as ammunition when discussing the problems with modern software development. To be clear: I too believe that hype-driven modern software development is bad, but I also think that we need better arguments than the ones presented in this video.

    The most poignant example of this is how Casey mentions microservices at the end of the video in the naughty list of software practices. What he seems to ignore, is that all good literature about microservices recommends placing the boundaries between different systems precisely where the boundaries in the company org chart are. This is done in order to minimize the amount of effort required to react to a change request by the business (Conway’s Law). So why break everything into services in the first place? To lower communication overhead between development teams (Brook’s Law) in order to parallelize the development work as much as possible (Amdahl’s Law). This is not to say that microservices are great and the futureTM, but it’s a reasonable approach to enterprise software development even within the mental framework that Casey himself delineated in this talk, which instead seems it was supposed to argue against the practice with enough clarity to justify a self-evident naughty list at the end.

    Microservices (in enterprise software development) are just one example of a situation where software is a support activity and not what’s supposed to drive the design, which in my opinion is the key insight missing from this talk.

    This video itself for example was most probably created using OBS and a window capture of powerpoint + color keying. In a stringent interpretation of the talk, surely a custom-built integrated solution would be better than this mess of abstraction layers, but the reality is that from the perspective of just wanting to make a video, color keying is good enough, and the same applies to most companies that just want to get their business done.

    So in my opinion the fact that Windows has that many glaring flaws is more of a reflection of how Microsoft’s priorities have shifted over time away from selling software, more than how bad they are at software architecture.

    To me the real unbreakable law is:

    The less software is core to a company’s business model, the more it will suck. Conversely, the more software sucks, the less it is core to a company’s business model (despite of how the company wants to position itself).

    1. 5

      This was a joy to watch!

      Made me wonder that maybe there is more juice than I thought in the “0 dependencies” folks and suckless philosophy manifesto (https://suckless.org/philosophy/).

      Thank You, Mr. Conway. And we’re sorry ahah

      1. 8

        Every dependency carries a cost, that at least must be justified by its benefits. So yeah, cutting back on dependencies does have its benefits. On the flip side, we can also reduce the cost of each dependency: if I’m writing a library, it will cost less if I manage to simplify the build system, the size of the API… or the number of sub dependencies.

        Note that API width is a huge part of a dependency’s cost. The wider the API, the longer it takes to learn. Wide API effectively require larger communication bandwidth. A bandwidth that you do not have, because you’re just trying to make your stuff work, and the expert that wrote your dependency doesn’t answer emails anyway.

        That’s why Ousterhout insist that classes should be deep: that’s because APIs, internal or exposed, are overhead that is best minimised. I can think of three ways to do this:

        • We can reduce functionality. Just omit the less important stuff. You ain’t gonna need it. Hopefully.
        • We can simplify the API. Find commonalities, make it more orthogonal.
        • We can move the API boundaries. We need to cut the program at its joints, and put the APIs where they’ll naturally be the smallest.

        That last one is often forgotten. Take OpenSSL for instance. Specifically its BIO (Buffer Input Output) interface. Originally, it provides lots of function that took file descriptors as parameters. Except people also needed to work with memory buffers, without having to write files just because the API said so. They “corrected” the mistake by basically duplicating the whole API with bio versions of the same functions. As for the buffers themselves, they were actually an abstraction that could hide either a file descriptor, or a memory buffer, depending on how it was set up.

        In hindsight, this design is absolutely insane. It’s pretty obvious now that they should have have a memory based interface instead. OpenSSL is a Cryptographic library. It computes stuff, and as such should not concern itself with the trivialities of I/O. Just read from and write to buffers, let users move the data where they need to. If users wanted memory buffers, they have them. If they wanted to write to files or the network, they can just do so. And indeed, more modern cryptographic libraries now do stick to simple memory based interfaces.

        1. 3

          This response is a much more introspective take, thank you.

          What the “Molly Rocket” fails to put emphasis on is that there are benefits to subdivision and that the reason to incur the cost of abstraction is because those benefits outweigh the cost. Thanks for highlighting this and for providing practical advice on API design.

          1. 4

            What the “Molly Rocket” fails to put emphasis on is that there are benefits to subdivision and that the reason to incur the cost of abstraction is because those benefits outweigh the cost.

            I believe he does so deliberately, to swing a pendulum he feels has swung too far the abstraction way. He probably assumes most of us have already been thoroughly exposed to the many benefits of abstraction. I wouldn’t repeat this advice in front of beginners however, they’d run the risk of feeling justified in making a mess of their programs.

      2. 4

        I was ready to bag on the video but it was very good and I learned a lot of subtlety about Conway’s Law that I hadn’t considered before.

        I will say that he’s pretty critical of the subdivision implied by Conway’s law and makes sweeping statements about it being bad. His argument is that subdivision of labor into modules in the org/code chart necessarily impose a communication interface that restricts the possibility space a-priori, before the solution space is understood. While this is true, the thing he misses is that by breaking problems into components, this allows for parallelization and subdivision of labor, a point that he almost surely understands because he’s mentioning Amdahl’s law, but doesn’t make the leap to give his interpretation more nuance.

        Put another way, yes, subdividing the space into an ‘org-chart’ necessarily imposes constraints on the solution space but this is, in some sense, the best we can do with any problem. The possibility space is exponentially large and without this type of structure the exploration could take exponentially longer as the problem grows. We restrict ourselves to problems that can be solved efficiently (or some semblance thereof).

        The deeper question, for me, is coming up with strategies that can allow for sections of the org chart to either be merged into other parts more seamlessly or, more realistically, be made so that they can be removed with minimal damage.

        1. 3

          Put another way, yes, subdividing the space into an ‘org-chart’ necessarily imposes constraints on the solution space but this is, in some sense, the best we can do with any problem.

          This is exactly what he was saying.

          1. 2

            No, he said multiple times that this was “very bad”, “wrong” and that we shouldn’t do this in order to solve more complex problems.

            A kind reading is him saying there’s an optimal solution that might be within reach with better processes or “processing power” (maybe via a musk implant?) but he misunderstands the nature of the fundamental problem.

            It’s not about being clever. The solution space grows exponentially. There is no hope but to break problems into smaller segments for solution. The best we can ever do is subdivide the space to find a solution and to find a cleaner way of swapping out our subdivided blocks to explore different parts of the solution space.

            Put another way, you’ll quickly end up spending more energy searching the space than you would ever extract from finding the solution. It’s easy to construct examples where you’ll quickly end up using the energy budget of the universe before finding an optimal solution.

            I agree with the sentiment. “Lean and flexible” is a great philosophy. I’m arguing over the inflection of how to implement such a strategy. He seems to be advocating for “throw out encapsulation, explore the space for the optimal solution”. I’m advocating for “understand that encapsulation is a fundamental constraint, figure out how to swap encapsulated bits more easily”.

            1. 4

              Ah, I see. Even a Superhuman AI past its Intelligence Explosion would be limited in finding the best program for any given problem, and thus has to find ways to cut the search space. And at the very least, assuming P ≠ NP, a strategy that guarantees we’ll find the best solution is also guaranteed to be computationally intractable. Thus, all tractable strategies will have suboptimal results, and we have to accept that.

              Still, his point remains: our human limitations are far lower than that of a superintelligence, and the skill of the average hireable programmer is quite a bit lower than that of our best geniuses. This means we need to cut the search space even more drastically, and end up finding even worse solutions.

              This is made even worse at the start of a new project, when we know least about it. We need to be prepared for the fact that a couple months or years down the line, we’ll understand the problem better, and see solutions we could not even dream of at the start. That would be my “lean and flexible” approach: understand that we start out as noobs, and let our future expert selves room for finding better solutions. That often means not setting teams in stone.

              Of course, if a field is properly understood, it makes sense to put strong interface boundaries where we just know they won’t cost much. For instance, it makes a lot of sense to write cryptographic libraries whose sole job is to read and write memory buffers. Not only does it enable a nice separation of labour, such interfaces have very little computational cost, compared to that of the cryptographic primitives themselves (at least on CPUs).

          2. 2

            Yes and I think there is more:

            Very often an apriori subdivision allows us to solve a problem faster than without it and while something better is possible, it is good enough.

            For many business areas most of the individual problems are trivial and the only challenge is to make them all work together.

            Enforcing a consistent super structure on multiple sub solutions might well be the best way. I think he acknowledges this and at the same time condemns it. I have a hard time understanding why you condemn the best possible solution.

            Practically, I wonder if it is more harmful to reorganize the org to the problems at hand frequently or keep the org relatively static.

            You could argue that the second leads to easier to understand designs since the time org chart axis is eliminated. Of course, only if the org has a good enough structure.

            The first one seems to be a more project - oriented approach. I think it actually works well for new stuff but then maintenance and ownership become difficult.

          3. 2

            This talk suffers from “if you have a hammer, everything looks like a nail”. At the end of the talk, it tries to apply Conway’s Law for everything (libraries, containers, microservices, …) saying it’s just the same reason behind it. But it is not. Of course, these things allow us to split the work but many of them are not done in the first place because of that, but because of DRY, reliability, reproducibility, isolation,…

            Still, most of the message applies, the communication bandwidth between team members is higher than with the rest of the teams. And that is going to create not-so-focused products. So, as long as we’re still humans, the law would apply.

            1. 1

              It was all over the place in the beginning, and the talk probably could’ve been done in half the time, but it was quite interesting.

              Makes me wonder if Conway’s law (that’s what the video is about) can be “broken” if you have one team that’s responsible for design (be it technical architecture design or UI/UX design) that every team has to go through to make decisions. This team could keep a more holistic view and eliminate historical cruft (or prevent new cruft from accumulating).

              1. 2

                Interesting idea, though in practice I can see that architecture team becoming a gigantic bottleneck if the problem gets big enough. That means it will then need to break into separate communicating sub-teams, and you’re back to square one. Plus, in most cases I would expect that team to gradually lose perspective of the “boots on the ground” problems of development and operations, unless they’re very good/experienced.

                Doesn’t mean all of that is inevitable, of course, just that seems to be the obvious failure mode. You’re just following Conway’s Law again.