Hacker Newsnew | past | comments | ask | show | jobs | submit | nohuhu's commentslogin

> The better ones are often tied to company-specific frameworks.

That is because to implement accessibility in a grid/tree widget to a meaningful level, you need a lot of underlying code. Even in modern browsers. Source: implemented accessibility in Ext JS framework.

One of the most often asked questions from users of Ext JS was: hey, can we have the Grid widget without all the bloat? Sure, and ~95% of the framework exists so that the Grid can have its features and work reliably across all the browsers. You can probably do without the rest 5%, no biggie.


> it's the only way to go to build products.

This! Back-to-front is a good way to build a scalable, performant, cleanly designed software. Front-to-back is the only viable way to build a usable product.

> Users just do not care what kind of horrible kludge is running behind the slick UI.

For 99.9(9)% of users, the UI is the product. Even those who do know what "back end" means, do not care.


One viable alternative for thunks and sagas that I came up with is using async functions and explicitly getting/setting state: https://github.com/riptano/statium#viewcontroller

Still a long list of chores to improve API, tooling, etc but very performant and battle tested.


If that works with your model of the world that's great. Wouldn't kick it out of bed for farting.

For me, the easiest way to handle async and effects in Redux is to write custom middleware for each context/entity. That's what it's for. It makes it possible to have a real message based architecture without hacks and (extra) libraries.


> If that works with your model of the world that's great. Wouldn't kick it out of bed for farting.

Oh I see, entity naming could also be improved. ;)

> For me, the easiest way to handle async and effects in Redux is to write custom middleware for each context/entity.

Right, and you still have to deal with Redux to get there. Not a preferred choice for many people.

> have a real message based architecture

What is a real message based architecture, in your terms? And why is it so important? Genuine question.

> without hacks and (extra) libraries.

Extra libraries only if you base on Redux and go from there. It's almost as if Redux itself wasn't an extra library...


Redux is fantastic and it's quite a simple library. The rest is what gets you into trouble.

Hardly anybody has a problem with redux until they have to deal with async actions but all the tutorials use thunks or sagas when the correct way to handle that stuff is to write middlware.

By real messaging I mean CQRS with event mapping/filtering/normalization.


> Redux is fantastic and it's quite a simple library.

... and it's an extra library. You can do without it in React, you know.

> The rest is what gets you into trouble.

Exactly. My biggest beef with Redux (and React, too) has always been that it makes much pomp about things that are relatively easy to solve, like state computation (or rendering). The actually hard things are left unsolved to a various degree, and that is what devs struggle with the most. Things like: how do I take the business logic best expressed in imperative statements (get foo, if it equals to bar, do that, if not, do something else), and express it in React component state transitions, with loading state indication, error handling, and conditional branching?

The most contrived React code I've ever seen was dealing exactly with that: fitting a finite state machine into a React component, which Redux is essentially zero help with. Why do I need Redux if it doesn't solve the hard problems for me?

> Hardly anybody has a problem with redux until they have to deal with async actions

Srsly? So tons of boilerplate, action at a distance as a blessed pattern, reliance on globals, contrived testing, and perf issues are not problems at all?

> the correct way to handle that stuff is to write middlware.

There are as many correct ways to handle that stuff as there are developers. Some ways are just easier to read and follow (also to test, maintain, etc etc).

> By real messaging I mean CQRS with event mapping/filtering/normalization.

Thanks for the explanation. You forgot to answer the second part of my question, which is: why this is important for a front end application. Again no sarcasm, just genuine interest.


I didn’t forget to answer anything, you are just treating this like a debate. While I understand why, it would do you some good to be more humble. You’re pretty junior and you still have a lot to learn.


Thanks for submission, a really interesting read! I'm into restoring old woodworking machinery, and hand scraping is one of the methods for truing lathe ways that I've read about. Could possibly be required for the Walker-Turner lathe I'm working on. :)


Also a woodworker here. I have to ask: how bad are the ways on this lathe and how could they get worn? Moving the banjo and tailstock on a wood lathe shouldn't wear the ways the way the routine use of a metal lathe wears the ways.


I haven't gotten to measuring wear on the ways yet, don't think I'll need to scrape them but that's a possibility. This is a pet project of mine, a barn find that was in a pretty bad shape when I got it: rusty, crusty, with missing parts and undesirable modifications by previous owners. Specifically the ways are pitted from rust; worse in places that were exposed to the elements. I'll have to try and measure the effect of this pitting on tailstock positioning. I don't think banjo positioning is going to be affected, the ways are not that bad. But then there's always the obsession with perfection, so who knows. :)

