Live data from Hacker News

Things I Don’t Know as of 2018

overreacted.io

221–226 of 226 posts

Re: Things I Don’t Know as of 2018

#221

Earlier quoted context omitted.

When I talk about an IO loop, I mean external state. The program sends a message to external state, the external state sends a message back. That is a loop. If you get rid of one, you no longer have a loop. you just have IO. If you get rid of both you have just data and no IO. I am not talking about abstractions on top of this loop. A global event emitter is such an abstraction that one can use to hide and block off…

That's a baffling definition of IO and IO loops. It sounds like you think bidirectional IO is an IO loop, as opposed to unidirectional IO (which . . . does that even exist outside of "write bytes here" shared memory constructs? Even UDP write operations get data back from the kernel), but you also classify a socket, which is typically bidirectional, as just "IO", so I'm not quite sure what to make of that. It sort of…

>That's a baffling definition of IO and IO loops. It sounds like you think bidirectional IO is an IO loop, as opposed to unidirectional IO (which . . . does that even exist outside of "write bytes here" shared memory constructs? Even UDP write operations get data back from the kernel), but you also classify a socket, which is typically bidirectional, as just "IO", so I'm not quite sure what to make of that. It sort of sounds like you're talking about asynchronous IO, which is often coupled with event loops (which may or may not be IO loops unless you define time-based conditions as IO) in practice, but doesn't fundamentally have anything to do with them. Is that what you mean?

I don't even know where you're getting all this from. I defined the "IO loop" the access of external state as both a read and a write. Once I defined it, it should be clear what I'm talking about. You should be aware of my definition through my explanation regardless of implementation. You go on to talk about asynchronous IO which is a whole different thing all together. I am not talking about concurrency. I am talking about IO from a very high level perspective.

Let's simplify it. Imagine an API that reads and writes strings from IO:

  func read(source: str) -> str
  func write(source: str, data: str) -> None
If you have both of these things in your program you have an IO loop. If you don't like the wording, give it another name. Either way, this "IO loop" is what I am addressing in the conversation. If I have a button widget that does IO, say... write data on click, then the most obvious way to create that widget is to unify the data describing that widget with a method that calls "write." When you unify data and methods you get an object. You understand now?

>This has nothing to do with functional programming, or a functional style. Immutable data exists as a very common pattern in both colloquially-FP and colloquially-OOP languages, and so does mutable data.

This is completely wrong. Mutable data is not part of the functional programming paradigm. Here's the definition straight from wikipedia:

"In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data."

>No, a data object can contain those things, but in higher-level UI programming, the data object is very very rarely the "widget" itself; it's just data that is supplied to the renderer (the API of which, in web UIs, is the DOM), and the renderer generates the UI based on that.

Obviously, we're not giving pixel level instructions (aka the actual widget) to the ui renderer. The renderer still needs to associate what's rendered with a function. A widget is not just a visual representation of something; it is an interactive visual representation. Data needs to be unified with methods to fully define a UI widget. Hence Object. As I will mention in other responses, this is the most obvious and common way of handling the UI problem. There are other methods that don't use OO. But a UI widget and what it does has a one to one match with the definition of an object in object oriented programming.

>I think you're confused about the difference between HTML (text, can be generated and passed around by code) and the DOM (the API to what is being rendered by the browser). HTML is data, sure.

I am perfectly clear about what I am talking about. There is absolutely no confusion. I am perfectly aware of what you just said. HTML is data, the DOM is an api that can manipulate said HTML.

>That's what event listeners and callbacks are. Whether or not you're dynamically generating HTML, or whether code is mutating it after it's loaded into the DOM, has nothing to do with functional-or-not. Code doesn't stop being 'functional' as soon as its goal is to alter the state of or handle input from some external thing, whether that's a DOM node or a traffic light.

When did I say the DOM was functional? I'm not talking about the DOM. I'm talking about UI development in general from a very generic perspective. I'm not looking at UI development soley from the perspective of javascript, HTML and the DOM. What I was talking about in the statement was this:

   input_parameters = get_io_stuff()
   renderUI(input_parameters)
Also this statement:

>Code doesn't stop being 'functional' as soon as its goal is to alter the state

