2 ms·
I will start with a couple clarifications, in good faith. I will admit that I have made lazy errors in this discussion. Specifically in regard to terminology. A
by Supermancho 5y ago
I will start with a couple clarifications, in good faith. I will admit that I have made lazy errors in this discussion. Specifically in regard to terminology. Afaik, there is no term for "temporally unsynchronized" other than parallelism or concurrency, and I have misused the term concurrency at times. I have also used the term transition to mean "asynchronous state transition". This may clarify my past statements, but I will attempt to do better, going forward.
So I'll visit on the material you are most familiar with so that my comments might have the most specific impact or irrelevance.
For your verification, I read your paper here:
https://www.hpi.uni-potsdam.de/hirschfeld/publications/media/WeiherHirschfeld_2016_ConstraintsAsPolymorphicConnectors_AuthorsVersion.pdf https://www.hpi.uni-potsdam.de/hirschfeld/publications/media...
To begin, I agree on the concept. If "constraining architecture" means any separation of concerns or interface.
To demonstrate that I did read through the code snippets you provided and completely irrelevant to the points being discussed,
I believe there was an error in the code you posted in Listing 8@p.136 -
- k: degreesK {
self basicC :( degreesF - 273.15. \*wat?\*
ivar : ui / celsiusTextField / intValue := self c .
ivar : ui / fahrenheitTextField / intValue := self f.
}
I also thought the implementation was a little muddled and would implement a solution similar to this^.
Object subclass: #Temperatures {
var c.
-changedC : sender {
self c: sender intValue.
self updateValues: { #val : c, #type: 'Celcius' }.
}
-changedF : sender {
self f: sender intValue.
self updateValues: { #val : f, #type: 'Farenheit' }.
}
-changedK : sender {
self k : sender intValue.
self updateValues: { #val : k, #type: 'Kelvin' }.
}
-<void>updateValues: dict {
stringValue := dict#type.
intValue := dict#val.
stringValue = 'Celsius'
ifTrue: [self c:= intValue]
ifFalse: [
stringValue = 'Farenheit'
ifTrue: [self c:= ((intValue-32)*5/9)]
ifFalse: [self c:= (intValue-273.15)]
].
self:updateUi.
}
-<void>updateUi {
ivar : ui / celciusTextField / intValue := c.
ivar : ui / fahrenheitTextField / intValue := c*5/9+32.
ivar : ui / kelvinTextField / intValue := c+273.15.
}
}
^I don't have all the necessary syntax for Objective-Smalltalk, I have munged in some Smalltalk and made up some dictionary derefence syntax. I other languages, I would construct this differently, with the same overall strategy.
After digesting the material, I do not think about the concept of architecture in the way you or Chatty or Backus have been presenting it. In support of this thinking, the idea of seeking the proper GUI abstractions has been sought by most programming language communities. ReactJS (uses HOM like Objective-Smalltalk) or a vanilla actor model^^^, is considered the current state-of-the-art. The MVC layers are most popular in areas where inputs are relatively static within a thread (eg web backend software). In opposition to this thinking, I believe Software Architecture emerges from a combination of mental modeling, language syntax, supported data exchange formats, and resource dependencies/components^^. To some extent, Chatty recognizes this; "We highlight a strong coupling between languages and architecture,..."
Backus (https://dl.acm.org/doi/pdf/10.1145/359576.359579 https://dl.acm.org/doi/pdf/10.1145/359576.359579) proposed that FP was possibly preferable. The main problem with presenting FP as a different architecture, is that it's just a bunch of abstractions on top of VNA (you might enjoy watching https://www.youtube.com/watch?v=otAcmD6XEEE https://www.youtube.com/watch?v=otAcmD6XEEE). Chatty references Turing in 3.1.1@p.6. Ofc Lisp and Occam rely on implicit grouping, in the form of blocks (or any other lexical scope). Fundamentally, FP vs any other style is all the same implementation running on the same kind of machine. A second problem, having to do with specific purpose, is that the side effects in procedural are largely a benefit for the median developer. At each interaction with state, a developer can use a program (that is nothing more than some psuedo-algebraic transforms), into an actor via the consequences of the imperative structure. Lastly, the imperative structure is explicit; although this has started to break down across modern languages. To demonstrate, when using the FP "apply(...)" in Javascript, you can generate outputs that have no explicit inputs (eg https://www.w3schools.com/js/js_function_apply.asp https://www.w3schools.com/js/js_function_apply.asp) breaking the input/output paradigm. This is perfectly normal in FP, which (like the Java Spring Framework) makes VNA code harder to reason about by introducing composition of unrelated structures resolving at runtime. This is a step backward for maintainability, reasoning, testing and formalizing. I cannot be convinced that FP is "the future" or is a different software architecture in any meaningful sense.
As an aside, Erlang and Haskell, which are the most feature rich FP languages around, aren't popular for GUI development. If there was a tangible benefit, I believe it would have been demonstrated.
^^https://resources.sei.cmu.edu/asset_files/TechnicalReport/1994_005_001_16277.pdf https://resources.sei.cmu.edu/asset_files/TechnicalReport/19... - M. Shaw's diagrams supposes that design is focused on components. This is partly incorrect. SDA Diagrams, uniformly track information flow, which necessarily involves a multiple components for information to flow between.
^^^"And not group little bits of GUI+model together, that way madness lies." - almost every game engine and GUI framework uses it. Heck, even the Objective-Smalltalk program is taking inputs from non-trivial widgets, which are precisely small GUI+model underneath.
- Supermancho 5y agoAnd I've even made an error in my "refactor" with the Farenheit conversions. Tests would have made that evident.
- mpweiher 5y ago> If "constraining architecture" means any separation of concerns or interface. It doesn't. It means you work with constraints, for example dataflow constraints. For example: https://dl.acm.org/doi/abs/10.1145/506315.506318 https://dl.acm.org/doi/abs/10.1145/506315.506318 > I also thought the implementation was a little muddled Yes! That was the point of that section of the paper, that doing the straightforward thing leads to a muddle: "At this point, it becomes clear that our original strategy of updating the UI from the individual setter methods is probably not tenable in the long run." A little later: "As we have seen, even a conceptually very simple application such as a temperature converter quickly attracts significant complexity with non-obvious trade-offs once the requirements of an interactive version of that application are taken into account." The fact that you need to create these centralised updater methods is non-obvious, and leads to a bunch of related non-local changes. Also a muddle. "This complexity is not the result of a complicated domain model, but rather of the architectural embellishments required to move data from location to location in order to keep the different parts of the application (model, user interface, persistence) synchronized. In the next section, we will look at a mechanism for simplifying this kind of overhead." > ReactJS (uses HOM like Objective-Smalltalk) ReactJS uses Higher Order Messaging? Where? > Chatty: "We highlight a strong coupling between languages and architecture,..." Which was my point, yes, thank you! We are limited in what languages let us express cleanly. React/SwiftUI etc. are workarounds for this issue: they try to re-cast the GUI "problem" as a simple function/procedure. "The UI is a pure function of the model". If it were true, that would make things very simple. Alas, it isn't true: https://blog.metaobject.com/2018/12/uis-are-not-pure-functions-of-model.html https://blog.metaobject.com/2018/12/uis-are-not-pure-functio... But even without being true, it makes things very convenient, particularly for simple cases. > Backus (https://dl.acm.org/doi/pdf/10.1145/359576.359579 https://dl.acm.org/doi/pdf/10.1145/359576.359579) proposed that FP was possibly preferable. Yep, but he later said that FP was a mistake (Interview with Grady Booch). https://www.youtube.com/watch?t=3896&v=dDsWTyLEgbk&feature=youtu.be https://www.youtube.com/watch?t=3896&v=dDsWTyLEgbk&feature=y... > The main problem with presenting FP as a different architecture, is that it's just a bunch of abstractions on top of VNA That is also one of my contentions: FP, procedural and OO are just variants of the call/return architectural style. https://dl.acm.org/doi/10.1145/3397537.3397546 https://dl.acm.org/doi/10.1145/3397537.3397546 Which is why they are insufficient for today's systems. What's VNA? > you might enjoy watching https://www.youtube.com/watch?v=otAcmD6XEEE https://www.youtube.com/watch?v=otAcmD6XEEE Yes, already seen it. Was good. > feature rich FP languages around, aren't popular for GUI development. If there was a tangible benefit, I believe it would have been demonstrated. Yes. There isn't. If you look at the papers, you will see that the benefit isn't so much claimed as assumed: "now we can get the wonders of FP for nasty GUI development". > "And not group little bits of GUI+model together, that way madness lies." - almost every game engine and GUI framework uses it. Yep, and that's why they all share the same problems (roughly "Massive View Controller"). It's not a trivial issue, because reusable widgets definitely make sense, but they lead you down a nasty path. https://blog.metaobject.com/2015/04/model-widget-controller-mwc-aka-apple.html https://blog.metaobject.com/2015/04/model-widget-controller-... You need to treat those widgets as easy-to-use Views, and interact with them largely as if they were just views.