I think the inability to express sequence diagrams...
# thinking-together
x
I think the inability to express sequence diagrams / state machines via programing constructs directly in code is the main reason why large codebases are unmanageable. AI is largely going to multiply this problem a 100 fold. A simpler way to do this with existing technology is 1. Use a message bus 2. Write functions that talk to message bus 3. All functions without exception must talk to the message bus. No function calls except for the most trivial of ones. All callbacks push to the message bus. Let me call this approach function pipes. Ideally visual node styles also work similarly from an execution perspective, in practice I find it becomes too complex to deal with. A folder of files is much easier to deal with and edit. ZeroMQ provides a request / reply apart from publish subscribe. So I think this technique should be easier to bootstrap. 100% logging is ensured because of the message bus. To make folder organization easier, folder name ~ message bus topic So that way you can always pinpoint all listeners to a message bug topic.
👍 5
k
If every codebase in the world was programmed with these 3 steps, then the world would be immeasurably better. But not because I can see sequence diagrams or state machines. Just knowing, "all calls go through the message bus" is a public good that we have no equivalent for today. Conversely, if you had the tooling to automatically express sequence diagrams and state machines for any codebase, then the world would be immeasurably better. Using a message bus would be irrelevant. In fact, better tooling increases the benefit of compound architectures with more levels of hierarchy and more boundaries. It remains easy to understand and so there are no headwinds on the technical benefits. The universe of domains for software is large, and no single architecture is ideal everywhere. So I buy both sides of your argument, but I don't buy that one is a way to do the other.
g
I definitely agree that lack of sequence diagrams / state machines is a problem. Yet, I think that the problem of code bloat and unmanageability goes much deeper. a) Are you aware of Harel's "Come Let's Play"? Harel created Statecharts, then went on to create scenario-based programming (sequence diagrams afaict). b) I think that calling the approach "pipes" will lead to confusion. This approach is just "message-passing". The name "pipes" has already been taken. c) I tend to think that code bloat is due to something I call "one language to rule them all syndrome". Grace Hopper called it "we've always done it this way". In my view, we've been piling everything and the kitchen sink into a single paradigm, stretching the paradigm way out of its sweet spot and causing exponential bloat (the equivalent to "state explosion" in state machine lingo). I consider Sector Lisp to be the epitome of "functional programming" (better even than Lisp 1.5 - Tunney emphasizes assembler tricks, but I think that Sector Lisp's economy of size is due to other, more important, factors (like pure functional programming - no assignment, no heaps)). We've been forcing out-of-band concepts into the functional (function based) paradigm for 50+ years, like assignment, heaps, memory sharing, etc, and spinning off different, but essentially the same, programming languages (all of which do not achieve the expressibility of machine code). That stuff doesn't honour the functional paradigm and should have been treated with completely different paradigms and notations. UNIX showed us how to compose programs using different paradigms (languages), but fell short by offering up a text-based shell that ignores issues like multiple input/output ports, fan-out, etc. d) A flat message bus will collapse under its own weight as we try to address bigger and bigger problems, i.e. "state explosion". Likewise pub/sub will cause accidental complexity and severe hand-wringing. Harel's Statecharts and UNIX processes plus recursive scripts show ways out of this problem, i.e. hierarchies of isolated components. I.E. not just one bus, but a hierarchy of buses, punting detail successively down to lower levels. IMO, the concept of a "bus" is too ad hoc, I like the concept of "wires" better. e) State machines can cause bloat, too, when used in "one language to rule them all" mode. In my mind a system of communicating state machines is best described by recursive node-and-wire diagrams. Novices attempt to draw node-and-wire diagrams for computational concepts like using "+" boxes to draw "a = b + c". Drawing "+" boxes is bloat. Writing "a = b + c" is more economical when written as text. Communicating state machines should only be used to express concepts that don't fit into the function-based paradigm, e.g. "control flow" (which is a mess in our current function-based languages).
w
But is AI going to multiply the problem? Are we sure of this? For example, last night I was specing out a protocol. Once I had the general real outline of it, having an agent code up a working implementation was trivial. This immediately changes my calculus for iterating on the design. When implementation has basically zero cost, I'm more likely to try several very different designs and then pick the one that is simplest and most elegant. The devil is in the details, so you're going to be sure how well a design is going to work until you try it.
g
AI is No Code for one specific architectural pattern. The one I call "function-based", which is synchronous and sequential. You can build other architectural patterns on top of that one architectural pattern, but the substrate function-based pattern restricts your architectural thinking ("Design"). For example, you cannot build Forth on top of that substrate. Forth doesn't use the function-based "calling convention". The best you can do is to build a fake Forth that adheres to a prematurely-supplied calling convention. Nor, can you build something that is asynchronous and fully parallel on top of that substrate, since the substrate has already eliminated asynchrony from any design you put on top of it. The best you can do is to define synchronous "reactors" and then plumb them together by hand in a manner analogous to writing assembler. I've built many Designs using a different substrate architectural pattern - asynchronous, electronic IC based. From that experience, I conclude that the function-based pattern is too restrictive and bloatful and that we need to break free of it. AI won't help with that.