Frameworks are the wrong level of abstraction for UI widgetry

Frameworks are the wrong level of abstraction for UI widgetry

Released Sunday, 2nd February 2025
Good episode? Give it some love!
Frameworks are the wrong level of abstraction for UI widgetry

Frameworks are the wrong level of abstraction for UI widgetry

Frameworks are the wrong level of abstraction for UI widgetry

Frameworks are the wrong level of abstraction for UI widgetry

Sunday, 2nd February 2025
Good episode? Give it some love!
Rate Episode

Episode Transcript

Transcripts are displayed as originally observed. Some content, including advertisements may have changed.

Use Ctrl + F to search

0:00

All right, we got to

0:02

talk about programming for a

0:04

second. So I'm working on this

0:06

charting library and it's

0:09

like, it's following the exact

0:11

same path as the date

0:13

picker. It's this pattern, you know,

0:15

where you just start a

0:17

thing, you just start like

0:19

running into the thicket of

0:22

a tough problem and you're

0:24

just like baton away like. you

0:26

know, bushes and thorns and you're

0:28

just running, you trip on a

0:30

log, that's the discovery phase. You're

0:33

making a mess. Claude's right in

0:35

half your code. It's just, you

0:37

know, you're just discovering, that's what

0:39

you're doing. You're discovering

0:41

the shapes of the problem domain, I

0:43

guess, but just the shapes of the

0:45

thing you're trying to build. You're

0:48

going, oh, that's a shape there,

0:50

that's like an axis or something,

0:52

like that's a concept, you're discovering

0:55

the concepts. Which at first

0:57

it starts out as broad

0:59

strokes like okay, there's an

1:01

x-axis and a y-axis and

1:03

then there's data along those

1:05

axes You know, okay, that's

1:07

simple enough and ticks like follow

1:09

the axes axis and they they

1:12

kind of happen at the points

1:14

that the data happens and you

1:16

have an x-y coordinate pixel system

1:18

and then you have you know,

1:20

value domains that map to those

1:23

pixels and like that's kind of

1:25

the initial concepts and you go,

1:27

all right, and then you try

1:29

to represent them in your code

1:31

as you go because, you know, it just slows

1:33

you way down if you just never take a

1:35

minute to like shore stuff up. But then

1:38

you just keep moving and then you find

1:40

like the next, the next place that your

1:42

code breaks down, which is usually, for

1:44

me, it comes in the form of

1:46

like, well, not only conditionals everywhere, but

1:49

then I start to realize that. Like,

1:51

you start to see the things you

1:53

don't understand or you start to see

1:56

the questions you have of like, oh,

1:58

wait a minute. So grid lines. Do

2:00

they align with ticks? Like ticks don't

2:02

always align with your data, especially on

2:04

the y-axis. Yeah, both axes, especially on

2:07

the y-axis. ticks don't align with your

2:09

data. So do you align grid lines

2:11

with, like that was one quick thing

2:14

I first ran into. It's like, my

2:16

horizontal grid lines were aligned with, well,

2:18

I guess? Yeah. I don't know. I

2:20

think the horizontal grid lines I initially...

2:23

Because gridlines just look evenly spaced. So

2:25

I initially had them just evenly spaced.

2:27

And then when I realized you have

2:30

to like calculate what value show up

2:32

on the y-axis for ticks, because the

2:34

x-axis is kind of easy. You can

2:37

just put a tick initially. You can

2:39

just put a tick at every data

2:41

point, but the y-axis is not like

2:43

that. It's like a linear scale, you

2:46

know? So you calculate those ticks, but

2:48

then, oh, they don't match up with

2:50

the horizontal gridline. So those gridlines need

2:53

to be bound to my y-axis ticks.

2:55

So that means I need to calculate

2:57

my ticks up front and make sure

3:00

that the code is all structured such

3:02

that it can all relate to each

3:04

other in this way. So that was

