[HN Gopher] How functional programming shaped and twisted front ...
       ___________________________________________________________________
        
       How functional programming shaped and twisted front end development
        
       Author : jicea
       Score  : 114 points
       Date   : 2025-10-04 13:04 UTC (9 hours ago)
        
 (HTM) web link (alfy.blog)
 (TXT) w3m dump (alfy.blog)
        
       | davedx wrote:
       | Think some of that (the dialog and friends) is the wrong way
       | around: we wouldn't have gotten all those nice DOM native
       | components if libraries and frameworks hadn't popularised them
       | and driven adoption into the standards.
       | 
       | I am not sure I agree "the state of front end development" is due
       | to "functional purism" either. React just provided a good
       | abstraction that worked well for many people. It's a meritocracy.
       | If the abstraction that worked best (however we measure that) had
       | been something more OOP then that would have been adopted.
        
         | paulryanrogers wrote:
         | It's funny because React has both class-based components and
         | more functional components.
        
       | madeofpalk wrote:
       | Not sure I agree with the tone of the article, but I do find that
       | Javascript developers have a weird relationship with "functional
       | programming". I see _so much_ convoluted code with arr.reduce()
       | or many chained arr.map().filter().filter().map(), that would
       | just be so much simpler and easier to read if it was a classic
       | for-loop. I suggest this to people and they scoff at the thought
       | of using a for-loop in Javascript.
       | 
       | > _Consider the humble modal dialog. The web has <dialog>, a
       | native element with built-in functionality. [...] Now observe
       | what gets taught in tutorials, bootcamps, and popular React
       | courses: build a modal with <div> elements_
       | 
       | The dialog element is new! Only broadly supported since 2022. I
       | find it hard to fault existing material not using it. Things like
       | dialog, or a better select, are notable because they were lacking
       | for so long.
        
         | madeofpalk wrote:
         | On the other hand, from my experience, large development teams
         | cannot write CSS at scale. "Writing clean CSS code" doesn't
         | seem to be a skill that most (frontend) developers seem to
         | value, so abstractions like CSS Modules (which is barely an
         | abstraction - it's just compile-time BEM) and CSS-in-JS came up
         | to manage complexity of both a large codebase and large team.
        
           | hombre_fatal wrote:
           | On the _other_ hand, scaling CSS is fundamentally hard
           | especially in a large team where it 's more of an
           | organizational problem.
           | 
           | It takes eternal vigilance to maintain it. Refactoring it is
           | a huge feat. And when you want to modify or add a single
           | component, it doesn't make sense to re-cred in the whole CSS
           | apparatus, and it's not necessarily trivial to figure out
           | where to make the CSS change, so CSS files tend to become
           | append-only.
           | 
           | It's like how learning how to "write clean code" doesn't
           | really change much about how hard it is to change large
           | software systems over time in a large team.
        
             | Terretta wrote:
             | These difficulties with CSS are how you know an org can't
             | "design system".
             | 
             | You will see similar issues with their Word and PowerPoint,
             | setting properties on elements instead of styles.
        
               | pverheggen wrote:
               | Yeah, most orgs use Figma as the source of truth, so if
               | your designers don't "design system", it finds its way
               | into the codebase.
               | 
               | Even if they do follow a design system, it tends to
               | evolve over time, and it can be a bumpy road to reach a
               | mature one.
        
             | madeofpalk wrote:
             | Yeah, this is exactly my point. It's hard to do, doubly so
             | when most folks don't value it.
        
         | nucleogenesis wrote:
         | I'm fond of chained array methods, especially if the callbacks
         | I pass are named functions - it can make for code that I find
         | way more legible than for loops. But even with anonymous
         | callbacks I'd rather do that ~90% of the time than use a for
         | loop anyway.
        
         | dapperdrake wrote:
         | Series (by Richard C. Waters) are a pipelining compiler for
         | map/reduce.
        
         | ninetyninenine wrote:
         | The benefit of FP has nothing to do with it being easier to
         | read. FP is HARDER to read. The benefit of FP is modularity.
         | Take your example:
         | arr.map().filter().filter().map()
         | 
         | Every step on that is a modular operation.
         | const x = arr.map()        const y = x.filter()        const z
         | = y.filter()        const d = z.map()
         | 
         | now I can easily do this:                  const x = (arr) =>
         | arr.map()        const y = (arr) => arr.filter()        const z
         | = (arr) => arr.filter()        const d = (arr) => arr.map()
         | o = d(z(y(x(arr))))
         | 
         | This is the main reason why functional programming is elegant.
         | It makes every corner of your program modular and solves the
         | fundamental program of program organization and modularity.
         | 
         | with a for loop it is easier to read initially but if that
         | filter chain grows the functional approach will begin to be
         | better.
         | 
         | Take an example of a for loop doing the same thing:
         | const acc = []        for (const x in arr) {           y =
         | map1(x)           if(filter(y) {              continue
         | }           z = y           if(filter(z)) {
         | continue           }           d = map2(z)
         | acc.push(d)         }
         | 
         | Yes more readable but imagine if the logic gets even more
         | complex. Then at scale functional will become more readable AND
         | more modular. Modularity, however, is the main problem here.
         | You cannot split or modularize that for loop.
         | 
         | But I agree with you. Initially and not at scale, functional
         | programming loses readability. Functional programming is harder
         | to read because people think procedurally over functionally. We
         | like numbered instructions or a todo list, not a series of
         | composed function calls and thus from a general view point
         | functional programming is harder to read than procedural
         | programming. But this has never been the benefit of functional.
         | 
         | Functional programming is supposed to solve the modularity
         | problem with how you organize programs to be reusable.
         | Functional programming objectively does this while it is only
         | subjectively considered less readable by the majority of
         | people.
        
           | madeofpalk wrote:
           | I don't actually have all that much of a problem with
           | chaining fp-style functions, but I note that I see a fair bit
           | of anonymous functions and excessive chaining where none of
           | the benefits you point out are realised.
           | 
           | My _actual_ problem is with bad reduce functions that try to
           | shoehorn multiple things into one function and often break
           | the core concept of functional programming by mutating the
           | input arguments. It 's that code that would just be better
           | written as a normal loop.
        
             | whilenot-dev wrote:
             | > It's that code that would just be better written as a
             | normal loop.
             | 
             | Have to disagree with your conclusion here. It's that code
             | that should be rewritten, so it doesn't mutate the input
             | arguments at all.
        
           | edoceo wrote:
           | When I'm doing FP, rather than making a long chain, I assign
           | at each step, then call the next one. As you've shown above.
           | Sometimes I even comment on why the code is doing stuff.
           | 
           | Making it read as a list of steps, helps me understand what
           | it's doing a little easier than that long chain.
        
             | monkpit wrote:
             | Same. Chaining all of those together does nothing useful,
             | is arguably less readable, and the JIT will optimize out
             | the intermediate assignments. So there's not really any
             | reason to do that big chain (unless you're talking about
             | HoC/composable functions, which this example is not).
        
         | derefr wrote:
         | > I see so much convoluted code with arr.reduce() or many
         | chained arr.map().filter().filter().map(), that would just be
         | so much simpler and easier to read if it was a classic for-
         | loop.
         | 
         | It's interesting; when I'm writing JS in an actual .js file, I
         | _do_ tend to use for loops. But when I 'm writing JS at the
         | (CLI or browser-dev-console) REPL, I'll always reach for
         | arr.map().filter().filter().map().
         | 
         | When you're at a REPL, with its single-line/statement,
         | expression-oriented evaluation, it's always easier / more
         | intuitive to "build up" an expression by taking the last
         | expression from history, adding one more transformation, and
         | then evaluating the result again to see what it looks like now.
         | And you don't really want side-effects, because you want to be
         | able to keep testing the same original line vis-a-vis those
         | modifications without "corrupting" any of the variables it's
         | referencing. So REPL coding leads naturally to building up
         | expressions as sequences pure-FP transforms.
         | 
         | Whereas, when you're iteratively modifying and running a
         | script, with everything getting re-evaluated from the start
         | each time, it's not only more intuitive to assign intermediate
         | results to variables, but also "free" to have side-effect-y
         | code that updates those variables. It's that context where for
         | loops become more natural.
         | 
         | I bet that a lot of the chained-expression JS code you see out
         | there was originally built up at a REPL, and then pasted into a
         | file, without then "rephrasing" it to be more
         | readable/maintainable in the context of a code file.
         | 
         | ...though there's also just FP programmers who write JS (or
         | more often TS) as if it were a pure-FP language -- either
         | literally making every variable const / using Object.freeze /
         | using Readonly<T>, or just writing all their code _as if_ they
         | had done that -- where for loops become almost irrelevant,
         | because they 're only really for plain iteration (they're not
         | list comprehensions), and plain iteration has few uses if
         | you're not going to do anything that produces side-effects.
        
         | yearolinuxdsktp wrote:
         | I think it's a far cry on the original author's side to call
         | the use of map().filter().map() an obsession with FP.
         | Underscore.js simply provided super-useful functions over
         | arrays and objects, which IMO makes for more legible code.
         | Often times you can re-use filters with named functions. If you
         | have multiple conditions for iteration exit, it's clearer to
         | chain filters than it is to have nested ifs or early exits in a
         | for loop -- it refactors better.
         | 
         | The real obsession with FP is the pervasive use of immutable
         | state. But in apps, state must be effectively mutated, but now
         | with a copy of the original immutable object. The FP obsession
         | believes that this better than directly mutating the state each
         | and every time.
        
           | madeofpalk wrote:
           | Using these functions is not the problem. It's using them
           | passed the point of being reasonable where I see the
           | incorrectly placed obsession.
        
         | DavidWoof wrote:
         | It's hard to talk in the abstract because obviously people can
         | abuse any type of code feature, but I generally find chaining
         | array methods, and equivalents like c# linq, much easier to
         | read and understand than their looping equivalents.
         | 
         | The fact that you single out .reduce() here is really telling
         | to me. .reduce() definitely has a learning curve to it, but
         | once you're used to it the resulting code is generally much
         | simpler and the immutability of it is much less error-prone. I
         | personally expect JS devs to be on the far side of that
         | learning curve, but there's always a debate about what it's
         | reasonable to expect.
        
           | albedoa wrote:
           | > The fact that you single out .reduce() here is really
           | telling to me. .reduce() definitely has a learning curve to
           | it, but once you're used to it the resulting code is
           | generally much simpler and the immutability of it is much
           | less error-prone. I personally expect JS devs to be on the
           | far side of that learning curve, but there's always a debate
           | about what it's reasonable to expect.
           | 
           | Not only that, but the words that GP uses to single out
           | .reduce() start with:
           | 
           | > I see _so much_ convoluted code with arr.reduce() or many
           | chained arr.map().filter().filter().map()
           | 
           | Which I do not doubt, but the point is diminished when one
           | understands that a mapping of a filtering of a filtering of a
           | mapping is itself a convoluted reduction. Just say that you
           | prefer to read for-statements.
        
             | madeofpalk wrote:
             | I say _convoluted_. I prefer using the functional-style
             | array methods, but there 's a time and place for
             | everything, and I feel a lot of Javascript developers
             | extend those methods beyond what is reasonable and into a
             | convoluted mess, _especially_ with reduce.
             | 
             | Give me a good classic `T[] => I` reduce function and I'm
             | fine with it. Not the more common case of folks mutating
             | the accumulator object.
        
           | chuckadams wrote:
           | The wonderful thing about .reduce() is that it can compute
           | literally anything. The problem with .reduce() is that it can
           | compute literally anything. As for the rest of the morphism
           | menagerie, I like being able to break up functions and pass
           | intermediate results around. It's literally cut and paste
           | with map/filter, with a loop it's rewriting. Yay
           | composability.
           | 
           | That said, it's easy to get carried away, and some devs
           | certainly do. I used to be one of those devs, but these days
           | I sometimes just suck it up and use a local variable or two
           | in a loop when the intent is perfectly clear and it's not
           | leaking side effects outside of a narrow scope. But I'll be
           | damned if I let anyone tell me to make imperative loops my
           | only style or even my primary one.
        
             | chowells wrote:
             | Reduce cannot calculate literally anything, in the sense
             | you mean. It corresponds in computational power with
             | primitive recursion. And quite famously, there are problems
             | primitive recursion cannot solve that general recursion
             | can.
             | 
             | On the other hand, I don't think I've ever seen something
             | as recursive as Ackermann's function in real life. So it
             | can probably solve any problem you actually mean to solve.
        
             | zelphirkalt wrote:
             | Unfortunately, since we don't have continuations, we cannot
             | make reduce _stop_ computing. In such cases where that is
             | needed, it might be better to use a loop that can be broken
             | out of.
        
         | michaelcampbell wrote:
         | > that would just be so much simpler and easier to read if it
         | was a classic for-loop.
         | 
         | Only if that's how you were taught. For devs brought up in the
         | FP manner, the for loop is as hard to grok as you find the
         | chained stuff.
         | 
         | The Blub Paradox in action.
        
           | zbentley wrote:
           | I have never, ever seen this. And I've worked next to some
           | very FP-forward types and academic CS/abstract math
           | background types who have vastly deeper knowledge of their
           | fields than I ever will of mine.
           | 
           | Plenty of them don't _like_ imperative loops, sure. But I've
           | never seen someone assert that a simple loop is not
           | intelligible to them while chaining functions are.
        
             | chowells wrote:
             | If you're replacing a chain of filters and maps with a
             | nested loop, you're far past "a simple loop" and well into
             | the realm of an unintelligible for loop. The chain of maps
             | and filters tends to make that far easier to read by
             | decomposing it into separately-comprehensible pieces.
        
               | zbentley wrote:
               | Oh totally agreed; for complex transformations, being
               | able to compose and tap the intermediate states is really
               | nice (though I quite like generator/yielding functions
               | with captured stack state as a happy medium).
               | 
               | But that's not the claim I was pushing back on. That
               | claim was that, given a loop and some equivalent chained
               | list-processing functions, primarily FP-taught people
               | _could not understand the loop_ due to their background.
               | That's bogus.
               | 
               | That complex loops are hard to understand for anyone is
               | inarguable. But there's not some magical "functional
               | mindset" in which imperative/mutative code is
               | unintelligible to the point of total obscurity and
               | functional code is not. If there were, how would anything
               | ever get rewritten in a functional style?
        
         | Jcampuzano2 wrote:
         | Personally I use filter and map (and others like .some, .every
         | .flat and flatmap etc) all the time but I avoid reduce.
         | 
         | filter and map immediately tell me what the purpose of the
         | loops are - filter things and transform things. A for loop does
         | not do this.
         | 
         | To someone familiar with functional programming these are very
         | normal and easier to read and grep than just a loop. In other
         | words filter and map give additional context as to the intent
         | of the loop, a bare for loop does not.
         | 
         | Not to mention this is not abnormal in languages outside of JS,
         | even non-functional ones.
         | 
         | That said Ive seen too many convoluted uses of reduce that I
         | just avoid it out of principle.
        
           | sgarland wrote:
           | I like map() and filter() in Python, but unfortunately
           | they're 2nd class citizens compared to list comprehensions,
           | which continue to get optimizations to further increase their
           | speed.
           | 
           | I like comprehensions as well - and their syntax is quite
           | readable - but I'd like for the two to be more at parity.
        
             | zbentley wrote:
             | One of the main reasons that map() and filter() don't get
             | optimizations in Python is because they're _lazy_.
             | 
             | It's a lot easier to optimize comprehensions because you
             | can make a lot more guarantees about what _doesn't_ happen
             | between iterations: the outer stack doesn't move, the outer
             | scope can be treated as static for purposes of GC-ing its
             | locals, various interpreter-internal checks for "am I in a
             | new place /should I become aware of a new scope's state?"
             | can be skipped, the inner generator can use a simplified
             | implementation since it never needs to work with manual
             | send(), and so on.
             | 
             | Map/filter can't take advantage of any of those
             | assumptions; they have to support being passed around to
             | different arbitrary places each time next() is called on
             | them, and have to support infinite sequences (so do
             | comprehensions technically, but the interpreter can assume
             | infinite comprehensions will terminate in fairly short
             | order via OOM lol).
             | 
             | That said, there are likely optimizations that could be
             | applied for the common cases of "x = list(map(...))" and
             | "for x in filter(...):" (in nongenerator functions) which
             | allow optimizers to make more assumptions about the outer
             | context staying static.
        
               | lblume wrote:
               | list(map(f, ...)) should almost always be replaced with
               | [f(x) for x in ...] though.
        
           | Quekid5 wrote:
           | Yeah, the "problem" with reduce is that it can do anything,
           | and so doesn't offer much over a traditional for loop with
           | mutable local variables to accumulate into. Of course, if you
           | can replace a reduce() with a filter and/or map or whatever
           | (which more clearly states intent), by all means do so!
           | 
           | If you really need arbitrary computation, I'm not sure
           | there's any real readability benefit to reduce() over _local_
           | mutation (emphasis on local!). Sure, there 's immutability
           | and possibly some benefit to that if you want to prove your
           | code is correct, but that's usually pretty marginal.
        
             | lblume wrote:
             | Reduce can be very useful to signal that the state used is
             | inherently limited. My rule of thumb is to use reduce when
             | the state is a primitive or composed of at most two
             | primitives, and a for loop otherwise. What counts as
             | "primitive" depends on the language of choice and
             | abstraction level of the program, of course.
        
         | zelphirkalt wrote:
         | I think the reason for JS devs having "a weird relationship
         | with 'FP'" is, that JS itself, in its nature, is not a
         | particularly well suited language for FP. It has essential
         | elements, that by their nature are global mutable state. For
         | example timers and their ids.
         | 
         | Also weak typing plays into this. Some operations not
         | immediately raising an error when the wrong type of thing is
         | provided, is a recipe for bad experience when having point free
         | style or semi point free style. If given the choice, at least
         | one thing would be good to have, strong typing or static
         | typing.
        
       | ninetyninenine wrote:
       | I believe functional is the better (and best) paradigm we have
       | right now. But the problem of why FE development still feels
       | overcomplicated is because of a different reason.
       | 
       | There's a mismatch between how components are organized and how
       | data flows through the front end application.
       | 
       | HTML is hierarchical. You have elements wrapping each other
       | A        +- B            +- C            |   +- C1            |
       | +- C2            |   |   +- C2a            |   |   +- C2b
       | |   +- C3            +- D                +- D1                +-
       | D2                |   +- D2a                |   +- D2b
       | +- D3
       | 
       | The issue here is that you can have something like D3 changing
       | the state of an element like C3. So data must be artificially
       | grafted on the above hierarchy to make it work.
       | 
       | D3 wants to send data to C3? Well then that means B must be the
       | owner of the data. So data that feels like it must live on D3
       | well now you got to make it live on B which has nothing to do
       | really with D3.
       | 
       | This has one primary problem.
       | 
       | It destroys modularity and much of the benefits of functional
       | programming making it sort of useless in react. If you did prop
       | drilling most things that have a path from B to C3 and B to D3
       | now are no longer modular and can ONLY be used in context of data
       | related to D3. If you didn't use prop drilling and used some
       | contextual way to pass the data the problem is still there
       | because now components on that path have access to contextual
       | data that's irrelevant. I mean for a time it may be safe... but
       | some developer may break it and have a component access that
       | context and suddenly modularity is broken... that component can
       | now never be moved outside of the context.
       | 
       | Really... how data flows through your program is actually a
       | separate graph structure, and how HTML elements are organized in
       | your program is another separate graph structure we try to graft
       | into the first one and that creates a mess.
       | 
       | I think the best way to do this, hasn't been done yet. But really
       | side effects like clicks and button presses should NOT live on
       | components. Components don't know about these things. That keeps
       | the hierarchy and modularity of these html elements pure. A
       | framework that's well designed needs to enforce this separation.
       | I even think this can be done in a way that is STILL functional,
       | but not react.
       | 
       | HTML and jquery were sort of going in this direction, but the
       | problem was HTML lacked modularization because you couldn't group
       | tags into a component. You also have timing issues and complexity
       | with state that jquery didn't handle.
       | 
       | Overall I think the old style was actually better. It was a
       | better overall direction that had tons of problems and I think
       | those problems could have been solved if we continued in that
       | direction. AND i feel we could have continued this direction with
       | some sort of functional framework.
       | 
       | Imagine something similar to jquery but this jquery can only
       | directly reference components on your component hierarchy and
       | pass data directly to components (aka manipulate them). Context
       | and state will also live on this jquery like framework and it
       | will be handled in a similar way to how react handles it. While
       | components themselves can wrap other components, and parameters
       | that go into components can ONLY have default values. The
       | components can never dynamically "call" other components with
       | data and actually have anything truly dynamic going on.... only
       | the jquery like framework can do this.
        
         | ianthehenry wrote:
         | Bonsai is a frontend framework that models data as an explicit
         | graph, separate from any "component hierarchy" or DOM
         | structure. State can live anywhere in the application graph,
         | whether or not it's associated with DOM nodes, and you
         | eliminate all of the "move this state to the parent to share
         | it" ceremony by just having "components" return their views and
         | "outputs" at the same time (if they want).
         | 
         | It's pretty great and hard to imagine going back to a React-
         | like component hierarchy.
        
           | ninetyninenine wrote:
           | Oh nice, it's ML style, like elm.
        
         | whstl wrote:
         | IMO/IME these problems have more to do with program
         | organization rather than with any individual architecture.
         | 
         | To avoid it, funny enough, you have to take cues from
         | functional programming, and you need strong, composable,
         | primitives with succint interfaces (the opposite of shadcn).
         | Even for visually combining and placing components, you need
         | stateless layout components [1] that don't depend on anything
         | and just render children a certain way. This way it's possible
         | to have a very flat component hierarchy. The entire state-logic
         | at the top-level doesn't hurt much anymore. Also, just
         | props+events are enough, no need for Context, Redux or other
         | tricks.
         | 
         | But if you go the "Clean Code" route and the main reason to
         | have components is so so they're not too big, then you get deep
         | hierarchies, prop-drilling becomes a big problem, and you need
         | Context or state libraries specifically for inter-component
         | communication.
         | 
         | This is a problem that I've seen come up time and time again
         | not only in Frontend but also in desktop apps and in video
         | games. And backends often have the luxury of having the entire
         | state in the database, so it doesn't happen as often.
         | 
         | Of course the side effect of this is that you will end up with
         | bigger components, and you need _better_ abstractions, but IMO
         | this is a small price to pay for having code that is easier to
         | work with and doesn 't need special ways for handling the data.
         | Also this method tends to work better in bigger apps and people
         | complain it's wasteful in smaller apps, so there's that too.
         | 
         | [1] In the design world this is often called Templates.
         | https://atomicdesign.bradfrost.com/chapter-2/#templates It's
         | interesting how this didn't catch among frontend devs. I
         | remember "layouts" being a big part of WPF for example.
        
           | ninetyninenine wrote:
           | hard disagree.
           | 
           | With prop drilling how do you get the setter methods into C3?
           | You have to prop drill all the way down.
           | 
           | Let's say I add a new component under C3 that has a side
           | effect in some sister hierarchy under B. Then now suddenly in
           | between and B and C3 and the other component I have to modify
           | EVERYTHING to take that new change into account and these
           | components now all have an extra prop that they don't
           | intrinsically need but they keep in order to account for C3.
           | 
           | Because data is so intrinsically linked with components Every
           | component between B and C3 now needs to be modified to prop
           | drill when previously it wasn't needed.
        
         | em-bee wrote:
         | that's because you are using react where every html element
         | that does something dynamic is its own component.
         | 
         | when i use aurelia, then the whole page is one component and
         | dynamic functionality in elements is achieved through bindings
         | and functions that all share the data in the component. you can
         | include other components, but you only do that where needed,
         | and then passing data becomes a lot easier.
        
         | myguysi wrote:
         | > Really... how data flows through your program is actually a
         | separate graph structure, and how HTML elements are organized
         | in your program is another separate graph structure we try to
         | graft into the first one and that creates a mess.
         | 
         | My team migrated away from Redux and for over a year I've been
         | unable to pinpoint why I've been longing for it again. This has
         | hit the nail on the head for me. Redux (and other "global"
         | state management solutions) allowed me to decouple the data
         | graph from the UI graph. When a UI event is triggered, an
         | action is dispatched and then the data graph takes over. This
         | makes the UI graph extremely simple - render UI and dispatch
         | actions - but these days we're mixing state with business
         | logic, event handling, API calls, rendering UI, styling, etc.
         | This is very much a problem of our own making that could be
         | solved by a different architecture, but yeah... thanks for
         | clarifying this feeling for me.
        
       | gedy wrote:
       | I don't disagree with the idea that people can be a little kooky
       | about FP, but the idea that webapps are perfectly fine without
       | modern front end approaches is a bit exaggerated. Managing UI
       | state is much easier in the client - sure, if you don't have a
       | stateful UI to begin with don't go build some JS SPA. But I've
       | have been there done that with teams and companies that dislike
       | JS then try to fake UI state back and forth from server to
       | client, and it really sucks, overcomplicates stuff that should be
       | simple.
        
       | AstroBen wrote:
       | A lot of these are implementation details and not necessary for
       | the abstraction to work. Preact doesn't use a synthetic event
       | system for example
        
         | paulryanrogers wrote:
         | Is that true even when you want to use Preact without class
         | based components?
        
       | ludicrousdispla wrote:
       | Something about web development really does seem to break a
       | person's ability to design/architect a proper event-driven, data-
       | oriented UI.
        
         | marginalia_nu wrote:
         | I suspect there's a class of problems, front end development is
         | one, ORM is another; where the problem itself is constrained in
         | such a way that only shitty solutions exist.
         | 
         | ORM keeps sucking because RDBMSes simply don't operate on
         | objects. You can either impose ill conceived object models on
         | the database, or try and fail to capture the database's
         | affordances in objects.
         | 
         | I don't have a theory on what's gone wrong with front-end
         | development to cause its chronic disease, but it may simply be
         | that HTML is a document markup language, and makes a
         | questionable base for a user interface.
        
           | taffer wrote:
           | > HTML is a document markup language
           | 
           | No it is a _hypertext_ [1] markup language and it doesn 't
           | suck if you actually use it as such.
           | 
           | The problem is that we decided that <a> and <form> tags
           | should be the only hypercontrols, only triggered by clicking
           | on them. However, libraries like HTMX and Unpoly enhance HTML
           | so that every element can act as a hypercontrol, responding
           | to all kinds of events. This allows you to implement
           | interactive features such as autocompletion, form validation
           | and infinite scrolling without writing a single line of
           | JavaScript.
           | 
           | > ORM keeps sucking because RDBMSes simply don't operate on
           | objects
           | 
           | Have you read [2]? Modern SQL can return nested JSON. No ORM
           | needed.
           | 
           | [1] https://htmx.org/essays/how-did-rest-come-to-mean-the-
           | opposi...
           | 
           | [2] https://www.scattered-thoughts.net/writing/sql-needed-
           | struct...
        
           | marcosdumay wrote:
           | The name for those is "wicked problem". They usually appear
           | when your problem statement is itself incoherent.
           | 
           | The entire thing about users interacting with data through
           | computers is one of them. There are several inconsistent
           | goals, like consistency is at odds with flexibility, and
           | accessibility is at odds with security.
           | 
           | We have those tools that push the incoherence around, but
           | they are always prone to collide somewhere.
        
         | knallfrosch wrote:
         | UI would be easy if its data wasn't just a cache.
        
       | morcus wrote:
       | This article started out interesting and then there were a series
       | of baffling claims that... didn't quite make sense to me and
       | feels like they are just trying to set up a straw man.
       | 
       | 1. The author complains that React devs don't understand
       | addEventListener when it is used and required reasonably often as
       | far as I have seen?
       | 
       | Also, "Again: the web had this. The browser's event system is
       | fast, flexible, and well-understood. But it wasn't controlled
       | enough for the FP ideal of a closed system."
       | 
       | The stated purpose of the synthetic event system was to normalize
       | differences in browser behavior back when React was created. It's
       | not as necessary these days because browsers have gotten better,
       | but saying it's about "FP Idealism" seems off.
       | 
       | 2. The author complains about re-inventing the <dialog> element.
       | This is valid, and new code should obviously use it. That said,
       | it only became available across all major browsers in March of
       | 2022, and still isn't supported by some minor browsers.
       | 
       | All of the popular component libraries were made before that, and
       | thus ought to keep their JS implementation for backwards compat.
       | 
       | As far as tutorials, when I search "React dialog tutorial" the
       | first result regrettably does show how to build your own, but the
       | next two focus on using the built in element.
       | 
       | 3. Then the author turns to customized select, and complains that
       | JS frameworks don't support them. This would be valid but the
       | very MDN article they link literally starts with:
       | 
       | > This article explains how to create fully-customized <select>
       | elements using *experimental browser features*
       | 
       | (emphasis mine)
        
         | reactordev wrote:
         | I can see from a new developer point of view, their
         | frustration. Why aren't things standard? Why not use builtin
         | tags? Why this or that?
         | 
         | Valid questions we should all be asking. Sometimes, just
         | because "that's the way it was" doesn't mean that's the way it
         | should be. Often times I find myself _deleting_ code that is
         | now more readily available as either part of the platform I'm
         | on or part of the framework I'm using.
         | 
         | Your points are valid too, that they don't know about the
         | history that got us here and why it is the way it is but
         | nevertheless we should all be asking ourselves daily, "do we
         | still need this?" and trim the fat.
        
           | totallykvothe wrote:
           | That's not what the article was about though. It wasn't only
           | a complaint about not using built in niceties of the
           | platform. It was an assertion that the reason we aren't is
           | because of some kind of functional bro boogeyman.
        
         | fleebee wrote:
         | > That said, it only because available across all major
         | browsers in March of 2022, and still isn't supported by some
         | minor browsers.
         | 
         | `<dialog>` only got full compatibility with Firefox about two
         | months ago with Firefox 141. Safari still doesn't support
         | `closedby`.
         | 
         | Given that, I still regard `<dialog>` as experimental, and
         | that'll remain the case as long as the "Baseline Widely
         | available" label comes with an asterisk.
        
         | hungryhobbit wrote:
         | It only became obvious at the end that the whole (WAY too long)
         | article was just a giant troll to promote the author's personal
         | pet technology (HTMLX). But it was a highly disingenuous one,
         | because (as the poster above noted) it was giant straw man, not
         | a legit critique.
         | 
         | I felt cheated just by having read the article: I'm all for a
         | long and winding article that has something to say, but this
         | one was telling a bad joke for WAY, WAY too many paragraphs.
        
           | rs186 wrote:
           | The article does not go into the disadvantages of server-side
           | rendering (or more specifically, fetching html from server).
           | I am sure the author is well aware of the choice between
           | client- and server-side rendering but skipped it and seems to
           | present technology like htmlx as "solutions" to all the
           | problems the article mentioned which is quite a stretch.
        
         | librasteve wrote:
         | I spent the whole time thinking "yeah, we need HTMX" - took a
         | long time to get there eventually.
        
         | troupo wrote:
         | > That said, it only became available across all major browsers
         | in March of 2022, and still isn't supported by some minor
         | browsers.
         | 
         | And the only reason it suddenly reappeared in 2022 was because
         | browsers want to get rid of alert/prompt dialogs.
         | 
         | The spec was (and probably still is) so riddled with issues
         | that it never went anywhere for 10 or so years, and Chrome at
         | one point argued it should be removed.
         | 
         | > This would be valid but the very MDN article they link
         | literally starts with
         | 
         | People involved with HTMX play really fast and lose with
         | anything that doesn't fit their conclusions hoping no one will
         | call them out.
        
       | didibus wrote:
       | What I'm curious is why the platforms don't adapt to how the
       | developers have found works best?
       | 
       | The developers look for ergonomics in maintaining the code base,
       | that can scale to larger team and websites.
       | 
       | This requires a lot of customers JS framework code to offer, but
       | in a sense, it's because the platform doesn't natively support it
       | no.
       | 
       | Would there be ways to evolve the web platform to better align
       | with the React style for example?
        
         | edoceo wrote:
         | WebComponents?
        
           | troupo wrote:
           | Web Components are not anywhere near to any requirements
           | people had, have, or will have.
           | 
           | That's why they went from "you won't need React" to "good for
           | leaf components maybe" to "maybe use HTML web components
           | maybe?"
        
         | aardvark179 wrote:
         | There are often a couple of barriers to this.
         | 
         | Firstly, you can't break what is already there, so any
         | evolution of the general platform often has to make wider
         | guarantees than a single framework.
         | 
         | Adopting ideas from any single framework too quickly may put
         | you in a worse position. A framework can evolve and choose when
         | to break compatibility, a language or platform standard has a
         | tougher job in that regard.
         | 
         | Some things that front end frameworks have settled on are now
         | being looked at for standardisation, but I'm personally still
         | wary about changing something like the ecmascript for. It would
         | be an easier call if there were a standard library which simply
         | needed an implementation, but we aren't quite there yet.
        
         | jt2190 wrote:
         | > What I'm curious is why the platforms don't adapt to how the
         | developers have found works best?
         | 
         | Here's my take:
         | 
         | - The web was visualized as a way to publish academic documents
         | in a hyperlinked document system. Librarians and academics live
         | in this world. We hear the word "semantic" from them a lot.
         | 
         | - The _visual_ web was visualized as a way to publish documents
         | that had a precise look. Graphic designers live in this world.
         | They don 't care about semantics. They do care about pixel
         | perfect layouts and cool effects.
         | 
         | - The web app was visualized as a way to deliver software to
         | users with lazy, "click link to install"-like behavior. What
         | this crowd cares about is providing server functionality to
         | users, and other concerns like semantics or pixel perfect are
         | often secondary.
         | 
         | - The single page web app is also visualized as as a way to
         | deliver software to users with lazy, "click link to
         | install"-like behavior. They differ from the web app group in
         | that they try to have more server functionality right in the
         | client. Again semantics and pixel perfect are secondary. App
         | complexity is a big problem that this group contends with, and
         | this is what the article discusses.
         | 
         | Given these different ways of visualizing the web (and I'm sure
         | I've left a few out), it's no wonder that we're stuck with the
         | mess that is today's web development. The right solution is a
         | sensible runtime for app development, that doesn't force you to
         | render UI through the DOM and doesn't make it hard for you to
         | get access to basic things like the local file system. We've
         | known this forever (anyone remember Flash?).
         | 
         | WASM _feels_ like it might finally allow app developers to do
         | all of the software things that native platform developers get
         | to do easily, and with the added bonus of strong sandboxing. It
         | 's early days yet, I think the "Ruby on Rails"-moment has not
         | yet arrived there yet, i.e. a very popular, easy way for devs
         | to create whatever app-de-jour everyone's excited about.
        
           | w10-1 wrote:
           | > WASM feels like it might finally ...
           | 
           | But WASM is weirdly allergic to the DOM and to javascript.
           | The core, fundamental interfaces are terrible and highly
           | disputed, so it will be restricted to mainly-WASM apps for
           | some time.
        
             | jt2190 wrote:
             | That's only a problem if your goal is to keep on doing the
             | same old web apps the same old way, just delegating part of
             | the program logic to WASM which, I agree, will be more
             | complicated. But if you're going to use WASM why limit
             | yourself to using the DOM and JavaScript? Why not use a
             | programming environment that lets you use more
             | sophisticated tools?
        
         | troupo wrote:
         | > What I'm curious is why the platforms don't adapt to how the
         | developers have found works best?
         | 
         | Because standards committees are also made out of people. They
         | have their own agendas, experiences, biases, company loyalties
         | etc.
         | 
         | And in the past ten or more years _all_ standards have been
         | taken over by a very small number of _very_ prolific people
         | from Google. Prolific as in: writing dozens and hundreds of
         | specs and having their fingers in all standards.
        
       | chrisallick wrote:
       | more like ruined it
        
       | joduplessis wrote:
       | No offense intended to the author, but this is the most bizarre
       | list of points.
       | 
       | I also realise how weird it must be writing a personal blog
       | article and then have random internet-folk dissecting it. Hope
       | this doesn't dissuade any future articles.
        
       | prinny_ wrote:
       | I am a FE developer and I believe that we collectively have a
       | loser's mentality when dealing with CSS.
       | 
       | In my mind, SCSS + CSS modules + maybe a processor tool is an
       | rock solid and modern set of tech that produces excellent results
       | and most importantly moves styling off the main thread. It makes
       | sense to use it, but we don't. FE interviews even for senior+
       | roles are JS/React/system design questions. Nothing about CSS and
       | I get it. Why interview for something you don't use internally?
       | 
       | I recently read something that stuck with me, which was about
       | micro front ends but I think applies in more cases than this: "it
       | doesn't solve a technical problem but an organizational one".
       | 
       | There was an excellent reddit discussion on the pros and cons of
       | tailwind and it boiled down to "it's really hard to enforce CSS
       | guidelines for teams of multiple people". Tech leads didn't want
       | to monitor how 10 or 20 or 50+ different FE developers wrote CSS
       | and opted for tailwind so that everyone wrote the same, even if
       | that meant multiple inline classes pasted on each element. I find
       | this reluctance to enforcing guidelines weird, considering at
       | $WORK we have multiple confluence pages and internal documents
       | about React and Javascript guidelines and I have seen similar
       | documents in previous work places. Would it be really different
       | to apply the same mental paradigm for CSS?
       | 
       | Of course, all this is under the hindsight knowledge that HTML
       | and CSS have evolved in recent years to be truly powerful and
       | versatile. I get the technical decision to go all in on JSS and
       | React 5 years ago. I don't now.
        
         | Tade0 wrote:
         | I share this sentiment.
         | 
         | CSS modules are really enough - there's no need to overthink it
         | any further.
         | 
         | I'm currently in a project where my first task, spanning
         | several months, was to clean up after the previous guy. The
         | main issues in styling were misguided attempts at sharing
         | styles implemented via breaking encapsulation.
        
         | zelphirkalt wrote:
         | It seems to me, that many FE devs don't even know CSS these
         | days. Rather just tack on some "ready" made component found on
         | NPM or some component library. When it actually comes to using
         | CSS to fix something about part of a page or part of a
         | component, I often see non-responsive ways of doing that, badly
         | tested across browsers, breaking at some width of the viewport,
         | etc.
         | 
         | In my view CSS is essential. Not knowing CSS at least somewhat
         | well is a huge obstacle in producing high quality frontend
         | work. It's like being a carpenter, but simply not knowing one
         | important aspect of wood, or not being able to use a specific
         | tool to work with wood, lets say a tool to smooth surfaces. CSS
         | is part of the medium you work with as a FE engineer. It is
         | unfathomable to me, how a FE engineer can not know this stuff
         | well. If some FE engineer is reading this, and feels some
         | impostor syndrome: Yes, if you don't know your medium and tools
         | as least in the basics, then you should feel like an impostor.
         | 
         | I see broken responsiveness very often. Of course in almost all
         | websites, that rely on JS to display what is essentially a
         | bunch of static texts.
         | 
         | If I was interviewing for a FE position, and really had to go
         | through the circus of asking interviewees code questions, I
         | would definitely include a minimum of CSS knowledge there.
         | Basic things like how they would scope their CSS to specific
         | elements or classes of elements and how they would prevent
         | their styling to bleed into other stuff. Or how they would set
         | up a theme with just CSS. Not questions expecting them to write
         | CSS on a whiteboard, of course. Just testing their basic
         | understanding.
        
         | marcosdumay wrote:
         | > I find this reluctance to enforcing guidelines weird
         | 
         | It's worse than that. All the hype in design has been about
         | creating a global design language, and enforcing it over all
         | your teams for more than a decade now. All the hype has been on
         | centralizing the design team, moving it away from the
         | developers for some years. All the hype has been on tools that
         | claim to enable reusing and distributing that work...
         | 
         | And yet everything is done in a way that developers have to do
         | everything themselves and don't get to coordinate with each
         | other.
         | 
         | (Honestly, I'm settling on the opinion that non-developing
         | application design is a scam all around.)
        
         | troupo wrote:
         | > In my mind, SCSS + CSS modules + maybe a processor tool is an
         | rock solid and modern set of tech
         | 
         | "my set of non-standard tools and preprocessors is superior to
         | these guys' non-standard tools and preprocessors" is not a good
         | argument.
         | 
         | > I find this reluctance to enforcing guidelines weird
         | 
         | Because CSS doesn't lend itself to any enforcement. All the
         | tools that appear around it _includng those you like_ like SASS
         | and  "some processing" don't appear because people don't
         | understand something or can't enforce something.
         | 
         | > Of course, all this is under the hindsight knowledge that
         | HTML and CSS have evolved in recent years to be truly powerful
         | and versatile.
         | 
         | Indeed. And many of these features have been made available
         | across all major browsers only in the past two or so years.
         | 
         | No one is going to rewrite everything from SASS or CSS-in-JS
         | just because some features now exist in vanilla CSS.
        
       | gjgtcbkj wrote:
       | Are there seriously devs that think FE code quality actually
       | matters? It's become so standardized and cookie cutter setting up
       | this frameworks to actually work in development and production
       | environments is ten times more difficult then recreating Facebook
       | or Twitter. Who would build there career on this at this point?
        
       | vinceguidry wrote:
       | Great article. I got off the webdev train just as Redux was
       | coming out and never looked back. When my team lead decided to
       | unilaterally replatform the app we maintained from Rails to
       | NodeJS my professional life went from heaven to hell. Gone were
       | the days of finishing our tasks for the week in two days and
       | playing ping pong every day. Insult was added to injury when that
       | team lead left halfway through.
       | 
       | The web had a golden age where it was _understandable_. The
       | browsers ' inconsistencies were mostly ironed out and you had
       | references for what worked where. Flexbox was magic and you had
       | shims to get it working where it wasn't yet supported. Web
       | development was actually fun. When you solved problems, you were
       | actually learning something, not just throwing stuff at the wall.
       | 
       | These web platforms gradually threw all that out. If you're a new
       | engineer, realize that platform knowledge isn't real knowledge.
       | Knowing React really well isn't a thing you can build a lasting
       | career on. Your job is your job, but your education is your
       | responsibility. If you don't want to be locked into an ecosystem,
       | make sure you are constantly learning fundamentals.
        
       | toastal wrote:
       | These are things to be critical of after post-React in the
       | explosion of complexity, but I don't think this is FP's fault. I
       | did a lot of FP front-end in the actual FP languages--not
       | languages cosplying FP with JS or TS--& these communities (Elm,
       | PureScript, followed js_of_ocaml, Reason, & the things Haskell
       | was trying at the time) were not jumping on these same bandwagons
       | of complexity but hoping to wrangle in some of it, usually
       | focused on how the view should be a declarative representation of
       | the state while pushing side-effects to the edges. There wasn't
       | talks of making CSS too complex, hydration, et. al. That JS/TS
       | crowd however...
        
       | breadwinner wrote:
       | > Combined with React Hooks (which replaced stateful classes with
       | functional composition), the ecosystem shifted decisively toward
       | FP.
       | 
       | React is the farthest thing from functional, see here:
       | https://mckoder.medium.com/why-react-is-not-functional-b1ed1...
       | 
       | Composition in React Hooks is closer to multiple inheritance in
       | C++ (because it combines state and behavior from multiple
       | components) than functional programming.
        
       | smrtinsert wrote:
       | This is a very incorrect conclusion. Nothing about jquery
       | prevented functional purity. If that's what you wanted, use it as
       | such. Jquery just made browser differences much less of an issue
       | and wrapped it in a nice way. The modern react stack is exactly
       | what all the fp snobs raged against and they weren't wrong about
       | it. Its been said before, there was jsf before react. Both are
       | bad ideas. React has terrible performance is extremely
       | heavyweight and ridiculous for what its used for. There's a
       | reason there's a revolt nearly daily.
       | 
       | To me the major failing here was people over investing in faang
       | thought leadership. Still haven't ever used react angular etc in
       | a major project and gone wow this is great. JQuery got a lot
       | closer. There were many other ideas coming forward around the
       | time those frameworks came up, it was a fertileperiod for
       | frontend. Sounds like we should cycle back.
        
       | w10-1 wrote:
       | Other commenters are criticizing details, but I really appreciate
       | the OP trying to see the entire landscape. I agree with other
       | commenters that ownership over code is a primary driver (at least
       | for CSS style vs. javascript interaction).
       | 
       | Leaving aside details, it seems clear the javascript frameworks
       | were ahead of the platform and had the perverse incentive of
       | staying that way, which also took the pressure off browser
       | developers (already slowed by inter/standards politics),
       | resulting in a long historical period of dissonance.
       | 
       | By comparison, Java bytecode gave Scala and Kotlin instant access
       | to the enterprise, and the JDK team responded with faster cycles
       | and steady but measured incorporation of features, because they
       | realized they needed something to get enterprise off Java 1.8 and
       | into licensable VM's. Progress is slower in the enterprise, but
       | the dissonance seems minimal.
        
       | nielsbot wrote:
       | FTA
       | 
       | > CSS cascades globally by design. Styles defined in one place
       | affect elements everywhere, creating emergent patterns through
       | specificity and inheritance.
       | 
       | I can't be the only person who finds that this makes complex
       | sites a nightmare to design? (Raise your hand if you've had to
       | use `!important`)
        
         | zelphirkalt wrote:
         | You are surely not the only one thinking that, but CSS also
         | provides easy solutions to this problem, namely selectors and
         | CSS classes. Rarely have I had an issue with CSS I wrote
         | accidentally doing things I didn't want. Maybe sometimes here
         | and there I needed to make a selector more specific, but that's
         | not too bad.
        
       | Animats wrote:
       | Towards the end of the posting, it turns out this is a plug for
       | HTMX.[1]
       | 
       | So, is HTMX any good? Do people use it?
       | 
       | The primary mechanism of HTMX seems to be that you click on
       | something, which causes the server to return HTML which is then
       | shoved into the current HTML at the selected point. Is that a
       | good primitive?
       | 
       | [1] https://htmx.org/
        
       | austin-cheney wrote:
       | I get the impression from the article the author may have meant
       | declarative instead of functional programming. FP can be fully
       | imperative. I often see developers interchange these terms
       | improperly because there is some implicit narrow context that's
       | out of scope to the broader nature of the terms.
        
         | zelphirkalt wrote:
         | Can you give an example for imperative yet functional? Do you
         | mean something like within a function using lots of assignment
         | and such, but keeping the function pure to the outside?
        
       ___________________________________________________________________
       (page generated 2025-10-04 23:01 UTC)