is completely and utterly wrong. Functional programming by its nature avoids all state changes. If it doesn't avoid state changes then it hides state changes through blackbox abstractions.

>I can say 'button.onClick(() => { button.clicked = true })' just as easily as I can chain every computation which would happen as a result of 'button.clicked' being true onto the event instead. The former is more OOP, colloquially, than the latter, but is definitely not inherent to UI programming: tons of popular patterns and frameworks exist whose primary goal is to remove the coupling between state and UI appearance.

This is exactly what I'm talking about. I never asked for the specific implementation in javascript, It's baffling why you bring it up. Here's what I'm saying: I'm saying the former OOP method is the most obvious method, the later method is using a global event emitter. The latter method is better because it makes the UI widget reusable across systems that utilize the same event emitter while the OOP method ties the handler and a reference to IO to the widget itself. Thats it. I think we can both agree that the majority of systems utilize the OOP method due to the prevalence of that style of programming.

>When you talk about an event emitter, what kind of code structures are you referring to? An EventEmitter a la Node.js is a pretty decent separation of IO and data, though not perfect: something external (perhaps an event loop) triggers subscribed code based on IO, but your code is given only data (payload) to process. Is your beef that 'someThing.onEvent(eventType, e => whatever)' is more 'OOP' than 'bindEvent(someThing.eventType, e => whatever)' is 'functional'? If so, how or why?

Yes. This is exactly what I'm talking about. I am also saying the latter method is better. It is better because it allows me to take that widget and reuse it in another project with a very different IO patterns. Imagine two implementations for button. We have code like this:

One implementation requires this: button.onClick(() => { button.clicked = true }) Another requires this: button.onClick(() => { button.color = "red" })

Try to think of onClick as just something that registers a handler to when the button is clicked. Ignore all the lower level details of what actually happens underneath and think of each as a method definition.

The code is not re-useable in general. Usually if I implemented the first requirement and hit the second requirement I have to write a lot of code to make an abstract version of button in which I can inherit two buttons with two different handlers.

Now look at this: button.onClick(() => { sys.triggerGlobalEventName("button.clicked") })

This makes the button reuse-able in any system that has sys.triggerGlobalEventName. The typical way to handle this issue is usually through inheritance and polymorphism. That style of abstraction leads to over complexity.

Re: Things I Don’t Know as of 2018

#222

Earlier quoted context omitted.

I’m well aware of who I am addressing. It seems you’re implying we should make special allowances for people depending on how popular they are. My entire point is that I won’t take someone at their name; I completely reject the idea of the “celebrity” programmer. Redux is pretty neat; IIRC it was a state store influenced by Elm and implemented in about 50 lines of JavaScript. But there are plenty of developers — even…

> who don’t have the same anti-intellectual position of rejecting CT because it isn’t “pragmatic” Where are you getting anti-intellectualism, rejection of category theory, or a defense of pragmatism at the expense of either of those things? Who is this directed at? Reading back up this thread, you're the only person referring to those, unless I'm missing an edit somewhere.

You had me worried for a moment; I also couldn't find where I had read that, so I thought either I had misquoted him or he had edited something.

But, no. Here it is: https://news.ycombinator.com/item?id=18783434

Re: Things I Don’t Know as of 2018

#223

Earlier quoted context omitted.

FWIW, I've always felt that having duplicate / parallel "container" and "component" folders/files just for the sake of separating them is completely overkill. Most components are only connected once - just do that in the same file and export the plain and connected versions separately. I wrote some thoughts on that here: https://gist.github.com/markerikson/ea312b5ee398627ffceb09f8... Similarly, I'm actually thinking…

Ah yes Immer is the framework I read about a few months back but couldn't find anymore. Thanks for reminding me. > My only concerns are that the code _is_ mutating unless you wrap it in RSK's "magic" `createReducer` utility that uses Immer, and it's going to be hard to figure out how to teach this properly. But, in terms of LOC and simplicity, it's a huge win. It's only a win since we decided that "mutation is bad" a…

I wish we had more historical overviews like this.

The number of new developers has been outstripping the number of old developers in most environments and this has been happening for at least the last 15 years.

Thus, we come back to Richard P. Gabriel's Worse is Better, or at least the essay's focus on the importance of social components of a project[1]. N.B.: not implying Redux is worse than any of the other discussed projects.