3:06

like one area where it's like, oh,

3:09

the system's breaking down, my mental model's

3:11

breaking down. There's relationships here that I

3:13

didn't see up front. And now I'm

3:16

starting to see. Like, ah, horizontal grid

3:18

lines map to ticks. Now, vertical grid

3:20

lines, do those map to data points,

3:23

or do they map to X-axis ticks?

3:25

Because X-axis ticks don't always map to

3:27

data points. Like in a time series,

3:29

there might be like increments of single

3:32

months, but there might be like many

3:34

data points within those months. Where do

3:36

your vertical grids, who do your vertical

3:39

grids align with? And the answer is

3:41

different. face was like, oh, grid lines,

3:43

go with ticks. And ticks, like, well,

3:45

whatever, there's, and then there's some chicken

3:48

and egg things that happened. I found

3:50

two chicken and eggs with charting. Like,

3:52

you need to draw the whole chart

3:55

first to know the size of everything,

3:57

to know if you need to like.

3:59

scale it down. And then once you

4:02

scale it down, you have to

4:04

redraw the whole chart. So there's

4:06

a lot of like relationships between

4:08

data and positions. But then you like

4:10

need to figure it all out first

4:12

and then redraw it to adjust spacing

4:14

for everything. So that's like a chicken

4:16

and egg. That's a solution. You know,

4:19

with chicken and egg problems, there's like,

4:21

I guess the best solution for a

4:23

chicken and egg. It's like, like, let the

4:25

chicken. And let the egg, like, like,

4:27

like, like, exist. Then let it hatch

4:29

into a chicken and then go back

4:32

and put it back in the egg.

4:34

So stupid. I don't think that worked.

4:36

So that was the first chicken and

4:38

egg problem. The second one I

4:40

just encountered is when you calculate the

4:43

domain of your data set, you know,

4:45

so if you're mapping like, you know,

4:47

you have a big array of objects

4:50

and each object has like the month

4:52

in it, the sales numbers for that

4:54

month, and the refund amount for that

4:57

month. So you have like... your x-axis,

4:59

your, remember the constant, these are

5:01

things that you haven't heard in

5:03

a while, domain, range, and independent

5:05

and dependent variables. You remember

5:08

those from math class? So

5:10

the dependent variable is the

5:12

y-axis, the thing that changes, the

5:15

independent variable, is the x-axis, the

5:17

thing that is constant, you know,

5:19

the thing that your data set

5:21

is related to, is your independent variable,

5:23

I believe. So... In this case, like

5:25

if you have this object of month,

5:28

sales, and refunds, month is your independent

5:30

variable. It's unchanging. It's the thing with

5:32

which you are comparing the other numbers.

5:34

And those other numbers are your series.

5:37

It's sort of like if you look

5:39

at this picture this Jason object, where

5:41

you have these objects, one on top

5:44

of the other, and there's three, basically

5:46

it's like a table with three columns.

5:48

The leftmost column is your independent variable.

5:50

The other columns, those slices, those

5:53

are series. And the plural of

5:55

series is series. It's a, it's

5:57

called a zero plural. These are

5:59

all the... random things you encounter

6:02

as you start working on

6:04

a thing you know like

6:06

deer series we already said

6:08

and it's access for singular

6:10

it's axes for plural which

6:12

is spelled like multiple hatchets

6:14

axes but it's it's funny

6:16

axes is spelled like ax

6:18

there's axis and then if

6:20

you have if you own

6:22

multiple things like tree cutting

6:24

implements. You have axes, but

6:26

if you're looking at multiple,

6:28

like reference lines on a

6:30

chart, they're axes, but they're

6:32

spelled the same as the

6:34

tree cutting implements. So that's

6:36

kind of fun. You know

6:38

what? The other one I

6:40

never get right is dice.

6:42

Dice. Plural of... Dice? No,

6:44

it's singular of dice. So

6:46