I have a soft spot for pre-1950 Walker-Turner machinery, their aestetics are off the charts; I'm trying to restore this lathe to its former glory, or even better. Not quite a classic car showroom condition but as close to it as I can get without spending a fortune in time and money. :)

The current stage is painting; turned out it's pretty tricky to spray glossy enamel so it would level out smooth! Especially in our cool and humid coastal climate, paint takes a while to dry and even longer to fully cure so the process is quite challenging. Not to mention the countless hours it took to grind out casting imperfections, apply bondo filler, sand it, etc etc.

I thought I was getting into woodworking but found that restoring machinery is lots of fun in its own right, and nothing compares to the satisfaction of using a well made and beautifully restored vintage tool. Especially when I'm the one who did the restoration. :)


Ah, I hadn't thought of rust. Good call. My experience with the tops of my table saw and band saw is that as long as they were ground pretty smooth originally, they don't really pit and I can scrape the superficial rust off and have a pretty good surface. They were, however, stored inside-ish. I could see a barn find in bad shape suffering a lot more than that.

I love the look of the old W-T stuff too, but I've somehow become a Delta man for the stationary tools, probably because of the ubiquity of their old stuff. None of mine is old enough to have the really nice castings. My Unisaw is from '78, and it has the sheet metal base rather than the old cast one. My 14" band saw is (I think) pre-war, but the original buyer didn't spring for the cast art-deco base :-(

Do you have pictures or a build thread on this project? I'd love to see it. And kudos to you for doing the paint and cosmetic stuff. There is nothing I hate more than doing paint.

My Unisaw is covered in years of (somebody else's) overspray. I've stripped it off the chromed fence rails because it was interfering with it working, but the cabinet? Screw it. I can live with it. My 14" drill press, however was flaking off (somebody else's) 3 or more poorly applied coats onto me and anything I drilled. I stripped and repainted that, but that's how bad it has to be for me to entertain painting. The paint job is not what anybody would call flawless, but at least it isn't coming off :-D


> I could see a barn find in bad shape suffering a lot more than that.

Yeah well, in between being a bottom feeder and looking for fun, machines usually come to me as project pieces rather than usable tools. :) I'd never opted to restore any of these rust buckets if I'd depend on them to do woodworking for a living; that said, the purpose of a hobby is to occupy my mind and give me a challenge that is rarely encountered in my day job anymore. So, the rustier, the better. :)

> I've somehow become a Delta man for the stationary tools, probably because of the ubiquity of their old stuff.

I can definitely relate to that, W-T makes a minority of my resto projects. Most of them are Delta as well, as I'm looking to build myself a fully equipped vintage woodworking shop. I'm almost there in fact, as several projects are nearing the assembly stage: a '64 Unisaw, a '52 HD Shaper (going in tandem with the Unisaw), a '54 14" bandsaw, a '60 combo sander, a mid-50s LD shaper, and a '42 6" jointer that I got for free in a total rust-bucket condition. That one was a challenge in itself, especially the motor.

It's just Walker-Turner machines are so beautiful, they're special. Next up after the lathe is a 1939 16" bandsaw, the final quest machine that I acquired last fall. I'll have to fight scope creep real hard on that one...

> My 14" band saw is (I think) pre-war, but the original buyer didn't spring for the cast art-deco base :-(

Ye shall seek and ye shall find, if you want to. :) Besides trawling your local Craigslist (that's where I find my projects), sign up on http://www.owwm.org and post an ad in BOYD forum. Cast iron bases do come up for sale somewhat regularly. Beware that even looking at that website is very dangerous, slippery slope ahoy. ;)

> Do you have pictures or a build thread on this project? I'd love to see it.

I don't usually take pics of the resto projects... I guess I'm just lazy. If you're into vintage tool porn, check out the OWWM community I linked above, and its sister site http://vintagemachinery.org. Lots of drool inducing pics there, I really cannot add anything that hasn't been done already. :)

> The paint job is not what anybody would call flawless, but at least it isn't coming off :-D

That's usually enough for many cases... If a machine doesn't have a sentimental value, why, just refurbing it to acceptable mechanical condition is par for the course. That's what I did with my current set of machines; no offense to Grizzly but their utilitarian cabinet saw aestetics do not really justify the amount of work that goes into stripping and repainting. A vintage Unisaw, on the other hand... I had to learn how to do cabinet scale electrolysis derusting, some basic metalworking, spray painting techniques, not to mention mechanical and electrical challenges. Heaps of fun! :)

