By the time all was said and done the PR for this thing had 27 files in it.
For a modal.
This seems ludicrous to me. The frustration, somewhat humorous, expresses by TFA is completely understandable, though. While I came to appreciate TS, I'm still skeptical about this JS framework stuff. They seem overly complicated to me. (While I have only read casually about React, it seems similar in this regard.)
I experienced the same thing when learning angular, flux and redux. It all screamed "overengineering" to me. But then I realized why it was that way, and why it had to be : you now have teams of like 50 js developers working on the same codebase. They have to have very strict and complex architecture, because their frontend codebase is just as big, if not more, than their backend codebase.
Those tools still lack alternatives for small to middle sized teams and products, IMO. React by itself is super cool to be quickly productive in that scope, but state management systems are not. For that reason, I made my own flux library, meant to keep things conceptually simple. The flux pattern by itself (data always propagating in a single direction) is not complicated, its implementations are. I would recommend that small teams working on small products take time to get the flux idea, then make their own implementation, it's worth it.
EDIT : to be more specific, here is a simple thing to do to make your own implementation:
1. build something (let's call it a store) with a `subscribe(func)` method allowing to be notified when data changed
2. add a public api to that store (`like store.addArticle(article_data)`)
3. in the `componentDidMount()` method of your root component, subscribe to store with a function that calls `setState()` on your component, then pass data as props to child components
4. when triggering an action, like clicking a button, call a method from the public api of your store
5. you now have a state manager ensuring data always flows in the same direction, and you can make your store implementation as simple or as complex as you want
Personally, I'd find it very hard to be motivated to work on a project like that. It sucks all the fun out of coding when things that should be simple aren't simple, it's draining for the whole team and it creates a lot of friction in adding new features.
So I guess that, to the question "How could the 27 file commit example comment not be a clear case of overengineering though?", the answer would be : "when there are 100 modals in your codebase and various devs work on various parts of those modals". Not saying that's a place I want to work either, obviously :)
Hmm, if each component is properly isolated though and you're not all working on the same area I still don't see why a simple modal could take so many code changes. Can you give an example?
Oh, no, absolutely no real life example. Note that something that huge is not something I encountered (gladly, 20 devs was the biggest team I was in). I'm trying to answer the question "in which circumstances people doing this may be right", which is my usual approach when I don't understand a behavior (provided it's not morally questionable behavior, obviously, but it's not the case here).
And I totally get what you mean with over-abstractions, many rails teams have the same problem, nowadays. I'm not advocating that, just trying to understand why it makes sense for them, and which problems they have that I don't.
So, if I had to give an hypothetical example, I would go with a chart modal on an e-commerce, like amazon. You have the list of items with their quantity, in it, quite basic, and a few devs are responsible of that part - those who manage checkout base code.
But you want your modals to look the same all over the domain, so you make an abstraction for it, made by a team who work on abstraction for the whole domain, expecting to be used in a certain way, but trying to avoid preventing devs to implement what they need.
Now, the thing with checkout is that there are a lot of legalities which vary upon countries. You have developers in those countries, so why not make them work on the specific VAT, legal mentions, or whatever that they're already used to, instead of having a team who should get all the different legal frameworks of all countries in the world? Or you can split responsibilities about those to various teams, each handling several countries, but none having to know the law of all countries. To do that, you'll probably add an API in the basic chart component and allow different teams to plug on it.
And then, there's the team handling promotional content. Most of the time, they can do with existing abstractions, but sometimes it requires new specific content, so you decide to have a team on that, since you're a giant and you deal with several promotions a day.
All those people keep editing the same feature, but none know the whole codebase for it, so they have to be pretty sure they won't break someone else part by making a change.
And now, people in all those teams keep coming in and leaving company, and you have to make sure no knowledge is lost when they leave, and that new people can make changes fast. If you split all of this in 30 files with a clear separation of public api and internals, it probably helps.
This is my best - although probably naive - guess of where an over-specified architecture may be useful for a modal.
Well I've been on teams on two where the software architect would insist on abstractions and dependency injection absolutely everywhere so it's probably not team size dependent. :P
I find it funny how some people promote the "you aren't gonna need it" principle but yet abstract absolutely everything in the incredibly slim chance they might want to swap something out in the future. I feel overabstraction is a very, very bad and common thing yet it is rarely mentioned compared to e.g. avoid goto, avoid comments. Overabstraction bloats your code and makes it really hard to understand.
> And now, people in all those teams keep coming in and leaving company, and you have to make sure no knowledge is lost when they leave, and that new people can make changes fast. If you split all of this in 30 files with a clear separation of public api and internals, it probably helps.
I could imagine how if you were dealing with Amazon's scale abstraction would be more common and more useful than in other places.
We have a big problem with small companies wanting to imitate giants and go with elasticsearch/kubernetes/rabbitmq/whatever from the start when they clearly don't need those (and the same goes for code architecture).
I just won't say that the simple architectures I write are how everybody should write code and that giants' devs are bad developers for solving problems I don't have :)
Use something tiny like preact and you'll probably enjoy the simplicity of it with hyperscript so it's all in js.
In desktop world, we were using this sort of software architecture decades ago. It's only a combination of modular design, separating state from presentation, and an observer, and these are all well-established principles that have stood the test of time. Countless developers have written something like this at the start of countless new projects, and they probably did it in five minutes without a second thought.
The difference In modern JS world is that some people talk as if you need 197 dependencies, a whole build process and a team of 5 just to maintain it. You really don't, and the frameworks and build systems that push in that direction make my head hurt.
A good set of components for your library of choice should make a modal dialog that works and has flexibility e.g. https://bootstrap-vue.js.org/docs/components/modal/
That said, a modal dialog can be very hard to implement, depending upon needs (centering in viewport, mobile devices, stacking multiple modals, form modals with popup controls above them, preventing tab key allowing focus to go to form behind, plus many other hard issues!)
> By the time all was said and done the PR for this thing had 27 files in it.
Can you not just use a library for this and do it in a few lines...? I found Angular 2 verbose but I don't see how the above is common. I just did something similar in Vue today and it was about 4 lines to load the library and call it. You shouldn't be implementing modals yourself if you can avoid it.
Just starting fresh, what is a modal? It's a widget (we could use a div) which when activated is moved to the front of the z axis and steals focus. CSS can do that. Now all you need it do is keep attributes regarding the text of the modal and state representing whether it's activated (we can juse a regular JS object for both), and you've got a working modal.
Some of the frameworks are needlessly complex, which is frustrating, because it's hiding something very basic.
It's surely not one line of code!
Didn't say not to use a framework. Use it and some CSS and that's a basic task, not to mention there are other libraries which do it for you already.
A good modal library is going to weigh in at a few thousand lines of code across JS, CSS and HTML for a reason. If you have a simpler use case then you don't need all that extra edge case handling, but that doesn't mean it's not pointless code.
No. Sorry, but that's just nonsense.
A modal is probably going to be rendered as an HTML div element, styled so it appears with a fixed centre-viewport position.
You probably also want a second div as an overlay to de-emphasize the rest of the page while the modal dialog div is visible.
You might want a standard X button to close the dialog, which hides the above when it's clicked.
You can write all of that in less than a screenful of code, and you can do it using nothing but basic web standards that are supported as far back as IE8 and iOS5 -- in other words, well before the browser generations that even Microsoft and Apple themselves still support today.
Of course, but you can trivially generate the required divs in JS, and you can easily track the number of current modals displayed and set the z-index to ensure proper stacking if necessary.
Other than that, what you put in the modal in terms of HTML content or rendering a template presumably works the same way as any other part of your UI. There's nothing magic about the fact that this particular div happens to be styled as a modal dialog.
For non basic modals you also need events to know if user accepted or dismissed the modal, you want the Escape key to also work, you want the option to allow or not closing the modal when clicking outside of it
OK, so you need two callback functions, a couple of buttons to proceed or cancel, and possibly a couple of event handlers for keyboard and mouse/touch events.
Again, you surely have something to render buttons and handle their events for your UI more generally anyway. Other than that, the only thing special about the modal is that maybe you're connecting a couple of other events to the same handler logic as the explicit cancel button.
Really, none of this is difficult, nor does it need anything like thousands of lines of code just to handle modal dialogs. You could code everything we've been talking about here from scratch in a few minutes, and you could integrate it straightforwardly with any UI library I can think of if you're already using something else to render templates or handle input events. If you already have something available that will save you those few minutes, great, go right ahead and use it, but let's not pretend this is some tricky problem that requires a lot of thought and a lot of code written by experts. It's an elementary exercise in UI design, which I'd expect any junior dev to handle easily.
Well, you keep saying that, yet putting focus on a designated element when opening the dialog is literally one line of code, and setting tab order isn't particularly difficult either (and is probably something you'd have to do in much the same way whether you wrote the code yourself or used someone else's library to create your modal).
In any case, we seem to have drifted well off the original topic now. The comment by revscat was about a requirement to add a very simple modal without any of these hypothetical complications you keep introducing, and how the resulting PR involved 27 files. That's crazy.
Point being, you can either write up a simple modal if you are targeting semi-modern browsers and don't need much, or you can use one of a dozen libraries that do this, but 27 files sounds pathological.
UI is hard dude. UI on the web is especially hard because the technology has been growing progressively for over two decades.
I've seen devs complain about how coupled some small jQuery one-liner is and then replace it with some muli-hundred line monstrosity of a module that's buggy, incredibly hard to understand and impossible to actually reuse...then when you call them out on it, they just say "fuck you, we're writing ES6 now".
The code they replaced was simple, just worked and didn't have side-effects. And they're still using jQuery elsewhere in their project anyway...
Probably because it's one line in Vanilla.js:
* With the vanilla solution, the user can check a box that says 'Prevent this page from creating additional dialogs' (which can break the site). With a non-vanilla solution, the user cannot check that box
* The vanilla solution can't be themed in tune with the rest of the site or webapp
* The only options you have are 'OK' and 'Cancel' - you may wish to have other buttons/labels for your modal. Never mind if you want three buttons, or a list or the like
It's been a solved (and re-solved) problem for decades.
- clients that range from tiny phone screens to full desktop screens
- incompatibility when it comes to what features clients support, and even how they support it
- a foundation not meant for UI's that is pretty much required to be abstracted away leakily (HTML, browsers)
- serious limitations in payload file size for the entire UI codebase
- much of the UI depending on asynchronous operations. The only 'UI' that I can think of that is similar is when I SSH into my server. All other user interfaces are mostly 'local'.
- backend systems that are not optimized for these kinds of things
I am a relatively 'young' programmer, so maybe I'm utterly wrong about thinking that, considering the above, we're in kind of uncharted territory. By all means correct me!
Also, personally I'm becoming more convinced that until all this stabilized, many of use (or at least I personally) might benefit from just not aiming that high when it comes to UI. If I'm honest with myself, an 'old-fashioned' backend that produces HTML with perhaps a few dynamically loaded components (as just HTML fragments, even) is perfectly fine and I truly doubt it would have a negative impact.
(hey carsongross, this is where you bring up intercooler.js!)
It does your checklist for 2 decades.
For example, I can't really think of a desktop app where most of the crucial app/UI logic is reliant on async communication with a server. Most data is stored locally and permanently.
I'd actually really like to hear because I have been eying native development lately!
clients that range from tiny phone screens to full desktop screens -- Desktop UI could support this if developers wanted to its just resizing a window. You just don't see it because devs assume the existence of a mouse which allows easing panning in a scroll bar window.
- incompatibility when it comes to what features clients support, and even how they support it - Desktop UI has or had solutions: Swing, JavaFX, QT, Adobe's Flex.
- serious limitations in payload file size for the entire UI codebase: There have been desktop XML UI for so long. The oldest I can recall would be Adobe's that went along with ActionScript to build Flex apps.
- much of the UI depending on asynchronous operations. The only 'UI' that I can think of that is similar is when I SSH into my server. All other user interfaces are mostly 'local'. -- The desktop analogy here is some long running process. Whether that is a slow disk, long computation, or some network access, desktop UI solved this a long long time ago with a rendering thread and worker threads.
- backend systems that are not optimized for these kinds of things - not sure what you mean here.
Rather, disregarding how we got here, the situation we're in now provides challenges that sort of justify the complexity and confusion we're in now. Maybe this comment better expresses what I'm saying: https://news.ycombinator.com/item?id=14218425
On the bright side, I will never forget a manager of that era who was very good with buzzwords but not so good with the technologies behind them. We had some existing software built using COM, Microsoft had just announced the first version of .NET (though no-one quite knew what .NET actually meant yet) and the Internet was taking off as a mainstream technology for the general public. The manager in question would wander around the department asking us if we were using this new .COM framework to build our new software...
This is the problem, right? It's not that the other problems are unsolved, it's that we're buiding on a lousy foundation. But even that is just an annoyance, something we know how to overcome, it's not a fundamental impossibility.