We have recently implemented Angular4 in our project, and have started to pick it up. Recently picked up a story that was adding a simple confirmation modal to a page: "Alert" text in the top, body with some warning text, and a yes/no button.
This was my first experience with modern JavaScript frameworks and TypeScript. I wanted to do it right, so worked closely with team members who were more versed in this stuff, and followed the various recommended best practices.
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've been doing heavy javascript interfacing since the end of the 2000' (it was still a rare skill back then, and made me good freelance money), and I totally understand how you feel.
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
How could the 27 file commit example comment not be a clear case of overengineering though? I frequently add similar functionality to Vue and Angular 1 projects in a way close to how you describe and it's simple. Even if the change involved adding a modal library (you should not be wasting time implementing that yourself) to your project first, it shouldn't be more than about 10 lines.
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.
Yep, I feel the same way, but then again I usually work with small startups. I had an experience with a bigger team, recently (about 20 devs) and went all the way "what you do is too complicated". I was quickly humbled when I realized that my "simple" designs were quickly growing out of control and breaking a lot after a few months so many devs were adding code in it, most of them knowing only a very small part of the app. I guess I could say no product should need 20 devs, but it feels like denial.
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 :)
> 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?
I've worked on Java codebases before where there's hundreds of abstract interfaces, factories, design patterns galore etc. where you can't work out where the actual work is done because every file is just delegating to another file which I hate with a passion. JavaScript gets a lot of stick around here but I find it fun and productive to work with to be honest, as long as the same silly level of abstraction is avoided.
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.
> 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).
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.
Yeah, totally, small and medium teams don't need all of those. That was my initial point about implementing our own flux-styled store layer for react, instead of using flux (the actual lib) or redux, which are made for such giants.
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 :)
The example you edited in makes your point very well. Essentially, you're describing a simple MVC design, with a couple of React-specific details for rendering your view.
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.
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!)
> Recently picked up a story that was adding a simple confirmation modal to a page: "Alert" text in the top, body with some warning text, and a yes/no button.
> 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.
Maybe a sign that things are too coupled through. Can make the same argument on any project, I.e. wanted to add small feature, ended up changing 27 files.
27 files sounds absurd. Maybe you're doing more than adding a store with some action?
I used mobx with react and a new store is 1 file, including its actions. Connecting it to components takes a few lines per component.
Redux may use more files but they are short.
Yeah something's not right. A modal is a line of code, not 27 files. The most extensible modal could be a single file component.
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.
Does that work in several versions of different rendering engines that date back a decade, at resolutions from 800x600 to an iMac 5K screen? How about on tablet and mobile devices? What happens when the user's scroll position is half way down the page? Does it listen for events to update or close itself?
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.
A good modal library is going to weigh in at a few thousand lines of code across JS, CSS and HTML for a reason.
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.
You need more functionality for a non basic modal, first problem is if you have 20 modals you want not to copy paste over and over again. 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,
The project I work on uses bootstrap, this means in the main html file you have copy pasted same html boiler-plate with only the content change, somewhere there is a button that has a special attribute that magically opens this modal(bootstrap js does that in the background), this does not scale and we searched for a good library so we can put each modal in it's own file and we also needed full control to create the modal if and when we needed it and not have it loaded in the main html but hidden. The solution would be to have modals implemented as standard and not having to hunt for a library because the lib we used is for angular+bootstrap but it will not work for react+bootstrap or for no framework projects.
first problem is if you have 20 modals you want not to copy paste over and over again.
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.
Ypu also need to have the modal setup the focus correct in the first input(or the one that makes sense), usually GUI libraries have a property for tab index that specify how focus changes when you press Tab, bootstrap seems to not properly setup the focus and I had to write code to fix that.
It is not impossible to write such code but I am sure the code you will write in 10 minutes will not be good enough, my point is this modal feature should be native and not have people re-invent it,
Also what if you want to allow resize or move, then you get again more and more code that is reinvented each time.
IMHO is the same issue as with the dropdown/select , when you need a dropdown that has icons or something that the native one is not good enough it is easy to write one yourself, soem divs, some events but this 10 minutes dropdown will have missing feature or issues, like corner cases when the popup thing goes outside the screen or conflicts with something else,or the thing that opens contains 6 and half entries and if you want to look good you need to put more work into it, then if you want support for arrow keys more work, or if you want the feature where the user presses the first letters and selection jumps down to the correct item even more code, my point is basic implementations are fast, good enough implementation like you have in Qt,Flex, WPF is a lot more work and we do not have a standard way of doing it, and the developer needs to research what library works with the current stack he uses
It is not impossible to write such code but I am sure the code you will write in 10 minutes will not be good enough
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.
What's the likelihood that he's supporting engines going back a decade? Modern rendering engines and CSS handle that pretty well. IE 8 is 8 years old. Bootstrap 3 supports IE 8 and has modals.
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.
Agree. More importantly, I see this nasty trend where people bag on jQuery code just because it's jQuery code.
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...
The vanilla solution doesn't offer as many features:
* 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
Of course there isn't perfect feature parity, but considering how much more complex a custom solution is, you should definitely think twice about what that complexity actually gets you
UIs on the web suffer much more than UIs elsewhere from the disease of people designing their own UI elements in order to achieve a novel, unique style. Perhaps, some day, this will be considered pointless and unprofessional like on the desktop...
But web design philosophy has been creeping on to the desktop for quite a while now. Apps like Skype and Slack are ludicrously overstyled these days. Flash and chrome have always played teeter-totter with utility and functionality, in every field.
But has it been solved if you take into account the various constraints/issues:
- 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!
All that said, I do get the feeling 'we' in the javascript world reinvent the wheel more than necessary. But perhaps that's because none of the historical solutions are 'complete' enough to get enough mindshare in the way that, say, Ruby On Rails was, or jQuery.
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!)
I've done stuff with Delphi back in the day, but I'm not too experienced. Would you mind explaining point by point how desktop UI 'does' this?
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!
Young developer here too, but I started about a decade ago with robotics/desktop development. Thus, I can sympathize with the comment earlier that desktop UI has done all this:
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.
I think we're talking cross purposes. I'm not saying that there we never came up with better things; far from it!
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
Oh, you're an evil person for bringing those up. Now I'm going to have COM and CORBA nightmares for days! It still blows my mind that we managed to write half a screenful of code, essentially just to call a function.
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...
a foundation not meant for UI's that is pretty much required to be abstracted away leakily (HTML, browsers)
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.
With the way callbacks work in Javascript and jQuery, you lose some flexibility in organizing your code. It is true the types in Javascript make it difficult to build large projects. These drawbacks can be overcome, of course, but this is all orthogonal to the main point......
If Javascript and jQuery truly are bad (though I would claim they are not, they are mediocre but workable), it's because their creators didn't know history, not because the problem is unsolvable.
Eich wasn't ignorant of history, he just had marching orders to deliver something that resembled Java for marketing reasons, and only a week to finish or be displaced by something worse. The trouble is nobody ever got to fix it until ECMA.
This was my first experience with modern JavaScript frameworks and TypeScript. I wanted to do it right, so worked closely with team members who were more versed in this stuff, and followed the various recommended best practices.
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.)