the plural of dice is

6:48

dice. Dice is an irregular

6:50

plural noun, so it doesn't

6:52

follow the rule of adding

6:54

right to the single world.

6:56

Dice is the plural of

6:58

the singular word die. Dice

7:00

can be used both as

7:02

a singular and plural. This

7:04

is clearing things up for

7:06

me. Okay, so it's one

7:08

die, but it can also

7:10

be one dice. You know?

7:12

But it's multiple dice, but

7:14

it can be multiple dice.

7:16

It's dice. Makes sense. Anyway,

7:18

where were we? These relationships,

7:20

the chickens and the eggs.

7:22

So I realized that it's

7:24

like when you calculate the

7:26

domain all the available, the

7:28

range of available values in

7:30

your chart, and then you

7:32

calculate the range, which is

7:34

the pixel values that those

7:36

are going to map to,

7:38

and then you calculate the

7:40

scale functions that convert arbitrary

7:42

values based on the domain

7:44

within that domain, within the

7:46

mins and maxes, into, you

7:48

know. relative pixel values for

7:50

the screen. But what I

7:52

realized is like when you

7:54

calculate ticks on the y-axis,

7:56

you might buffer like the

7:58

top tick because You might like

8:00

you could make it so that the

8:02

ticks happen in equal increments like 5

8:04

10 50 and then the top tick

8:06

is the the top most highest Y

8:09

value you have But like that kind

8:11

of looks a little weird. So you

8:13

often just overshoot You know, it's like

8:15

5 10 15 20 even if the

8:17

highest value in your in your line is

8:19

like 18, you know So now the

8:21

available domain on your chart is zero

8:23

through 20 not zero through 18. So

8:25

you have to calculate the initial domain

8:28

based on your data set Then you

8:30

have to draw all your ticks and

8:32

lay them out and decide what steps

8:34

they're going to be in. Then you

8:36

have to recalculate the domain based on

8:38

the new available, based on the

8:41

original values combined with the

8:43

tick values. Because sometimes ticks

8:45

might even be within the bounds of

8:47

your data set. So you kind of

8:49

have to do this like, well, whatever.

8:51

Anyway, that's a chicken and egg problem.

8:53

But you don't know. Like it's just...

8:56

It's just your code breaking down

8:58

and then you have to go

9:00

investigate why. Is it because you

9:02

don't understand something? Is it because

9:04

you thought there was a relationship

9:06

that there wasn't? There's all sorts

9:08

of those because like you have

9:10

an x-axis and a y-axis and

9:12

they're the same in so many ways,

9:15

but they're different in other ways.

9:17

Like for example, the x-axis is

9:19

a dependent variable. It will only

9:21

map to a single... a set of

9:24

values where the y-axis is

9:26

a it's an aggregate scale

9:28

it represents the scale of many

9:30

different series so anyway that changes

9:32

a lot of math so I

9:34

had rewrote the whole thing because

9:36

you know that's how it goes I

9:39

mean I've kind of rewrote them

9:41

all times but this was the

9:43

big rewrite and what was the

9:45

big revelation here the big revelation

9:48

was the same one it always

9:50

is separate the data from the

9:52

presentation of the data. Sit down,

9:54

this is me with a pen and

9:57

paper, sitting down, and figuring

9:59

out all of the properties, all of

10:01

the, all of the data. If

10:04

I made a giant god chart

10:06

object, what would the properties be?

10:08

With, height, axes, and then within

10:11

axes, it'd be X and Y,

10:13

and within X and Y, it

10:15

would be the field name, it

10:18

would be the scale, the domain,

10:20

the range, the scale, line paths,

10:22

like generators, like. all sorts of

10:24

stuff like that. Then there's series

10:26

inside the chart, which is an

10:29

array of all of the data

10:31

series that are going to be

10:33

mapped, you know, on the y-axis

10:35

and extra helper functions within those

10:38