Newer generations cannot possibly have the time to go through the history and tradeoffs of various frameworks that used to be extremely popular and the reasons people moved on. Too many previous frameworks and too few posts like what you just wrote. Besides, where to start? It's not like TAOCP is going to have a chronology of Browser UI frameworks.

Instead, the tendency is to leverage the rapidly developing ecosystem and work with the projects that have the largest numbers of stars on github, etc.

If you are a very large well heeled eng. organization with a capability to enforce the use of particular frameworks, it is in your interest to popularize them. You will pay and encourage your engineering org to, among other things they do, market it to the dev. community. If there are enough engineers in your org (say: tens of thousands), you will begin exerting a tremendous concentrated influence on the Open Source community.

At the same time, for everyone else who does notwork inside a 10K+ engineer org, the lack of future maintenance and upgrades presents such a huge downside risk to not using the most popular open source frameworks. The open source community moves so quickly that you run into the risk of being stuck with maintaining the reusable components you plucked from other open source efforts.

The backwards compatibility guarantees are so much lower than what they used to be. The browser world is still figuring out how to link dependencies[2], let alone generate a stack that is stable enough where you don't have to continually update your UI codebase if you want to keep continuing to reuse other people's widget code.

So you tend to stay with the pack. React is the new most popular thing? OK, let's do React. Redux is the new way? OK, Redux. Pick anything else and you risk being stuck with a stack that rapidly loses the ability to interoperate with a huge majority of new Browser UI open source code.

[1] https://en.wikipedia.org/wiki/Worse_is_better

[2] https://medium.com/webpack/the-state-of-javascript-modules-4...

Re: Things I Don’t Know as of 2018

#224

You can make a living as a frontend dev without having to touch those topics much. Other devs: desktop app devs, mobile devs, backend devs, devops devs, network devs, data scientists, game devs get exposed to those a little bit more. If you are interested in learning a lot of those at the same time, write a server in C. https://beej.us/guide/bgnet/html/multi/index.html

If you are not working on Browser frontend, you will also enjoy the API stability.

Here's an older verison of the same guide by the same author, more than 2 decades ago: https://web.archive.org/web/19970812031954/http://www.ecst.c...

Amazing how little has changed. I strongly suspect anyone will remember the UI framework du jour 10 years from now but Berkeley sockets have staying power. Despite occasional efforts to replace (OpenTransport anyone?).

Re: Things I Don’t Know as of 2018

#225

Earlier quoted context omitted.

Thanks for your answer, I think that at the time of ReasonML presentation and a couple of other times I had the impression that there was quite of a push on that direction, but I may be wrong.

There’s not really such a thing as a “push” at FB — each product team is independent and decides what to use based on its own criteria. So there’s never an org-wide mandate to adopt a certain technology. Reason has some adoption but it’s happening organically.

IMHO, teams using a certain stack have agency to see that stack win the hearts and minds of other developers.

Additionally, the opinions of popular leads, managers etc on what should be used will count more. Winning their mindshare will win you a lot of FB org.

Winning a lot of FB org will exert a tremendous influence on the Open Source community as you now have large numbers of engineers working on open source projects on premium pay.

I believe this is how it works in most modern large engineering orgs. After reaching a certain critical mass of adoption, a team will be hard-pressed to use anything else, especially if reusing other team's components requires you to master, say, Redux anyway.

Re: Things I Don’t Know as of 2018

#226
post #150

Earlier quoted context omitted.

And not that many technologies.

No, not that many. I've worked with C# and .NET ecosystem (WinForms, ASP .NET MVC, NHibernate, EF, MSSQL), later Django/Flask/Python, later Xamarin/Cocoa and Rx, yet later Backbone, AngularJS, React. Haven't worked with low-level stuff at all.

I would say that in this particular domain going from:

WinForms -> ASP .NET MVC

and then

Backbone -> AngularJS -> React

(including participating in React development) gave you the kind of exposure and experience you needed for Redux.

I think a lot of people reading on here missed this parts and I certainly didn't catch onto this reading your Things I don't Know as of 2018 post or the "Things I do Know" post you linked to.

Post reply on HN