Checked out your website... Wow. I have a long, long way ahead to that kind of woodworking projects. ;)


Oh dear, another OWWM'er on HN :-) I lurk, but I mostly try to avoid that rabbit hole unless I'm trying to solve a specific problem. Turns out, I waste enough time on the internet already without drooling over the work people do there restoring old machines to better-than-new condition. Seriously, some of those folks are nuts (as you well know).

It sounds like you've got a nice shop going. I'm a little jealous. My stationary tools are actually stashed in a literal barn right now because I no longer have a basement to put a shop in. I work out of a makerspace, but that's closed due to present conditions, so I moved my bench into my living room. I gave in and fetched my band saw, and it's now sitting on my covered porch. And I have no blades for it at the moment. I'm getting a lot of exercise milling lumber entirely by hand. Honestly, my arms are going to fall off (or get huge) if the lockdown continues much longer.

I'm with you on the modern tools, by the way. On the vintage stuff, a lot of companies really took pride in their industrial design (as you well know). And even the totally utilitarian stuff has stylistic variation between manufacturers. The only difference between Grizzly and current Powermatic tools is the color of the paint. I remain hopeful that Festool having proved that there's a market for higher-priced tools means that somebody will start making nice stationary tools again.

That's probably a lot to hope for, though I recently discovered that Northfield is still chugging along and so is Tannewitz. They're out of my price range for the time being, but I hope they survive long enough for my price range to intersect their prices! It's a real pity that Oliver is now yet another nameplate on the same castings from overseas. The school I went to has a vintage 166 jointer and a 399 planer that I'm in love with.

> Checked out your website... Wow. I have a long, long way ahead to that kind of woodworking projects. ;)

Thanks! I'm a long way from making actual money at this. I'm lucky to be married to somebody very supportive. We'll see how the economy does. I have a couple of paid projects that appear to be holding, and we'll see where things go from there. I guess there's always software to go back to?


One way lathe ways get worn is if the user uses an abrasive wheel to grind without covering and cleaning the ways.


The worst thing is neglect, rust, and accidental damage. In low volume use, e.g. proto shop or home shop, the ways should be virtually eternal. Keep them covered, clean and oiled.


> Funny, I usually see type haters claiming that they don't actually make the kinds of mistakes that are fixed by strong typing.

As your typical type hater, my preferred argument is: yes, static typing prevents a certain class of bugs from happening; no, this class of bugs is not nearly as relevant as type lovers seem to be claiming. By an order of magnitude if not more.

Source: 6 years of being a core developer of a front end framework consisting of 1,500,000 lines of ES5 JavaScript and SASS.


I'm sure that class of bugs is relevant for Typescript programmers, because they never develop the skills to not implement those bugs in the first place.

If your usual workflow is to defer all of the typing information to the IDE, rather than keeping it in your head. Then the second you can't access that information at a whim, you're fucked. It's like how I can't navigate around my city without Google Maps, because I've never had much of a reason to.

That metaphor works well, because Google Maps is probably a net positive. It's just that if I go around waving my phone in the face of a 60 year old cab driver that knows where everything is, going "I can't understand how you think you can get around without GPS, you're making loads of mistakes without realising it", I'm going to look like a fucking moron.


> If your usual workflow is to defer all of the typing information to the IDE, rather than keeping it in your head. Then the second you can't access that information at a whim, you're fucked.

This is just not at all how it works in practice. You still keep it all in your head, but the compiler errors protect you from small mistakes.

No matter how great of a programmer you are, you will make transcription errors with the things you have in your head. This is literally exactly the type of "I don't make mistakes" nonsense that I said was common, and a bunch of other people said was extreme and a strawman.


Your argument is the one that's a strawman. You're assuming that the kind of mistakes that I make while coding are the exact kind that Typescript prevents. Which is not the case.

There's more ways than type hints to fail fast. I'm not saying me and all the other JS devs don't make mistakes. I'm saying the mistakes we make are ones that we catch in 5 seconds because the modern web dev environment is set up to facilitate that. Typescript devs make additional mistakes on top of that beacuse they have tools that catch those mistakes quickly too. We don't, so we get conditioned to program in a way to prioritise not making those mistakes (possibly at the expense of other mistakes becoming more common).

