3 ms·
> So when we get a new interaction mechanism, we write a new connector. Done. Interesting idea... but I'm struggling to get the full picture here... (I might b
by Jupe 5y ago
> So when we get a new interaction mechanism, we write a new connector. Done.
Interesting idea... but I'm struggling to get the full picture here... (I might be way-off here, but):
Is this about "formalizing" connectors? Such that, once a connector technology comes along (RPC, REST, Web Sockets, GraphQL, who knows what next), such connectors could be implemented on either side of the boundary layers and then "selected" via some architectural language? I think the semantics of each "connector" demands different design constraints on either side of the equation.
An overly simplified example: Java logging "appenders" allow dispatching log messages to different targets (stdout, filesystem, database, etc.) But, STDOUT doesn't "fill up", while file systems/databases do. DB's support querying, while STDOUT does not. DB's do get overwhelmed; should processing halt until such "overwhelmed" situations get resolved? Databases (should) include security; STDOUT does not. Etc.
If there were different "types" of connectors defined, each with different behaviors, and those could be easily chosen, then maybe. But even the "types" would be solution-dependent. Retry rules, idempotency, serialization rules, compensating transaction support, etc. These topics (to me) are far more important than simply creating new connectors.
- abernard1 5y ago> These topics (to me) are far more important than simply creating new connectors. Yes. What this vision requires is pushing down a shared library or coordinated behavior into every new language or future technology that requires it. If the behavior is not actually required, and is more of a suggestion, then it's a "protocol" and requires interface modifications everywhere. And now we're back to "why do we need this shared code/language?" and "how is this different than patterns?" This model has been tried many many times. We just got rid of the ignominious stench of CORBA and its removal from Java in the last year after a 25 year failure. The architecture astronauts require their language to be guaranteed across wire boundaries which is a fancy way of saying that their uber-language needs to be implemented in all the subsystems for guarantees to work.
- mpweiher 5y ago> What this vision requires is pushing down a shared library or coordinated behavior into every new language or future technology that requires it. NO IT DOES NOT. Please do not repeat this false claim. > This model has been tried many many times No. What YOU describe has been tried many times. It doesn't work. We agree. > The architecture astronauts require their language to be guaranteed across wire boundaries Yep. This does not. > which is a fancy way of saying that their uber-language needs to be implemented in all the subsystems for guarantees to work. Yep. Which is why that is a bad idea.
- mpweiher 5y ago> Interesting idea... Thanks! > but I'm struggling to get the full picture here... Me too, but I've been struggling much longer :-) > Is this about "formalizing" connectors? Operationalizing more than formalising, although that is a variant of formalising. "Let's actually program using architectural abstraction", rather than just (variants of) procedural abstraction. Or rather than just using architectural abstraction to describe systems that we then still have to program procedurally.
- Jupe 5y agoOk, call it "operationalize" vs. "formalize". I'm still completely unsure how my logging example above would play-out. I've briefly looked at your code samples, but still not getting it. I just don't see how this is a "programming language" thing.
- mpweiher 5y ago> I just don't see how this is a "programming language" thing. I think you're getting it just fine, because most of it isn't a programming language thing, and shouldn't be. I explain this in more detail in my paper: Can Programmers Escape the Gentle Tyranny of Call/Return [1] We've really been able to build these kinds of architectures for some time using call/return, and particularly using OO. However, we haven't been able to directly express them in code. Andrew Black put it really well: "The program’s text is a meta-description of the program behaviour, and it is not always easy to infer the behaviour from the meta-description." The fact that this is so indirect leads to all kinds of mayhem, with one particular kind of mayhem being that good architecture in our current systems necessarily entails indirection, which leads architecture astronauts to the conclusion that it is the indirection that is the good thing, and thus they indirect away. > I'm still completely unsure how my logging example above would play-out. For one, it doesn't really require a lot of linguistic support for the parts you mention. In general, the idea is to have as little in the language itself as possible. "Talk small and carry a large class library". But a little bit is needed. For streaming/pipe-and-filter support, which I think the logging would slot into, I use Polymorphic Write Streams [2]. These are just some classes implementing a pipe-and-filter architectural style using a few protocols and some triple-dispatch trickery. They can be connected to stdout, to variables, ordered collections, to GUI text fields and surely also to logging subsystems. The linguistic support is fairly minimal: the polymorphic "->" connection "operator", which can be used to connect filters into a pipe but is not specific to filters, and a bit of syntactic sugar that ensures defining a filter is no more effort than defining a method. So a small script to convert input to upper case looks as follows: #!env stsh filter toupper |{ ^object stringValue uppercaseString. } (stdin -> toupper -> rawstdout ) run The 'filter' keyword introduces a filter definition, which is just shorthand for a class definition (see the C++ metaclasses proposal by Herb Sutter. This is similar but not as sophisticated). Then we connect stdin to the filter and the filter to stdout (rawstdout, the default stdout is cooked). I gave a number of additional examples in my UKSTUG talk: https://vimeo.com/655812971 https://vimeo.com/655812971 In a more general form, logging also enables dataflow constraints: any store can be wrapped in a logging store that logs all accesses. That logger can then be connected to a copy-stream that takes two stores and applies the operations that were logged to those stores. But you can also just connect the logging store to stdout (or a database, or a file) for debugging purposes. There's more, but the central idea is to have as little linguistic support as possible, but of course as much as needed. It would have been nice if that could have been driven to zero, but alas that's not the case. [1] https://www.hpi.uni-potsdam.de/hirschfeld/publications/media/Weiher_2020_CanProgrammersEscapeTheGentleTyrannyOfCallReturn_AcmDL.pdf https://www.hpi.uni-potsdam.de/hirschfeld/publications/media... [2] https://dl.acm.org/doi/10.1145/3359619.3359748 https://dl.acm.org/doi/10.1145/3359619.3359748