series. Anyway, so all the data,

10:40

purely data, this is something that

10:42

I think charting gets wrong

10:44

almost universally is conflating the

10:47

data with the presentation. which

10:49

is like an obvious thing

10:51

to separate, but charting is

10:53

the worst offender when you're

10:55

defining a series, which is a line,

10:57

on a chart, or a bar, set of

10:59

bars, you might specify a color for the

11:02

series. But what if you want

11:04

different colors for the series, the

11:06

points on the series? And now

11:08

you, that's another config, and you

11:10

know, whatever. It's like colors live...

11:13

right next to line thicknesses or

11:15

stroke widths and they live right

11:17

next to like data keys and

11:19

hard numbers and that's wrong. So

11:21

I'm completely separating out the entire

11:23

data portion such that I basically

11:26

have an object that could drive

11:28

out like you could use this

11:30

if you were really brave you

11:32

could use this to drive out a

11:34

chart in alpine I think. Like it

11:36

would be fun to turn this into

11:38

an alpine plug in and just see

11:40

if like... I think alpine works

11:42

inside of SVCs. SVCs are

11:44

weird. They're in a different

11:47

name space. You ever like

11:49

seeing like N.S. in in

11:51

HDML stuff like when you're,

11:53

I don't know, where have I encountered

11:56

at us? I've definitely

11:58

encountered it. But SVG elements

12:00

are different than HDML elements. They're within

12:03

a different document name space. And there's

12:05

like little things that are just odd

12:07

or different, like a template tag inside

12:10

of an SVG doesn't work the same.

12:12

It won't really have any content. It's

12:14

not a normal, it's not like recognized

12:16

as an element. So that's like a

12:19

hurdle I had overcome, but anyhow. So

12:21

it makes things like dom crawling a

12:23

little bit weird. It can mostly work,

12:26

but there's weird stuff like in SVG,

12:28

transform and opacity and everything. Those are

12:30

attributes as well as CSS properties. Not

12:33

just CSS properties like in normal

12:35

HDML. So weird stuff. Anyway, I

12:37

think Alpine works inside of SVG.

12:39

I'm pretty sure. That'd be pretty

12:41

fun. This would be fun. Ooh, I should

12:43

do this. This is rivers. Yeah, we can do

12:45

it. Dad, we could do it. So yeah. Yeah. Yeah.

12:47

Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah.

12:50

Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. That's something

12:52

I should do. Okay, so the thought

12:54

again just to reiterate that It's like

12:56

this is how it goes You gotta

12:58

just you gotta you gotta enter the

13:00

discovery phase and make big heaping piles

13:03

and messes Then to know what you

13:05

don't know to establish the concepts to

13:07

establish your constraints and your scope then

13:09

Then once you've already like

13:11

understood these things separate out the

13:13

data in the presentation and that

13:16

is your golden ticket Because you

13:18

can't do that up front because

13:20

you don't know the data and

13:22

you don't know the presentation So

13:24

it's I think it's better up

13:26

front to just make a giant mess

13:28

and then sit down with a pen

13:31

and pad and a cup of coffee

13:33

or tea and figure out You know

13:35

how you're going to represent it all

13:37

and have a good long chat with

13:39

chat GBT which in this instance was

13:41

way better than clod I'm getting so

13:43

sick a cursor cursor as dumb as

13:45

rocks that it's doing for me is

13:47

like recognizing when I make a change

13:50

on one line and I need to

13:52

make it on like 50 lines but

13:54

other than that it's constantly generating shit

13:56

code like constantly it is not helpful

13:58

to me in this code base anymore

14:00

at all, which is a huge

14:02

bummer. And I went back to

14:05

chat TBT for fun to just

14:07

see what chats up to and

14:09

have a conversation with chat about

14:12

some charting concepts while I was

14:14

like mapping out the chart object.

14:16

And it was like a breath

14:18

