TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

The complexity that lives in the GUI

361 pointsby yes_but_noover 4 years ago

40 comments

brundolfover 4 years ago
The fundamental challenge of GUIs is that they have state as a core concern. Unlike most systems, state is not an implementation detail that can be refactored away. It is central to the problem domain. The <i>end user</i> sees and cares about having a stateful system.<p>The hardest part of dealing with state in a complex system is maintaining consistency in different places. Some instances of this this can be avoided by creating single-sources-of-truth, but in other cases you can&#x27;t unify your state, or you&#x27;re dealing with an external stateful system (like the DOM), and you have no choice but to find a way to keep separate pieces of state in sync.<p>I should probably write a blog post on this
评论 #26134194 未加载
评论 #26134046 未加载
评论 #26137618 未加载
评论 #26136574 未加载
评论 #26136807 未加载
评论 #26135200 未加载
jonathanstrangeover 4 years ago
Here is my personal opinion on it (not sure if it&#x27;s the right one, though): Write the GUI independently of the model, let the GUI components update and communicate among each other as they like, and perform some validation in these GUI components. Translate between model and view only at one well-defined point at which there is also a final validation at the model side, and make sure model and view are only loosely coupled.<p>Good GUIs have way too many requirements to be controlled (via a controller) by the model. As a typical example, the fact that a button should only be activated if there is data in a textbox has usually nothing to do with the underlying model. The model should only ever contain valid and consistent data.
评论 #26133706 未加载
评论 #26133228 未加载
评论 #26136848 未加载
ChrisMarshallNYover 4 years ago
This is a great discussion on the challenges of designing UI for complex applications.<p>In the aggregate, what ends up being most effective for me, is rapid prototyping, and “paving the bare spots.”[0]<p>I find that I do a terrible job of predicting user mental models.<p>The rub with prototypes, is that they can’t be lash-ups, as they <i>inevitably</i> end up as ship code. This means that a lot of good code will get binned. It just needs to be accepted and anticipated. Sometimes, I can create a standalone project for code that needs to go, but I still feel has a future.<p>So there’s always a need for fundamental high quality.<p>What has been useful to me, is Apple’s TestFlight[1]. I write Apple software, and TestFlight is their beta distribution system.<p>I start a project at a very nascent stage, and use TestFlight to prototype it. I use an “always beta” quality approach, so the app is constantly at ship quality; although incomplete.<p>It forces me to maintain high quality, and allows all stakeholders to participate, even at very early stages. It’s <i>extremely</i> motivating. The level of enthusiasm is off the charts. In fact, the biggest challenge is keeping people in low orbit, so they don’t start thinking that you are a “WIZZARD” [sic].<p>It also makes shopping around for funding and support easy. You just loop people into the TestFlight group. Since the app is already at high quality, there’s no need for chaperones or sacrifices to The Demo Gods.<p>I like that it keeps development totally focused on the actual user experience. They look at the application entirely differently from me.<p>[0] <a href="https:&#x2F;&#x2F;littlegreenviper.com&#x2F;miscellany&#x2F;the-road-most-traveled-by&#x2F;#paving" rel="nofollow">https:&#x2F;&#x2F;littlegreenviper.com&#x2F;miscellany&#x2F;the-road-most-travel...</a><p>[1] <a href="https:&#x2F;&#x2F;developer.apple.com&#x2F;testflight&#x2F;" rel="nofollow">https:&#x2F;&#x2F;developer.apple.com&#x2F;testflight&#x2F;</a>
评论 #26132370 未加载
digganover 4 years ago
I&#x27;m fairly sure I&#x27;ve said this before here and elsewhere, but bears repeating, especially for this post.<p>Statecharts is currently probably the most undervalued tool when it comes to programming GUIs with state. Statecharts are a continuation of state machines, but with less footguns and better abstractions to be able to build larger systems.<p>In the end, you either build a GUI that are using state machines implicitly, or explicitly. Tends to be less prone to bugs if you do so explicitly.<p>If you&#x27;re interested, here is some starting points (copied from an older comment of mine):<p>Here is the initial paper from David Harel: STATECHARTS: A VISUAL FORMALISM FOR COMPLEX SYSTEMS (1987) - <a href="https:&#x2F;&#x2F;www.inf.ed.ac.uk&#x2F;teaching&#x2F;courses&#x2F;seoc&#x2F;2005_2006&#x2F;res" rel="nofollow">https:&#x2F;&#x2F;www.inf.ed.ac.uk&#x2F;teaching&#x2F;courses&#x2F;seoc&#x2F;2005_2006&#x2F;res</a>...<p>Website with lots of info and resources: <a href="https:&#x2F;&#x2F;statecharts.github.io&#x2F;" rel="nofollow">https:&#x2F;&#x2F;statecharts.github.io&#x2F;</a><p>And finally a very well made JS library by David Khourshid that gives you lots of power leveraging statecharts: <a href="https:&#x2F;&#x2F;github.com&#x2F;davidkpiano" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;davidkpiano</a><p>While we&#x27;re at it, here are some links to previous submissions on HN regarding statecharts with lots of useful and interesting information&#x2F;experiences:<p>- <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=18483704" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=18483704</a><p>- <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=15835005" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=15835005</a><p>- <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=21867990" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=21867990</a><p>- <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=16606379" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=16606379</a><p>- <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=22093176" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=22093176</a>
评论 #26131746 未加载
评论 #26131634 未加载
madhadronover 4 years ago
I mean, of course you lift the state. It&#x27;s just like a database. You have a normalized model containing the state, and the GUI is a view on it. Events from the GUI trigger transactions that update the state and then every element is triggered to update itself based on the new state. That should never trigger a loop of events, because a view updating itself from the model should never trigger transactions on the database.<p>Many complicated views have their own internal models for things like where they are scrolled, what columns are shown, or what elements of a tree are expanded. But those compound views are written so that, from the outside, they appear exactly the same as any other view.<p>&gt; I’d love to hear what the functional programming camp has to say about this problem<p>It&#x27;s called functional reactive programming.
评论 #26134696 未加载
评论 #26136455 未加载
flohofwoeover 4 years ago
IME, working with an immediate mode UI framework automatically gets rid of most such &quot;architecture astronaut&quot; problems.<p>But I found that it&#x27;s almost impossible to describe to someone used to event-&#x2F;callback-driven UIs <i>why exactly</i> that is. You really need to try it yourself on a non-trivial UI to &quot;get it&quot;.
评论 #26132896 未加载
评论 #26132691 未加载
评论 #26132323 未加载
评论 #26132266 未加载
评论 #26132474 未加载
hermitcrabover 4 years ago
I find that Qt signals and slots works pretty well for managing complexity in GUIs. In this case you would connect a signal that is emitted when inventory table changes state to a slot that changes the appearance in the user avatar. This would probably be done in the pane&#x2F;dialog that contains them both. They 2 components would remain nicely decoupled.<p>This approach isn&#x27;t without it&#x27;s own challenges of course. For example it is sometimes hard to keep track of what is going on in complex applications with cascades of signals and slots. Some people also hate the fact that signals and slots use auto generated code, but I have never really found that to be a problem in practise.
评论 #26133620 未加载
评论 #26132386 未加载
IshKebabover 4 years ago
This is a really good take on the (still unsolved IMO) problem, though I suspect it only makes sense to people who have experienced all the issues personally, since so many of them are &quot;it gets really awkward with big programs&quot; type problems.<p>He did miss out a pretty significant flaw of message busses - the producers and consumers of messages are completely decoupled, which makes debugging really annoying because you don&#x27;t have anything like a stack trace. You just know that your component received a message, and good luck trying to figure out where it was sent from and why.<p>That&#x27;s also a big problem with magical reactivity systems like Vue. Your stack trace is pretty much &quot;yeah something changed somewhere so we&#x27;re updating this component. Don&#x27;t try and figure it out.&quot;
评论 #26133619 未加载
评论 #26134563 未加载
erdoover 4 years ago
So nice to see this universal issue being discussed, it doesn&#x27;t seem to get as much attention as it deserves.<p>IMO, a great solution here is along the lines of &quot;Lift the state up&quot; &#x2F; &quot;MV(X)&quot;. But... there is a vital detail which is usually missed when deciding how exactly the state in your M gets passed to your V for display: you must refresh your entire V when M changes in any way, not just the bit of V that you think changed. It&#x27;s the only way to completely remove these difficult to test, hard to spot edge cases that the article discusses.<p>This is almost impossible to talk about without specific examples, so a while back I wrote such an example that I think distills the core problem, and demonstrates how refreshing the entire V not only solves the problem but typically takes less code to do it: <a href="https:&#x2F;&#x2F;dev.to&#x2F;erdo&#x2F;tutorial-spot-the-deliberate-bug-165k" rel="nofollow">https:&#x2F;&#x2F;dev.to&#x2F;erdo&#x2F;tutorial-spot-the-deliberate-bug-165k</a>
smhgover 4 years ago
&gt; There is also another way of making GUIs called Immediate Mode that is commonly used for drawing user interfaces in games. In this mode the GUI components are no longer subscribing and waiting for events to come, but are instead a part of the main loop that runs at 60 fps and re-render themselves based on the current “global” state.<p>&gt; Immediate Mode GUIs somehow never reached the critical mass and you are probably not going to find it outside of the games industry.<p>Isn&#x27;t this what React is built on? I think this was part of the &#x27;original&#x27; selling point by Pete Hunt: <a href="https:&#x2F;&#x2F;youtu.be&#x2F;x7cQ3mrcKaY" rel="nofollow">https:&#x2F;&#x2F;youtu.be&#x2F;x7cQ3mrcKaY</a> (2013). Around 20:00 in that video he compares React with the Doom3 engine.
评论 #26135027 未加载
评论 #26135127 未加载
MaxBarracloughover 4 years ago
&gt; Clicking on buttons will start triggering events which will modify the state in the model that will in turn start triggering event listeners causing your GUI to flash like a christmas tree. The problem of data bindings and change listeners is that they make it really easy to introduce a hidden circular event listeners that will trigger one another multiple times (event A changes state B and change of state B triggers event A).<p>Agree with both of these points. You can no longer treat assignment simply as the way you mutate data, you also have to anticipate its effects in the data-binding system.<p>I imagine the circular event problem could be addressed with static analysis, but I don&#x27;t know of any framework that does this.
评论 #26133004 未加载
评论 #26132706 未加载
评论 #26131958 未加载
heycosmoover 4 years ago
I have a simple rule for GUI design: build trees not graphs. Write components that accept a state snapshot and broadcast changes. If component A listens for state changes from B, then A is a parent node of B. If A sends state to B, then A is a parent of B. Components reconcile state before broadcasting changes toward the root of the tree.<p>Often there is a price paid in brevity, but I believe it is worth it. It may seem annoying to propagate a click explicitly through 5 parent components just to sum clicks into a count widget, but as soon as a short circuit is made, you&#x27;ve created a graph, and you lose the ability to isolate GUI sub-trees for testing&#x2F;debugging.
评论 #26134636 未加载
hyberbole_1234over 4 years ago
The best approach I’ve seen is separating State and Views and having some form of property diffing.<p><pre><code> struct LightState { var isLightOn: Bool } class LightViewController { let lightView = UIView() } class StateDirector&lt; LightState, LightViewController&gt; { let lightState: LightState init(state: LightState) { self.lightState = state } func bind( view: LightViewController ) { &#x2F;&#x2F; Every time is turned on changed call this LightState.add( listener: self, for keyPath: \.isTurnedOn, handle: .method(Self.handleLightChange) } func handleLightChange(isOn: Bool) { view.lightView.backgroundColor = isOn ? .green : .red } } </code></pre> This allows clear separation of State, View and Changes.<p>You can then just model your state in your reducer and “simulate your views” inside Unit tests
dale_glassover 4 years ago
What kind of GUI app has a performance problem with the message bus?<p>We&#x27;re in the age of 4K, 60 FPS rendering. If any GUI application has a message bus that&#x27;s strained enough to impact performance, then either the application isn&#x27;t made for humans (because if all that stuff is doing anything it&#x27;d result in a screen updating far faster than it could be read), or there&#x27;s some horrible bug somewhere that produces a flood.
评论 #26134131 未加载
phtrivierover 4 years ago
This seems to miss the &#x27;ui=f(state, effects)&#x27; model that&#x27;s sort of what&#x27;s behind react+redux or elm or similar ideas.<p>Or is that really the same as immediate mode ?
panicover 4 years ago
I&#x27;ve found the best way to handle this problem is a variation on &quot;lift the state up&quot;, but instead of binding synchronous listeners to state changes in the model, have these state changes mark any involved views as &quot;dirty&quot;. Then, after all events have been processed for the current run loop, go through all the dirty views and call a single update function on each.<p>For the example given in the article, the update function could look something like<p><pre><code> def View.update(): if model.lightTurnedOn: self.backgroundColor = red else: self.backgroundColor = ibmGray </code></pre> This way, all view property changes happen in one place, where you can read the code and understand how the view will appear in each possible state. Circular listener loops are impossible, and view properties for animations can even be computed by calling update twice (once before and once after the state change).
评论 #26131812 未加载
评论 #26136499 未加载
strictfpover 4 years ago
You can also use the original web page model; the state is on the server, every button click generates an action to change state, and the updated ui is regenerated fron scratch based on the new state.
spionover 4 years ago
&gt; I still don’t know what the proper solution to this problem would be. Keep your state manipulations as simple as possible and try not to share any data between different models. Every time I went forward with some fancy listener-binding mechanisms, I’ve ended up causing subtle circular listener recalculations that were extremely hard to debug.<p>The answer for me has been pervasive use of MobX computeds everywhere. See <a href="https:&#x2F;&#x2F;mobx.js.org&#x2F;getting-started" rel="nofollow">https:&#x2F;&#x2F;mobx.js.org&#x2F;getting-started</a>
RoyalSlothover 4 years ago
Author here. This is not related to this discussion, but does anybody know what causes these lines to appear in my server logs?<p><pre><code> &lt;REDACTED&gt; - - [14&#x2F;Feb&#x2F;2021:22:26:45 +0100] &quot;GET &#x2F;posts&#x2F;the-complexity-that-lives-in-the-gui&#x2F; HTTP&#x2F;1.1&quot; 200 16798 &quot;-&quot; &quot;HackerNews&#x2F;1391 CFNetwork&#x2F;1220.1 Darwin&#x2F;20.3.0&quot; &lt;REDACTED&gt; - - [14&#x2F;Feb&#x2F;2021:22:26:45 +0100] &quot;GET &#x2F;posts&#x2F;the-complexity-that-lives-in-the-gui&#x2F; HTTP&#x2F;1.1&quot; 200 16798 &quot;-&quot; &quot;HackerNews&#x2F;1391 CFNetwork&#x2F;1220.1 Darwin&#x2F;20.3.0&quot; &lt;REDACTED&gt; - - [14&#x2F;Feb&#x2F;2021:22:26:45 +0100] &quot;GET &#x2F;posts&#x2F;the-complexity-that-lives-in-the-gui&#x2F; HTTP&#x2F;1.1&quot; 200 16798 &quot;-&quot; &quot;HackerNews&#x2F;1391 CFNetwork&#x2F;1220.1 Darwin&#x2F;20.3.0&quot; </code></pre> The requests usually come from a certain ip multiple times until fail2ban bans it. It&#x27;s not just one offender, there are multiple behaving like that.
评论 #26136566 未加载
scarredwaitsover 4 years ago
Good explanation, but the article reads as if React never happened. Maybe it was written by someone who&#x27;s only worked on desktop apps?
评论 #26137093 未加载
rwmjover 4 years ago
I remember in my first real job I wrote a GUI for an RTOS (all the way up starting with the hardware, device driver, ...). Not knowing anything about how GUIs worked, or about events, I had a main loop which redrew the GUI on every action. This article tells me I wasn&#x27;t completely wrong, these are called &quot;Immediate Mode&quot; GUIs!
mwcampbellover 4 years ago
&gt; Immediate Mode GUIs somehow never reached the critical mass and you are probably not going to find it outside of the games industry.<p>And that&#x27;s a good thing, because so far, AFAIK, no one has implemented accessibility (e.g. for screen readers) in an immediate-mode GUI. I hope to work on that problem sometime soon.
onion-soupover 4 years ago
Don&#x27;t libraries like react solve this?
评论 #26135526 未加载
nikisweetingover 4 years ago
Excellent writing, this is a great article to show a junior frontend engineer who would otherwise spend their next years having to crystalize these ideas on their own. I wish I had read this 8 years ago.
1vuio0pswjnm7over 4 years ago
I rarely ever use a GUI. Certainly not for any recreatonal web use. Unless I&#x27;m using a GUI, I do not load the graphics layer. I stay in textmode. No X11, Wayland or whatever is compiled in. Ideally I have a designated computer on the local network that has a graphics layer, a full corporate GUI OS. When I need graphics to view stuff I can send it over the local network to the GUI computer. Otherwise I keep recreational use on text-only computers, away from the whiz-bang corporateOS-controlled computer.
评论 #26137334 未加载
cpillover 4 years ago
&gt; I’d love to hear what the functional programming camp has to say about this problem, but I guess they are too busy with inventing yet another $20 term for a 5 cent concept<p>hA! Hit the nail on the head :P
walkingpigeonsover 4 years ago
At the end of the article it said something about immediate mode. I do think React or Vue are kind of working like this now? Both requires you define your state of the each component and define how it should look like based on the state values. When you update the state it will then update the view automatically as well based on what you&#x27;ve defined (JSX&#x2F;template). It is not 30&#x2F;60FPS though, it is re-rendered when it knows there is a state change (i.e. setState is triggered)
codefloover 4 years ago
I’ve recently become interested in immediate mode UIs, and find that there are surprising similarities to React. In both cases, components are just functions that must explicitly render their child components and pass down any shared state. It’s conceptually a very clean way to handle UI state.<p>However, React introduces a lot of complexity to avoid unnecessary DOM updates, which makes me wonder about the viability of an immediate mode GUI in the browser using canvas.
评论 #26132547 未加载
评论 #26132555 未加载
评论 #26132545 未加载
tomaszsover 4 years ago
After 20 years of working with frontends mostly I consider that there are three causes of problems with GUI:<p>- it is badly designed. If state is too hard to manage it means often that the design is bad<p>- state is not the most important part of the UI. Interaction and being elastic to changes are the most important things<p>- frontend is often overengineered in a bad way. When you use bad solutions like React or Redux there is no change there won&#x27;t be any problems.
axilmarover 4 years ago
I totally disagree with the author. For me, the problem of state management in the GUI is totally solved: the GUI shouldn&#x27;t manage state, plain and simple.<p>If you have a problem synchronizing your views with a light, that&#x27;s because the light should exist outside of your views.<p>MVC was invented in the 70s. Why do we have to act that this is not a solved problem?
continuationalover 4 years ago
I ran into a buch of similar problems in the past personally, so much that I ended up writing my own library.<p>The home page is a bit ugly, but it contains a range of examples that are commonly awkward to implement in other UI libraries:<p><a href="http:&#x2F;&#x2F;www.react4s.org&#x2F;" rel="nofollow">http:&#x2F;&#x2F;www.react4s.org&#x2F;</a>
mattgreenrocksover 4 years ago
I’m not fond of the reasoning employed in the message bus section that decries the fact that misuse results in a big mess.<p>No programming paradigm can stand up to rushed&#x2F;flawed mental models.<p>The domain can become quite complex; it is wishful thinking to believe that a single approach could drain it of all complexity.
protoman3000over 4 years ago
A related question, how do GUIs actually resolve quickly on which element under the cursor a click lands?<p>How is the click propagated recursively through every component and is the position compared repeatedly at every step?
评论 #26136625 未加载
评论 #26134525 未加载
FpUserover 4 years ago
&gt;&quot;the GUI always ends up being a ridiculous mess&quot;<p>Well no. There are applications with nice well thought out GUIs.<p>&gt;&quot;Congratulations, a large amount of your effort will go towards resolving weird message bus problems as opposed to writing the business logic of your app&quot;<p>Sorry but I do not resolve &quot;weird message problems&quot;. I use my own publish-subscribe mostly asynchronous message bus for my GUI apps (actually I use it also for non GUI parts as well). Components (visible or not and including running threads) can subscribe to events. It does not exhibit any performance &#x2F; memory problems and in combination with the global app state object makes programming interactions a piece of cake.
评论 #26134728 未加载
vikingcaffieneover 4 years ago
I&#x27;ve written front end for nearly all of my 13 years in this field. I&#x27;ve written some absolute dumpster fires in my time and have also written some very large and complex UI&#x27;s successfully. I would like to think I have some insight to add here. I agree with a lot of the points brought up in this article. I&#x27;d like to add a few more points about why I think FE can be such a pain to get right:<p>1. Mixed concerns and a lack of application layering. In React code bases and others like them, its not uncommon for me to find business logic embedded directly inside the components themselves. This makes the component inherently coupled to the specific implementation its being used and can only be re-usable in other contexts by passing in modifier flags to the props etc. In my opinion, components should be mostly of the stateless flavor and delegate anything not directly related to their immediate UI concerns elsewhere. This increases the likelihood of re-usability of your components and makes testing business and component logic much much more straight forward.<p>2. This might just be my personal experience, but I&#x27;ve noticed a bit of a dismissive attitude around design patterns and traditional computer science principles among my front end brethren. YAGNI and all that. While I think its fair that the UI != to the back end, I think frequently the baby gets thrown out with the bath water. For instance, I frequently leverage dependency injection in my front end work as a way to make my code more flexible and testable. It&#x27;s hard to sell the benefits of something like DI until your application grows in complexity to the point that you are dealing with things like nested mocks in your tests and&#x2F;or need to make a non trivial change to some piece of functionality. I&#x27;ve been seeing the winds start to shift a bit on this which is encouraging.<p>3. Most of the time there is little to no overall _conceptual integrity_ to a given front end code base. Its uncommon for me to come into an existing code base and have anyone be able to tell me what the architecture is comprised of. Things like what logic lives where and why. I&#x27;m not saying people _don&#x27;t_ do this, but in the more gnarly code bases I&#x27;ve encountered, this &quot;accidental architecture&quot; is more common.<p>4. Front end is still see as &quot;easy&quot; and the place you stick the less experienced engineers first. I sincerely hope this doesn&#x27;t come off like I am gatekeeping or anything. I work with some absolutely brilliant people who are only a year or two into their career and much smarter than me. IMO its less about skill and more about having been burned enough times to know where unexpected complexity lie.<p>I love front end. Its challenging and interesting and maddening. My hope is that it will continue to mature and grow to the point that it gets the same respect as other disciplines within this field. These days I work full stack so its not all I do, but it will always be my favorite. :)
评论 #26141291 未加载
c-smileover 4 years ago
TL;DR: there is no one silver bullet for the UI in general.<p>As a rule practical and manageable UIs use all these approaches at the same time.<p>Components, class based and&#x2F;or functional (fe: UserSection, InventoryTable ), are in principle loosely coupled. They may not know about each other and use messages to communicate.<p>The Flight by Twitter ( <a href="https:&#x2F;&#x2F;flightjs.github.io&#x2F;" rel="nofollow">https:&#x2F;&#x2F;flightjs.github.io&#x2F;</a> ) was&#x2F;is probably the first <i>practical</i> thing that pioneered that approach.<p>The Flight is not even a framework but rather a design principle.<p>In fact it is an anti-framework - it postulates that in practice each component may have its own optimal internal architecture. One component is better to use React-ivity, another - Angular-ish data binding, etc. On some, immediate mode drawing is the most natural.<p>Smaller the task (component) - greater the chance to find silver bullet for it.
valandover 4 years ago
Another option is injecting an optional dependency without connecting the box.<p>I see OP doesn&#x27;t mention this option, but is slightly related to both option 1 (connect the box) and 3 (message bus &#x2F; event emitter). This option is similar to how OS provides an API to user space application program. For example Windows provides an API to an application to flash its window without exposing all of its state like mentioned in option 1. <a href="https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winuser&#x2F;nf-winuser-flashwindow" rel="nofollow">https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winuser&#x2F;n...</a><p>Here&#x27;s the detail:<p>A self-powered object, let&#x27;s call it workingIndicatorObject, can be introduced to work on the working indicator. It provides 1.) `getState() -&gt; WORKING&#x2F;NOT-WORKING` a function to get its state, and 2.) `register() -&gt; None`, a function to register user activities. These functions are dependencies for UserSection component and InventoryTable component respectively. In term of lifetime and hierarchy, it precedes and outlives both components.<p>The workingIndicatorObject MUST have its own lifecycle to regulate its internal state. Its core lifecycle MUST NOT be managed under the same event loop as the GUI components, assuming the program is written on top of a framework that has it (React, Vue, etc). This is to assure that it doesn&#x27;t directly affect the components managed by the framework (loose coupling). Although, a binding MAY be made between its state and the framework-managed event loop, for example, in React environment, wrapping it as a React hook. An EventEmitter can also be provided for a component to listen to its internal event loop.<p>Injecting it as a dependency can use features like React Context or Vue&#x27;s Provide&#x2F;Inject pattern. Its consumer must treat it as an optional dependency for it to be safe. For example, the UserSection component can omit drawing the &quot;working&quot; indicator if it doesn&#x27;t receive the `getState` function as a dependency.<p>Internally, the workingIndicatorObject can use a set. The set is used to store a unique value (a Symbol in Javascript). `register` function creates a Symbol, stores it in the set, and deletes it after $TIMEOUT, while firing event both at addition and deletion. `getState` function is a function that returns `set.size()`. When bound to the component, an addition to the set fires an &quot;update&quot; command to the component, which redraw the component along its internal state. This is just one example of implementation and there are other simpler ways to have the same behaving workingIndicatorObject.<p>This approach allows UserSection and InventoryTable to only know `getState()` and `register()` function and nothing else, and having both of them optional. Using static type system such as TypeScript can help a lot in this since we can pin down the signatures of both function to `null | () =&gt; WORKING | NOT_WORKING` and `null | () =&gt; void`, where we can enforce both dependent components to check if it exists and to call it with the correct types, otherwise the compiler yells.
评论 #26137873 未加载
ggmover 4 years ago
Neither is between two choices: he&#x27;s presenting Three.<p>Small point, but it grated.
评论 #26137943 未加载
pixel_tracingover 4 years ago
Article presents a bunch of problems on UI but no solutions... perplexing.
评论 #26271584 未加载
chris_wotover 4 years ago
Um, isn&#x27;t this what the Mediator pattern was designed to solve?<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Mediator_pattern" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Mediator_pattern</a>