top | item 29551123

Widget Driven Development

40 points| alexey2020 | 4 years ago |alexei.me

24 comments

order

hitekker|4 years ago

> [Widget Driven Development] makes the data flows transparent, architecture flexible, the code resilient and easy to test.

A direct quote from my "expert-junior-evangelical" phase. When I marveled at my own cleverness & marketed my brand-new paradigms to my unfortunate peers. Lots of assertions, few citations, no research. All the fun was in coding, not in studying books or even the industry at large. Then, business requirements changed and I was left to maintain over-engineered monolith of my own making.

After a few cycles of hubris, I learned the danger of selling fads as evolutions. It hollows you out.

discreteevent|4 years ago

> not in studying books or even the industry at large

In fairness the author spends most of the article explaining the approach of the industry at large (it's a good explanation too).

gherkinnn|4 years ago

Thank you for formalising this.

We came to a similar conclusion as we moved from imperatively handling server state to using ReactQuery.

What I got to like the most was the small cognitive load. Other than the minimally shared UI state, everything I need to hold in working memory is close by. Not that it's novel or impossible to achieve the same through other means, but that this way of building UIs often leads to a manageable result.

It works very well in cases where the server is the source of truth, but I don't want it to feel like it is.

The creator of ReactQuery talks extensively about the philosophy behind his library in a recent PodRocket episode. [0]

0 - https://podrocket.logrocket.com/tanstack

alexey2020|4 years ago

"the small cognitive load" - true that!

Thanks for the link to the podcast. Will definitely check this out

filoeleven|4 years ago

This article gives a great rundown of various UI layer approaches, the problems with each, and how the subsequent ones solved them. I hadn’t seen react-query or its listed alternatives before, so thanks!

The one thing I’m not clear on is how this is much different from the “single global store” approach. It looks like that’s what this approach uses, and the main difference is in the “store API.” In other words, usage from components is nearly identical, and it’s the mechanics of the store itself that is changed. There’s a layer of focused queries between the store and components that hides the access (and maybe update?) mechanics from the widgets. So instead of

  getFromStore(“books”, bookId) // pseudocode, I am not a Redux user
you instead use

  useBookQuery(bookId) // which includes some nice things like { isLoading, error }
It doesn’t seem to resolve the need to handle the following bullet point found in the store drawbacks, it “just” pushes it into a group of queries (and presumably updates).

> we now have to deal with a completely new concept, the Store, and care about a bunch of new things, such as designing and maintaining Store structure, appropriately updating data in the Store, data normalization, […]

Is this separation the point? Or am I missing something else? Keeping the store access mechanics separated from the widgets that use them makes sense to me, especially when it has built-in loading/error notifications. I was going to say that “widget driven development” doesn’t really point to what this achieves by making that separation, but I may be coming around to the term with those other considerations.

I suggest emphasizing the loading/error mechanics more strongly at the end of the article. React is doing a lot of work with Suspense to improve their ability to give UI feedback in those states, and it looks like this approach simplifies the data side of that.

alexey2020|4 years ago

Thank you for the valuable feedback!

Very good question about the difference between `getFromStore` and `useBookQuery`.

When using `getFromStore` you have the expectation that the value is already in the Store. Someone should have already put the value there somehow.

You have also the expectation that `getFromStore` is synchronous and simply gives you nothing if the value is not there.

With `useBookQuery` you expect the value to be fetched from Server. There is no 3rd party to care about putting the value in the Store. `useBookQuery` is simply like `fetch('...')` from a Component perspective.

With libs like ReactQuery every component "simply" fetches what it needs, sort of directly communicating to the Backend. No intermediary party (like a Store)

>React is doing a lot of work with Suspense ...

Yeah, I heard about React team collaboration with libs like ReactQuery on making Suspense work with those, also on server side. But I'm not much into that Suspense topic, so decided to not mention anything about it.

>I suggest emphasizing the loading/error mechanics more strongly at the end of the article.

Thanks for the suggestion. I will think about it.

tmikaeld|4 years ago

The benefits seem unclear to me, especially how this solves the shared-state issue. Is it just that each "widget" calls the same API "manager" and propagates the changes to every widget in the event of a change?

Isn't this exactly what Redux already do if you use actions to fetch data and put it into the store, with the difference that each "widget" manage filters and state based on the fetched API data? Seems like it could create a lot more code with less re-usage, since every widget has to manage this themselves.

alexey2020|4 years ago

With pure Redux approach the mutation flow is more complex: - send mutation request to Backend - fetch updated data - put the updated data in the Store - see the updated data propagated in components

The suggested approach: - send mutation request to Backend - see the updated data being fetched and displayed by components

To me the second is much cleaner and easier to reason about

cjfd|4 years ago

One problem is the idea that there is a one-size-fits-all solution. An application should be structured in such a way that it fits the problem that you are trying to solve as ergonomically as possible. 'Widget Driven Development' might be very good in some circumstances but not in others.

alexey2020|4 years ago

Agree. There are applications where widgets approach would not bring much benefits.

Let say, applications with lots of UI state (state that doesn't exist on Server).

Also not sure how it would work with realtime apps.

It's the same with every approach, the are always exceptions from the rule.

That said, I see the benefit of this approach for the majority of UI apps, which heavily rely on Server data.

d--b|4 years ago

This is rather vague.

Let's take a more concrete example:

Let's say you want to add a button somewhere that hides/shows another widget. Surely you don't want to go to the backend to do that? So how do you do it? With the store approach, clicking the button creates an action, that modifies the store (changing a visibility parameter somewhere) and repaints the UI.

In the diagram there is no flow back from the "API" box to the widgets. Though it still something that needs to happen.

The "API" necessarily contains some state, at least to track which component needs which data.

alexey2020|4 years ago

>Let's say you want to add a button somewhere that hides/shows another widget.

That's a good case. This is purely UI state, right? (we don't store it on the server).

For UI state we still need to depend on prop-drilling or State Management solutions.

In the article I'm mainly talking about the Data which exist on Backend (as you can also see from all the pictures). In my experience such Server data is 90-95% of all data in most UI applications and that data contributes the most to the complexity.

Pure UI state is often just a fraction of the the whole State and is's often synchronous, so managing it should not be complex. So this kind of coupling will still exist.

To clarify, I do not say Widgets should be 100% independent. We do not achieve complete decoupling. But moving Server Data under control of Widgets gives us closer to this.

alextheparrot|4 years ago

Would this work with server side rendered applications? We SSR a lot of the data calls, as the identifiers to be fetched is usually available in the URL.

——

Nvm, I see that’s listed as a React Query feature.