The point is that someone with years of JS experience is going to be more productive with JS, and someone with years of TS experience is going to be more productive with TS. I'm not saying Typescript sucks, just that the cost side of it's cost/benefit equation isn't the same for every dev, whereas your shit argument assumes that it is because you only base it on your own experience.


> You still keep it all in your head, but the compiler errors protect you from small mistakes.

It is interesting how "protecting from small mistakes" is touted as "solving our API woes", innit?

At some point it is liberating to admit that static vs dynamic is a matter of personal preference and nothing more. If I like it, I will find a thousand reasons to justify it, and vice versa.

I just wish everybody would be open about it: I like "type safety" and the warm fuzzy feeling it gives me, and nothing you unwashed heathens can say about tight coupling, increased incidental complexity, over-engineered APIs and productivity loss can sway my opinion! Why, my productivity is _increased_ with static typing, because I make up for hours of bikeshedding about which type better conveys the underlying intent with writing less null checks and unit tests! Take that, type haters!

Meh, wishful thinking.


> I'm sure that class of bugs is relevant for Typescript programmers, because they never develop the skills to not implement those bugs in the first place.

This rings true, especially given that in my experience, most of the static typed people either never worked with dynamic languages at all, or converted from dynamic to static. Most of the dynamic minded people I know actually converted _from_ static typing after doing that for years (myself included).

The calculus is pretty simple IMO: if one has mental discipline to work with a dynamic weakly typed language, not having to mess with types and compilers is downright liberating: ye godz, just gimme that data! On the other hand the people who never experienced conditions leading to developing said mental discipline tend to abhor the idea of not having the "type safety" (cute marketing, that). Hence the chasm between Lisp crowd and Haskell mob, with JavaScript being the perpetual battleground somewhere in between.


I'm having a hard time picturing a 1.5M LOC front end Javascript framework. Can you tell us more?


Ext JS is the framework in question. The last time I worked on it (Oct 2018), it was about that size shared between two major versions: Classic toolkit and Modern toolkit, including tests and examples. It could be more than that now but I haven't touched it since.

I used to do a lot of things on it, including _very_ deep refactorings with sweeping changes across the codebase. The secret sauce is focus on automated testing: when I left the company, we had ~70,000 test specs for the framework, and the test suite was executed on each commit to every PR pushed to Github. Depending on framework version (there were several in flight), and browser matrix (15+ supported browsers), each test run yielded 500,000-700,000 spec results (and finished in under 20 minutes).

There was a lot of custom tooling around this, of course. Including a test runner that I got open sourced right before leaving the company: https://github.com/sencha/jazzman. Sadly it looks like there were no new commits since I left; I hoped to pick it up later but so far I haven't encountered the need to run significantly sized test suites in massively parallel fashion. Nobody writes that many tests. :)

EDIT: I almost forgot that as a condition for open-sourcing the test runner they made me write a blog post about it: https://www.sencha.com/blog/ext-js-testing-story-under-the-h... :)


I would have to assume GP used "framework" differently than you understood it. They may have meant "foundational code of an app".


A framework is usually the foundational code for an app, for sure. In this case it was a bona fide JavaScript framework, Ext JS.

It is that big because it implements a lot of things that other frameworks don't even try to try thinking about, things mostly used to build very boring line of business applications (think thousands of forms, huge grids, reports with charts, etc). Applications built with Ext JS can easily dwarf the framework itself; the biggest I've seen personally was ~30 mb of minified ES5 JavaScript.

...and it worked in IE8, BTW. :)


Not my blog but I find it fascinating: https://technicshistory.com

Really surprised nobody mentioned it yet...


When people ask me what my wife does for a living, I tell them she's working as a full time mom to our 4 kids. She likes that a lot more than being a "housewife". :)


This makes total sense to me. If you can solve the hardest problems, it is reasonable to expect that you can solve the rest as well. If you fail at solving the hardest problems, the system will not work anyway.

The science, then, lies in identifying the hardest problems. The art lies in identifying people who can solve these problems.


So I guess this is how living in the 1960s felt like? :)


This is what Statium and Urlito are for:

    import ViewModel from 'statium';
    import stateToUri from 'urlito';

    const defaultState = {
        foo: 'bar',
        qux: {
            time: Date.now(),
        },
    };

    const [getStateFromUri, setStateToUri] = stateToUri(defaultState, [
        'foo',
        {
            key: 'qux.time',
            uriKey: 'time',
            fromUri: time => parseInt(time, 10),
            toUri: time => String(time),
        },
    });

    const Component = () => (
        <ViewModel initialState={getStateFromUri}
            observeStateChange={setStateToUri}>

            {/* ... */}
        </ViewModel>
    );