of fresh air. It wasn't shoving

14:21

react on my throat every two.

14:23

It was like way more

14:25

capable than Claude. It's so weird.

14:27

I don't follow the models. But

14:30

maybe chat just like has something

14:32

better now that's awesome. I don't

14:34

know. Try it out. It's nice.

14:37

It's faster too. The interface is

14:39

better. Feels cleaner. Even though clots

14:41

like constantly generating like code and

14:43

trying to run it for you.

14:45

And it's just not that useful.

14:48

Like I just don't, that's not how

14:50

I work with AI, I don't want

14:52

to like iterate on a thing that

14:55

we're testing in the browser because I'm

14:57

always looking for pieces, you know, I'm

14:59

never looking for like, Alexa make

15:02

me an app, you know, because it's

15:04

going to be a heaping dumpster fire

15:06

mess and and make the like, you

15:08

know, the, whatever, the size, token,

15:10

document, whatever thing that you send

15:13

back and forth, you're going to

15:15

like bust through your AI limit.

15:17

We're really rambling today, huh? Yeah,

15:19

so that's, you know, you work

15:22

with chat TVT and you bring,

15:24

you bring, yeah, you figure out

15:26

the domain and then you separate

15:28

the data in the presentation and

15:31

you do that. And that's great.

15:33

And that's the pattern to like

15:35

solving a tough programming problem and

15:37

it's nice. Okay, so another thing

15:39

that I wanted to mention at

15:42

some point, which we're, what's our time

15:44

here? Oh yeah, we're already 15, let's

15:46

go 20. think react well

15:48

we'll see because if I

15:50

turn this into an alpine

15:52

plug-in and it's like really

15:54

awesome and I love it that'll

15:56

be fun but I think that

15:58

frameworks I think the

16:01

perfect place to

16:03

be is your UI

16:06

widgets, basically, is the

16:08

wrong level

16:10

of abstraction

16:12

for componentry,

16:14

for discrete UI

16:16

widgets, basically.

16:19

I think the perfect

16:21

place to be is your

16:24

UI widgetry is

16:26

self-contained.

16:28

And it's self-contained. That's

16:30

something that I dislike,

16:32

and I don't work

16:34

and react every day,

16:36

granted. But something I dislike,

16:39

I mean, it applies to

16:41

alpine as well. Something I

16:43

dislike about using these frameworks

16:45

where they break down for

16:47

me is when you zoom way in, you

16:50

know, when you're doing surgery

16:52

on very nitty gritty things.

16:54

That's where they break down.

16:57

And I've sourced of so

16:59

many react widget libraries. It's

17:02

insane. And inevitably, when I

17:04

read react app code, it's not

17:07

so bad. Same thing with view

17:09

code and whatever. But when you

17:11

look, when you like, when you

17:13

see it being used for

17:16

very surgical things, like a

17:18

charting library, or even

17:20

a drop down menu, like a

17:22

real, you know, one with the

17:24

like, drag over stuff. When you see

17:26

that, you see how it all breaks down. It's

17:29

not fun anymore. It's gnarly. And

17:31

here's what's wrong with it. What's

17:33

wrong with it is, well, A,

17:35

often, like, a lot of the

17:37

optimizations of these libraries kind of

17:39

break down at that level of

17:41

granularity and you end up trying,

17:43

end up wrestling with them more

17:45

than anything and having to really

17:47

lean on things like memoization or

17:49

whatever, because RAC, I mean, specifically,

17:51

is kind of built for... course

17:53

grain updates where it's like gonna

17:56

it's gonna like re-render everything you

17:58

know and then find the diffs

18:00

and patch them, which isn't

18:03

necessarily what you want, because

18:05

you might, well, whatever, you might

18:07

need to, you might have a

18:10

thousand ticks on a line, or

18:12

you might have like a thousand

18:14

points on a grid, and you

18:16

might have like a thousand points

18:18

