469 karma · joined September 14, 2017
I find pitching it as a “self funded 20% time project” also helps with the negative perception of laziness. I’ve been using the extra day off to learn VR game development and rock climb.
With the way the market is desperate for senior engineers right now you have a lot of negotiating leverage, and salary above a certain amount is pointless. Can’t take your money with you when you die.
How could Ethereum possibly compete in terms of transaction cost or ease of use with Facebook or some other centralised system.
Blockchain considers secure private key management outside of its threat model which is crazy when you think about it.
The best argument I think I could make in favour of using paper over any electronic voting system is the scalability of an attack.
Generally speaking changing one vote in an electronic system is just as easy as changing a million. Scaling a physical attack against paper ballots is much harder and actually increases the likelihood of getting caught.
Also for blockchain in particular. It solves no problem existing mixed trust voting systems already solve more efficiently.
Most countries birth rate falls off as they become more developed. There’s estimates that the world population will stabilise around 11 billion. I don’t think there’s any theoretical reason why high quality affordable high density housing is impossible.
Most of my peers are either completely priced out of the market, or taking on 40yr or interest only loans. It seems like the market is currently a game of chicken of who’s willing to sign away more of their life. An interest only loan is literally admitting you can’t afford this house and the only hope you ever have of paying it off is if it increases in value without you doing anything.
Here in Australia the government is talking about letting young people access our equivalent of their 401k to afford a deposit on a house. Without changing the supply of housing how is this anything other than another attempt from boomers to steal more wealth from their children so they can line their coffins with more gold.
You should have a core (pure) functional component, that doesn't perform network requests, and an outer component for side effects.
Except when you go to use that container component inside another component. Then you’re back to the same problem. Unless you’re advocating for a single container component at the top level in which case we completely agree! Is there anybody that develops on the frontend professionally fulltime and makes these kinds of complaints?
I do? These are all real problems I've encountered working on large apps at multiple organizations. React hooks are a constant source of difficult to write and non-deterministic tests. Class components also suffer from the same problems. Now after learning about it I'll never go back to class components.
Those aren't the only two options. What I'm advocating for is using react only for pure functional components without the use of any hooks. Hooks are completely isomorphic to class components. Instead of binding the `this` of class methods to an object as a class component would. React hooks maintain basically the same thing in the background and bind it to the values of the hooks, identifying them by call order in your component. Which is why you can't call them conditionally. They're way nicer than class lifecycle methods. Primarily because they organize code that's related together, rather than by when in the lifeCycle it is triggered.IMO state and side effects belong outside of the render functions. Not mixed up inside them. This is exactly what redux, cycles.js, Elm, MVC, etc do.
No idea what this promise chaining thing is that you're talking about.
You know that async await just chains promises together right? e.g. async () => {
await foo();
await bar();
}
() => foo().then(() => bar());
So any callback that makes multiple API calls will require multiple `await wait(0)` in tests to allow for the mocked API calls to resolve before the UI will be finished updating. No idea why you're suggesting Redux has anything to do with hooks. They're completely different.
If you can't see why Redux is related to hooks, I don't know what to say. They're both approaches to managing the impure parts of your UI. I suppose you could continue to insult my experience as a frontend engineer. Hooks are the place to segment out effectful code from otherwise pure code
The effectful code shouldn't even be there. It should live separately from the render / view code to make it easier / faster to test without having to simulate a fake DOM. The average call to `render` takes around 100ms. The tests could be orders of magnitude faster and so much easier to test if people would just keep their business logic and effects seperate from their render code. Does no one remember MVC? You can write global reactions to state changes very easily.
This is exactly the problem, shared mutable state leads to "spooky action at a distance". It results in causal connections between parts of your codebase that are not reflected in the control flow of your code. If you have immutable unidirectional data flow causal relationships between parts of your code base must be reified in the control flow of the language. Most components do not have any async effects.
At least when using Apollo / GraphQL almost every component ends up with async effects.I think this talk by Andre Staltz is the best explanation and solution of the problem https://www.youtube.com/watch?v=SXdtrhn8iII
Mixing stateful effectful code inside what would otherwise be a pure declarative render function leads to so much complexity in an attempt to bridge the two paradigms. Junior engineers are also constantly tripped up by the subtleties of `useEffect` and `useState`.
Furthermore I think attempting to "encapsulate" side effects is a bad approach to writing testable programs. Most React components that use hooks end up having several chains of promises inside them but no way to await the final promise meaning tests have to be full of
await wait(0)
await wait(0)
await wait(0)
God forbid someone comes along and tries to be clever and replaces it with await wait(3)
which now makes the test non-deterministic.Cycle.js is the only framework that seems to get this right by acknowledging that a component doesn't just output JSX, but actually outputs JSX, HTTP Requests, etc.
Look, I get that Redux was a pain in the ass with all the boilerplate, but how did we throw the baby (unidirectional data flow) out with the bathwater. I no longer advertise that I know frontend development because the entire react community seems to have lost its mind.
This was something that confused me when I first started learning Typescript but is actually not an edge case but a fundamental feature of Typescript's structural typing.
A type T is only guaranteed to be at least (a subtype of) T. Which in the case of objects means it has at least those fields, but potentially more. For instance
interface FooBar {
foo: string
bar: string
}
interface Baz {
baz: number
}
const fooBarBaz: FooBar & Baz = {
foo: 'foo',
bar: 'bar',
baz: 3
}
const printFoobar = (fooBar: FooBar) => {
for (const key of Object.keys(foobar)) {
if (key !== 'foo' && key !== 'bar') {
// If Object.keys was (keyof T)[] Typescript would claim this branch is unreachable
}
}
}
printFooBar(fooBarBaz)
It's really worth thinking about Typescript types not as nominal objects like in Java or Haskell, but contracts about minimum functionality. Embracing this in terms of function arguments and return types makes testing and composing typescript code much easier. For example, if you were writing a AWS Lambda function in Typescript that only uses the body of the incoming event. export const handlerOne = (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
console.log(event.body)
return {
statusCode: 200,
body: event.body,
}
}
interface MinimalEvent extends Pick<APIGatewayProxyEvent, 'body'> {}
export const handlerTwo = (event: MinimalEvent): Promise<APIGatewayProxyResult> => {
console.log(event.body)
return {
statusCode: 200,
body: event.body,
}
}
handlerTwo only requires a handlerTwo({ body: '....' }) call in a test, instead of having to fill in all the extra properties of the APIGatewayProxyEvent that aren't even required. You might be tempted to use a type coercion in the test instead e.g. handlerOne({ body: '....' } as APIGatewayProxyEvent) but the problem with the coercion is that is in not checked at all by the compiler, it's essentially like temporarily using an any type. So if handlerOne is updated in the future to depend on more of the structure of APIGatewayProxyEvent Typescript will be none the wiser that the test requires updating (although granted hopefully the test would fail).Anyway, that's a long winded explanation of why Object.keys shouldn't return (keyof T)[]. If you want to program generically over the Type of something I'd suggest making use of a runtime type library like io-ts instead which gives you a data structure representing the type to iterate over, etc.
For instance in Typescript,
const absurd = <A>(): A => absurd()
const unimplemented = <A>(): A => { throw new Error(“Unimplemented”) }
const uninhabited: string & number = absurd()
Intuitively you can think of it like, “Yeah sure, I can build you a term of any possible type, as soon as I get back to you.”, but then the function just ghosts you by looping forever. But it hasn’t lied. However, so long as you’re aware of these gotcha’s they don’t come up much in practice which is why viewing types as proofs is still useful. Just don’t stake your career on one.