Are reusable view components really a good idea in web apps?

(Shavais) #1

I’ve attempted a number of times to create reusable view components in web apps, and I’ve kind of come to the conclusion that it just doesn’t work out very well. Maybe someone can talk about how they avoid/get around the kinds of issues I run into.

What happens to me is that, for example, I’ll create a handy reusable component for use in the view (view A) I’m working on, right? So then I go to reuse that in another view (view B). Well, but in that view I really need it to do some more and different things, so I add support for those more and different things, maybe in a derived class. In a third view (view C), I want to use that component, but I really only need some things that are similar to what view A needed, and some different things, and some things that view B needed, but slightly different, so again, I add more support for more different behaviours in different situations. The “api” for the components starts to get… “interesting,” and it’s functions and layers and so on begin to get even more so. Then time goes by and I end up changing view A, and changing the component because the requirements for it have changed, but I don’t really want to let go of the old functionality because I might need it again someday, so… eventually in time I end up with this “component” that has a ridiculous amount of code and mark up associate with it. Some of which had reasons for being there at one point, but no longer really does. Because it has support in it for all these different things that these various versions of different views needed, at one time or another. I’ve attempted to refactor the hierarchy of classes, but… that process has involved a lot of head scratching and uncertainty and a lot of, well, wasted time, really, because while in theory it should work great, in reality my experience has been that it’s pretty tough to line up the layers in such a way that the code that is actually applied has what is needed without having too much of what isn’t needed in the context of any given view.

Inevitably, at some point, into this big ball of wax comes a bug. Somewhere in that milieu of component code. Something somewhere somehow got tweaked or… gremlins are seemingly at work… stuff that shouldn’t be happening is, and stuff that should be happening isn’t. And the danged thing is incredibly hard to debug because it has 11 layers and 25 times more code associated with it than is really needed for the particular view I’m working on. (And it’s many times more complicated than it needs to be for that view, too.) You think I’m exaggerating, don’t you? Not much!

So that general experience with attempting to componentize web app code has kind of led me to the conclusion that it’s just better not to. It’s better to think of html elements themselves as being the “components” I’m working with, and just create the code behind a view as if that view is the only thing that’s ever going to use that code. And if I need something like that in some other view, just copy/paste/modify. That way the code that is associated with any given view is what it needs to be, all of what it needs to be, an nothing but what it needs to be. Which in my experience is a actually quite a bit less than it is if I’m trying to make it more generally applicable.

I’m not saying I don’t use abstractions in my view code. I’m just saying that I only use an abstraction if and to the extent that it is beneficial within the context of the particular view the code is associated with.

I’m also not saying that I don’t nest views, or reuse views on different pages. For example if I have a dialog, I consider that to be a view, as opposed to being a component. There is no difference beyond maybe a bit of CSS theming between the dialog on page A and the dialog on page B. If there is any behavior difference that is needed - I shamelessly copy/paste/modify, at this point. Because I know that that danged thing will eventually become a monster if I don’t. It doesn’t matter how much over all js code the application has. Even if there is a fair amount of duplicated js code, I don’t really care. No web app page, which typically has a megabyte or two of media to download and render, cares a whit about a few hundred more bytes of minified js code. But how much js code I have to dive through in order to figure out how the code involved in supporting a given feature works, and how complicated that code is - that matters a lot. So it seems to me that componentization efforts kind of go in the wrong direction: They try to limit what doesn’t matter while failing to constrain what does. To me, web app code is much, much better done wide and shallow than narrow and deep.

While I’m certainly willing to be convinced that I’m wrong, at this moment, it seems like libraries like JQuery, Knockout, AngularJS and Underscore, etc., that aim themselves solely at reducing the amount of code I have to write when writing the code for a given view, are very helpful. But big frameworks like Angular2 and maybe ReactJS (I haven’t figured that out yet) that try to help me organize my code into components or into controller actions or something like that really just get in my way more than they help me.

So with that said, here are my questions:

1 - Am I wrong about view components? And if so then how can I avoid this snow balling effect of the volume and complexity of code that is involved in supporting a given feature as the components get used in different contexts that each require them to behave slightly differently?

2 - Is ReactJS still helpful if you’re not componentizing?