on a grid, and we might

18:21

have to update that a

18:23

hundred times in five milliseconds

18:25

or something that you pay

18:27

the cost for. In simple

18:29

way, like if you have a ton

18:32

of work to be done, a scheduler

18:34

is good and is going to help

18:36

you, but if you are not doing

18:38

a ton of work, you pay a

18:40

cost by using a scheduler in general.

18:42

And there's so many things like that,

18:44

where you just have all this overhead,

18:46

not to mention the cognitive overhead and

18:48

the conceptual overhead and the siloing of

18:51

all these useful widgets that are now

18:53

silo to react for no good reason.

18:55

And you like, yeah, it's frustrating to

18:57

me. is the place to be for

18:59

discrete UI widgetry because

19:01

it's not rocket science like it's

19:04

dom manipulation. You already know it.

19:06

It's like you create an element,

19:08

you append it on a page,

19:10

you set some attributes, you move

19:13

it around, that's kind of it.

19:15

It's like... you can delete the element,

19:17

you can change its text content, you

19:19

can crawl its children, whatever, and you

19:21

can just kind of get done what

19:23

you need to get done. And you

19:26

have full control over when an element

19:28

is rendered versus when it is updated,

19:30

how often it is updated, you can

19:32

create your own little observable, you know,

19:35

engine that can fully control those

19:37

updates, you're not relying on, you

19:39

know, um... on like the system to detect

19:41

when your data changes to re-render everything,

19:43

you would get more control over that.

19:46

You can re-render the only things that

19:48

need to change when some other thing

19:50

changes. And the massive benefit of this,

19:52

aside from all those other reasons, is

19:55

that work can be shared across ecosystems.

19:57

How amazing would it be if React

19:59

Aria was... custom web elements like

20:01

shoelaces or if it was just

20:04

something that that was embraced by

20:06

all ecosystems and was written in

20:08

vanilla JavaScript and for vanilla non-frame

20:11

for non-frame work front-end I guess

20:13

then we could all use it

20:16

and wouldn't that be a wonderful

20:18

life there is an alternate universe

20:20

where I make this my mission and I

20:22

take all of the work that I'm

20:24

doing and make it like a crusade to

20:27

bring you know, to be the

20:29

savior of the non-react world.

20:31

But that's a pretty thankless

20:34

job. And it's definitely not

20:36

an income generating job. And

20:38

it's really what you're doing

20:41

is just fueling other people

20:43

to make money off you. But

20:45

that's my new cynical open

20:47

source take. Anyway, so yeah, so

20:50

those are some thoughts. But yeah,

20:52

I think discrete UI

20:54

widgetry is best done by few

20:56

people. by the way, I think there

20:58

should be, you know, I don't think, I

21:01

don't think everybody should be doing

21:03

this. I think few people who

21:05

want to really roll up their

21:07

sleeves and live this life should

21:10

do this for everyone else. And

21:12

then everybody, which is what I'm

21:14

doing, and by for everyone else,

21:16

I mean purchasers of flux. And

21:18

then everybody else for my

21:21

circumstance. And everybody

21:23

else can stay at the application

21:25

layer. They can stay at

21:28

mapping their database. They

21:30

can stay at configuring

21:32

this, this UI

21:35

component widgetry to

21:38

get data in and

21:40

to show the data out.

21:42

That's the layer that

21:44

web developer is

21:46

going to sit in. And

21:48

yeah, so that's the way

21:51

it should be. I don't

21:53

know. Have we said anything.

Rate

Join Podchaser to...

  • Rate podcasts and episodes
  • Follow podcasts and creators
  • Create podcast and episode lists
  • & much more

Episode Tags

Do you host or manage this podcast?
Claim and edit this page to your liking.
,

Unlock more with Podchaser Pro

  • Audience Insights
  • Contact Information
  • Demographics
  • Charts
  • Sponsor History
  • and More!
Pro Features