I'm not familiar with either of them, but that seems like a lot more code!

How does changing the URL trigger a state change? Does the whole page need to reload?

In my system, my "Reader" knows this object so it can just call the regular setState (I also have some mount/umount logic there to avoid leaking memory). This makes back/forward transitions very snappy!

I can also use the same logic for my Server (another "Persistor" [sic]) which indeed uses POST for submitting updates, but responses come down a shared SSE stream (which I need anyway so that users can see eachothers changes in real-time).


> I'm not familiar with either of them, but that seems like a lot more code!

Sorry, I should have been more forthcoming with explanations but got paged at $work. Almost nobody is familiar with Statium yet, it's very new. :) It was developed for cloud applications UI here at DataStax.

Statium implements a very simple key/value storage in a React component called ViewModel. It is using `setState()` internally, so all the usual React rendering logic applies unchanged. Each ViewModel has access to keys of its ancestors, all the way up the chain. There is no global store but a chain of stores instead, which helps to keep state local to consumer components that use it.

Urlito is just a simple library for persisting state to and from URI, currently using query params. This is intended for local component state like selected tab, sort order in a table, or a list of expanded rows in a tree grid, the sort of things that do not deserve full blown URI routing pattern matching. We still use `react-router-dom` for that.

> How does changing the URL trigger a state change? Does the whole page need to reload?

No, it's the usual React logic: when ViewModel renders it will call the function provided in `initialState` prop, which in turn will read the current state of the model from URI query string. Whenever ViewModel state changes, `observeStateChange` function is called, and updates URI to reflect the current model state.

Urlito implements the functions for reading keys/values from URI and writing them back to URI, with support for default values and key filtering.

> In my system, my "Reader" knows this object so it can just call the regular setState (I also have some mount/umount logic there to avoid leaking memory). This makes back/forward transitions very snappy!

Almost the same solution in Statium, except that we have a full blown class based React component to hold the state, and hooks are not used internally (there is a hook based consumer API). The main reason for not using hooks for us is that the values held in `useState` are hard to propagate down the component tree, and hard to test. ViewModel takes care of this easily, with each key available anywhere downstream, e.g. a Component somewhere deep can retrieve the value of the topmost ViewModel without having to access it directly. This helps mightily with testing too: just wrap your tested components with a ViewModel and pass whatever you want to it (including state changes).

No memory leak issues at all, since a ViewModel is simply a React component that outsources `this.setState` for consumer components. :)

Transitions are very snappy with Statium, too. In fact, state updates are lighting fast: value updater function will walk up the ViewModel tree, find the closest owner and set the value in it using `setState`. This will cause the owner ViewModel and its children to re-render, but the render will be automatically scoped to the least amount of components. Since the state is usually localized, the problem of updating the whole app state on a keypress does not apply by default.

> I can also use the same logic for my Server (another "Persistor" [sic]) which indeed uses POST for submitting updates, but responses come down a shared SSE stream (which I need anyway so that users can see eachothers changes in real-time).

Asynchronous logic is hard to handle in synchronous React rendering paradigm... That was the reason for me to come up with a ViewController concept (https://github.com/riptano/statium#viewcontroller), which is the other part of Statium. The idea is to write business logic in a more imperative style, statements not functions:

    const loadUserPosts = async ({ $get, $set }) => {
        let [user, posts, comments] = $get('user', 'posts', 'comments');
    
        if (!posts) {
            await $set({ loading: true });
        
            posts = await loadPosts(user);
        
            await $set({ loading: false, posts });
        }
    
        if (!comments) {
            await $set({ loading: true });
        
            comments = await loadComments(user, posts);
        
            await $set({ loading: false, comments });
        }
    };
Decyphering this: $get is a function that returns ViewModel state values by keys, and $set allows updating these values. This is a matter of personal preference of course, but I think this approach makes the logic much easier to read and understand than Redux thunks or sagas.

There's also the RealWorld example app I came up with for React + Statium, check it out: https://github.com/nohuhu/react-statium-realworld-example-ap.... It's not yet submitted to the official list because I'm stuck trying to come up with a sensible logo for it... :)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: