After a lot of years of application development I was just improving my frontend skills while learning react. Since my passion is architecture and therefore application structure, I thought about how to structure a react app. I thought about my frontend experiences in developing RCP applications build with Swing or Eclipse RCP (SWT). In those RCP environments one usually desings UI models that are stable abstraction of what one wants to view and then use UI components that operate on these models. Stable abstractions are usually a good practice that help you to stay flexible and with “flexible” I mean to easily change UI components and to easily test their behavior.
In contrast to my experience in the RCP world I wondered why React frontend developers often don’t use stable abstractions of what they want to view. Most models are tightly coupled to the use case they are made for. E.g. I often see the JSON objects that are returned by rest services directly used in the UI component. Even if this is a straight forward development it does not give you a lot of flexibility when you want to replace a view component or even create view components that are reusable.
One might think now…
Why do I need the replaceability of my components, I don’t want to write a library. I want to program a particular application thus I’m writting specific components.
That sounds straight forward. But we still have the testabililty aspect and product owners can quickly change their minds and we should be prepared for this.
So let me tell you a little story of how an application development might be:
One day in a sprint planning meeting the product owner says…
Product Owner: Our survey dialog has multiple pages with questions that the customer can answer. I want a kind of progress view so that the customer can always see how much pages are left.
Developer: Ok I will implement a beautiful progress view.
The first component the developer comes up with might look like this
Our product owner is happy and really likes the progress view. But after a while the product owner comes back…
Product Owner: The progress view of our survey dialog looks nice, but it consumes a lot of space. I want a progress view that is less space consuming. Could you please make a proposal?
So the developer implements a progress view like this.
Our product owner likes the new view and is again happy (for a while….)
After a while the produce owner comes back…
Product Owner: At the moment our survey dialog shows the progress of the survey and we have that next- and previous-button at the bottom. The progress view tracks the dialog pages that have already been processed. Is it possible that the progress bar can also be interactive. I mean that the customer can go back and forth by clicking on the progress bar. Developer: Hmm, looks like you want a kind of slider. I will implement it and we will see.
So the developer starts implementing a slider like this:
Ohh, this was a lot of work, because it is now an interactive component. But sadly it is not what our product owner wants.
Product Owner: This is not exactly what I wanted. I was looking for a kind of paging.
So finally the developer comes up with the following solution.
How much work do you think the developer has invested and how many of the different components that were implemented are reusable?
Wouldn’t it be nice if we had implemented all the different solutions in a way so that we can reuse them in other contexts as well – I mean real ui components or just switch back to a previous design when needed?
Wouldn’t it be nice if you could just replace
<ProgressCircle model={model} />
with
<ProgressBar model={model} />
At the begining of this blog I said
I usually desing UI models that are stable abstraction of what I want to view and then use UI components that operate on these models.
What is the stable abstraction of a progress bar, a slider, a progress circle and a paging?
Java swing calls the common model a BoundedRangeModel and it’s a quite good name. In our web frontend world we could use a similar model. We can just say that there is a data structure like this:
{
min: 0,
max: 100,
value: 20
}
After we have defined this abstract model, we can create controllers, etc. that operate on it. Take a look at this codepen for an implementation proposal.