This is an awesome article! I like the idea of being more forthcoming with what we don't know.
> Containers. I have no idea about how to use Docker or Kubernetes. (Are those related?) I have a vague idea that they let me spin up a separate VM in a predictable way. Sounds cool but I haven’t tried it.
> Deployment and devops. I can manage to send some files over FTP or kill some processes but that’s the limit of my devops skills.
I'm working hard on trying to tease out a method to educate developers about DevOps / Kubernetes... It's hard to explain to people who have not been on-call or walked into a company on their first day as a devops, but I am strongly in the camp of "Kubernetes is live-saving, game-changing, etc". I tend to fail to explain to most product-focused developers successfully - Either too low level, too high level and hand-wavey, or they walk away with a sense of "man one day, that might be cool", rather than "We could get going on this _today_!". The most success I've had is in demonstrations (I have a raspberry Pi Kube cluster with 4 pies, with which I can physically unplug power, network, disk, etc and show off Kube's self-healing and auto-discovery powers), but at companies with day to day stresses, not so much. Plus the demo only scratches the service of cool features of even the Deployment API object.
Shameless self promo, but I'm working on a project with a friend that hopefully helps. I want product-focused developers to have a "Heroku" moment about kube and understand the immense benefits they get from designing their applications with a "cloud-native" mindset. That the small cost is _vastly_ worth the benefit. The project is here: https://kubesail.com/.
My "thing I dont know as of 2018", just for good measure: How to build complex front-end applications without making a complete mess of things!
I also admit that I still have no idea what a Kubernet is or what Docker and containers orchestration or any of those things are all about. I mean, I visited their web sites and read a few wikipedia articles. But I'm primarily an embedded/mobile guy and whatever problem space containers solve is something I've just never even remotely encountered.
Same with enterprise software development. It's kind of neat that the world of software engineering is so big that one can go 20 years into their career and be totally experience-deficient in large spaces of the industry.
>My "thing I dont know as of 2018", just for good measure: How to build complex front-end applications without making a complete mess of things!
If you find anyone that truly knows the answer, please let us know :)
I'm sure plenty of people claim to, and many more will just claim that the mere concept is flawed so there's no point, and there are even more non-answers. But the actual problem is very difficult. I remember when AngularJS (the old Angular) first came out and it felt like we finally started having an idea of how to handle frontend after years of dissatisfaction with jQuery, Knockout, etc.. Then React, Polymer, Web Components, ES6, Webpack, Modules, TypeScript, Redux (and its Flux-based ancestors) and so, so much more hit and... it's mesmerizing.
I think React is the best option so far, it's still not 100% where it should be but it offers my favorite API and the essence of it is simple enough to fit in a tiny, minimal library if you want. It can be tricky here and there, but the way it encapsulates state is, for the most part, super predictable. I love the way you fold asynchronous streams into state and props using tools like create-subscription so that components don't have to fiddle around with confusing, long async chains.
For me, Polymer and Web Components were both huge misses - the promise of Web Components is still neat to this day, but I really don't think I would want to compose my application out of many Web Components, it just doesn't seem like the right tool for that job, it seems like a better tool for embedding or shared widgets. There's really a lot that can be said here w.r.t. Polymer and Web Components in general but I don't think any of it hasn't been said better so I'll leave it alone.
Angular 2+ do not do it for me. It is amazingly nice having so much out of the box unlike React, but at the same time I find myself constantly annoyed. The NgModule system feels like a relic of AngularJS. When it was standard to simply concatenate JavaScript files together and call it a bundle, this system made perfect sense. In the world of ES modules and Webpack, it's just a layer of needless complexity. The AOT compiler causes all sorts of shenanigans where valid, obvious JavaScript won't work. I don't really care for dependency injection, at least not the way its implemented in Angular. It does give you some neat tricks, but I am happier with my obvious, ugly code, thanks. Even disregarding modules and DI, I still don't like Angular. My favorite concept from React is that the tree of components is out of line of the DOM. In Angular the component is actually in the DOM. This usually only matters in a few cases, but when it does it's really annoying. Example would be CSS, or say, if you want a component to be a table row. The way event listeners work is not orthogonal between child elements and the so-called 'host' element due to this, as well, whereas in React you can just use HTML-style on event attributes since you are rendering all of the elements that end up in the DOM always. Angular's documentation frequently doesn't have example code showing you how to use things, which may actually be because the developers aren't sure - I've often tried to figure out how to use basic features only to find GitHub issues pointing out the severe limitations in them. Like, Angular Router - What if you want to compartmentalize some routes in a child module? You could of course just define a Routes[] variable somewhere and import it, but there is actually a RouterModule.forChild, so surely you can use that? No. You can only use that if you are using loadChildren, which uses lazy loading. Lazy loading is actually a PITA especially depending on how you have modules setup, and the AOT compiler once again does some truly confusing stuff. Like, you can fake loading something synchronously with loadChildren, but check out what you gotta do to make it work with the AOT compiler: https://github.com/angular/angular/issues/10958#issuecomment... - Nearly every interaction with Angular beyond trivialities end in multiple open GitHub issues that lead nowhere, and it's frustrated me like crazy. Angular also seems to like RxJS, a library I really want to love but can't seem to quite get there. It's very powerful, but I hate that to get the exact behavior I want I often end up with quite a long list of operators where the order can be important in subtle ways. It's easy to leak subscriptions in RxJS especially if you're new to it. Some things are hard to implement, like say if you wanted to implement some kind of feedback loop where the result goes back through. And worst of all, you tend to get RxJS subscriptions and subjects at the component level at Angular, meaning you've got to deal with these async values in rendering code, in logic code, etc. Which can cause RxJS to spread like a virus when all you wanted to do was pull some state in and combine it with some other state. And if you want change detection to work, there's even more rules you need to be careful about following...
I've yet to try Ember. I've looked at Vue.js but ultimately haven't been as drawn in.
...But even despite my preference for React, large apps are still super hard to structure, and many problems feel unsolved. Like saving and synchronizing state to a server. There's individual solutions to that problem, but none feel like they're 'perfect' across all of the domains you want them to be. GraphQL seems like it could be nice but so far I have been mystified by it in practice, and longing for better type-safety on both sides. React obviously is far from perfect, too, and because of its imperfections, you are going to want a lot of linting to prevent people from shooting themselves in the foot, especially if you are working on a team. I've never fully figured out unit and integration testing in React, last I checked the standard was to use Jest and JSdom and JSdom required native Node.JS modules and bla bla... needless to say, I was unsatisfied. Because unit test suites on JS apps tend to compile to one giant bundle, you have a harder time parallelizing work and doing coverage-based tests.
Organizing components? Smart components vs dumb components? Container components? High order components? Where to put the Redux reducers and actions and state? How to split your bundle? Whether or not to split your bundle? Webpack vs Rollup vs Parcel? I'm barely scratching the surface. Production frontend apps are insanely difficult and it's fragmented to all hell. I don't buy in super hard to the JS fatigue thing, but I do think we're very scatterbrained right now on how to build good frontend apps, and it seems like it's gonna take a while to fully collect our thoughts and figure out how things 'ought' to be done. Right now, it's really super all over the place.
So yeah... I think it's OK if you don't know how to write complex front-end apps without making a mess. I doubt you are alone even among the pioneers.
A few things that have made creating new React projects easier for me:
- create-react—app or Parcel bundler, both of which require zero config. CRA is easiest but I’m not a fan of their defaults for Typescript (which is to prevent the app loading in dev if you have any tslint or compiler errors, even if they are just warnings) so once I’ve messed around fixing that, it’s almost just as easy to use Parcel.
- For website projects, I use react-static as a static site generator as it can handle all your data loading, bundle splitting, server side rendering, etc. for you automatically. It’s best to start your project with react-static rather than retrofitting it, they have a command line tool to set up a new project so this is usually instead of CRA/Parcel. Gatsby is probably an equally valid choice, react-static seemed a little simpler to me and I’ve been happy so far but Gatsby community seems larger.
- I’ve not used Redux for a couple of years now, instead using MobX for application state. Personally I find it so much quicker and easier to use, although it is undeniably more “magic”. Honestly think this is one of the biggest productivity enabling changes I’ve made since switching to React.
- Personally I’m a fan of Typescript, while it can be a bit of a pain initially, I think you reap the rewards as a project progresses in terms of ability to refactor easily and avoid wasting time on syntax errors.
I disagree with CRA because it promotes developers avoiding and fearing configuration files. If you are a full time front end developer and your shop uses it you NEED to learn Webpack/Babel/NPM/etc because it is a short up-front investment, will save significant amounts of time, and will lead to a noticeably better product.
We're talking about hours of study leading to a long-term hundreds of hours of time saved.
Devs shouldn't have to spend hours setting up build configuration just to get started learning React, or every time you have a side project you want to try out. Granted, you _never_ needed Babel and Webpack _just_ to use React, but for a long time every React tutorial started with "First, we'll learn how to set up Babel and Webpack". Now, they can just say "Run `npx create-react-app my-app`", and immediately get a solid project setup that works out of the box.
Nothing prevents you from still writing entire Babel and Webpack configs by hand if you want to, but it shouldn't be a prerequisite for actually using React (or any other framework).
Couldn't you make this same argument about math curriculum? "Why should we teach algebra when its so easy to just use basic calculus for real world problems".
The problem is there is a huge gap between a development react application and a production react application that is served to users with best security/operational processes. The own creators of CRA do not recommend it be used in production and isn't that the goal for most react developers, to put apps into production?
On the contrary, CRA's docs specifically recommend it for production use:
> No Configuration Required: You don't need to configure anything. A reasonably good configuration of both development and production builds is handled for you so you can focus on writing code.
Nowhere in the docs do I see phrases like "don't use this in production".
As for the math analogy: I'd say the difference is that many calc concepts do require understanding of algebra to grasp and use, whereas the only thing about React that _sorta_ implies knowledge of Babel is the JSX transform, which isn't a hard requirement to use React but is certainly the common preferred approach.
Again, I'm not at all saying that people _shouldn't_ learn how to set up build tool configs. I agree that's valuable knowledge to have. I'm just saying it shouldn't be a hard blocker for using React, and that React tutorials shouldn't have to spend half their time teaching unrelated build tools instead of React itself.
Off the top of my head, I'm sure I'm missing a few obvious ones. Notably CRA doesn't prevent you from doing any of these, but taking the time to learn the various build tools will better enable it.
* spend less time debugging dependencies across version changes
* reduce bundle sizes
* create a better CI/CD pipeline
* reduce unnecessary dependencies
* fork/fix/create your own plug-ins and other tools
* self-hosting npm to avoid production/dev outages
* easily learn new tools because you understand the underlying systems/alternatives
In case you missed it, the official create-react-app 2.x supports TypeScript out of the box now, and it has better defaults than react-scripts-ts. No more ridiculously strict lint rules.
My primary background as a professional developer is front-end, and I sometimes feel I can barely keep up. For any project where it's an option, I try to put as much in the back-end as possible. So far it's working out well.
For example, I had a little game where initially I wrote a React+ecosystem solution that worked. Then, considering that I don't need x updates per seconds, I switched to server-side rendering + morphdom.
As a result I could reduce all my code to 1) websockets messages to the server and strings of markup from the server, and 2) a few 'optimistic updates' on the client-side by directly changing the DOM. Having no more client-side state to maintain really simplifies things.
Considering that this was a viable solution to a game that has to update the DOM on pretty much every click (but no more than that), it's probably a fine solution to the vast majority of apps I build.
I can't wait for Phoenix LiveView to make this kind of solution less ad-hoc, but at least so far even the ad-hoc solution is so much simpler...
You definitely aren’t restricted to lazy loading when using RouterModule.forChild, idk where you got that, just define a module, add forChild with your routes, and import it into another module. Im doing this all over our codebase.
I can understand you’re opinions about the module system, but I disagree. For a small to medium size app it can seem like annoying boilerplate that gets in the way. If you’re working on a large app across multiple teams then it’s very helpful. You have a single entry point for all relevant code. You can define the api for that module so other teams don’t misuse what you have built. It can get frustrating when you have a single component that you want to share and you need to wrap it in a module, that feels very unnecessary, but I know the angular team is working on that.
I actually really like that my components are in the dom, I can see clearly where it is, not which div with which class or Id it is. It makes inspecting the tree very easy.
RxJS can be difficult and hard to learn, which doesn’t help that the docs are meh and you can never find exactly where to go. Juniors really need someone to help them not leak subscriptions. Though if you follow Angulars promoted idea of using the async pipe, then that will automatically clean up your subscriptions. Again, for small components/apps it feels way overkill, but it feels oh so nice when your trying some complex async stuff and can handle it and pass it along so easily.
>You definitely aren’t restricted to lazy loading when using RouterModule.forChild, idk where you got that, just define a module, add forChild with your routes, and import it into another module. Im doing this all over our codebase.
Genuinely, I have not been able to figure out what it actually does from the documentation. Either it isn't there or I have been holding it wrong.
Because, loadChildren actually would import the routes from a child module as children of an existing route. But what you're saying, it sounds like the child routes would get placed at the root of the tree. I don't want that though, that doesn't allow me to do the decoupling I wanted to do. I don't fully understand why I can't just specify a module for children when loadChildren will happily take one asynchronously.
>I can understand you’re opinions about the module system, but I disagree. For a small to medium size app it can seem like annoying boilerplate that gets in the way. If you’re working on a large app across multiple teams then it’s very helpful. You have a single entry point for all relevant code. You can define the api for that module so other teams don’t misuse what you have built. It can get frustrating when you have a single component that you want to share and you need to wrap it in a module, that feels very unnecessary, but I know the angular team is working on that.
I work on only relatively large teams and I still don't get it. If I didn't want someone to be able to use part of my API, I would just not export it. Further, systems like Bazel already provide package visibility, which is a lot more powerful in terms of limiting the spread of an API imo. I know in Angular sometimes things have to be exported because of the AOT compiler, but that's not a great justification.
>I actually really like that my components are in the dom, I can see clearly where it is, not which div with which class or Id it is. It makes inspecting the tree very easy.
I would've thought it would make this easier, but due to the amount of power you have in the selector for components and the way directives work, I've still definitely found myself confused at times. At the end of the day, I didn't really have a complaint with the way React handled it, aside from the inconvenience of needing a separate debug tool to see the component tree.
>RxJS can be difficult and hard to learn, which doesn’t help that the docs are meh and you can never find exactly where to go.
To be honest with you, I found the RxJS docs to be OK. It is a bit hard to search them, but most of the information I actually needed was available if I did. I personally had more trouble finding answers with Angular than RxJS.
>Juniors really need someone to help them not leak subscriptions.
I don't like the way you've worded this because it heavily implies that it's mostly only an issue for junior developers. However, I've seen some very tricky takeUntil setups that are surprisingly nuanced. If your async chains are simple it's easy to define the lifetime, it's not so easy when your chains lifetime may be a subset of your components or services lifetime.
Interestingly, if we had things like higher order components, we could turn the problem into a component lifecycle problem, which is what React likes to do. I miss being able to encapsulate problems like that.
>Though if you follow Angulars promoted idea of using the async pipe, then that will automatically clean up your subscriptions.
I use the async pipe where possible because it does offer a reprieve from manually managing things like lifespan. Sadly, there are a lot of times where using the async pipe is not super nice. Let's say a value that was synchronous has become an observable, now if I was using other pipes or using the dot accessor suddenly it becomes more complicated. Generally I just give up at that point.
>Again, for small components/apps it feels way overkill, but it feels oh so nice when your trying some complex async stuff and can handle it and pass it along so easily.
With the caveat that it actually does not map all complex async problems elegantly.
It is super nice for some common cases like implementing type-ahead, and I generally use RxJS even outside of Angular nowadays because of the fact that it's just easier to express complex asynchronous behavior with it, but there have definitely been moments when I realized my somewhat complicated RxJS code could be replaced with relatively simple use of async/await and a for loop :|
I have a very large number of Angular gripes other than what I listed, so please don't take it to be exhaustive. I just wanted to illustrate in great detail the ways I did not like Angular because if I don't do that many people will assume it's because I didn't give it a fair shake.
There is a core issue with UI development that makes things harder and less elegant than the backend.
It's the io loop. Components must change state and react to state. This where the complexity arises. If you remove the loop by having components only react to state, you will find your programs to be simple, modular and more beautiful.
The feedback loop of IO destroys the functional and modular nature of UI. Functional programming simplifies programming through restriction, however ui development is inheritly an object oriented problem due to the IO loop, so the results of trying to make it functional will have limited benefites.
The way to make UI work is to find a way to have components react to state and change state in a simple way and without hard coding a refrence to external state in the component itself. Aka stateless.
Many people believe that passing a closure is the solution. The reality is passing a closure is awkward and a form of encapsulating state with methods that leads to the same issues of complexity that you get with oop. Keep data and functions seperate always, a closure is technically a functional concept, but it is also oop in disguise as it is instatiating state coupled with a functions just like an object in oop.
Global event emitters might be the best way. I'm not sure if redux does this. I'm not a UI guy so everything is just imho.
IO loop necessitates OO unless you do some obscure tricks like passing closures and using a global event emitter. The most obvious way to implement UI is to do OOP.
Widget hierarchy does not necessitate OO. Hierarchies can be built with plain data structures. OO comes into play when you place methods within the data structure. Methods coupled with data is essentially an object as described by OOP.
Why would you need integrate a method inside data structures?
Those claims are somewhat confusing. What is the difference, in your mind, between an IO loop and a "global event emitter"? That's all the IO loop is; an event emitter that fires events at subscribed code.
Do you consider the "OOP"-ness to be evident in the fact that subscription functions (whether 'onclick' functions or 'fetch' callbacks) contain both code to react to events and an implicit binding to the IO loop? Or is your issue that some (not all!) DOM APIs happen to let you attach on-event functions to the same things you can read data out of?
Basically, I don't see why UI programming is any more inherently OO or functional (assuming those are even opposites, which has historically been debated more or less to death) than any other domain. There are UI toolkits that subscribe to each and both of those paradigms, with varying amounts of rigor.
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 the impurity of IO from the rest of your code. The most primitive form of IO is the socket.
>Do you consider the "OOP"-ness to be evident in the fact that subscription functions (whether 'onclick' functions or 'fetch' callbacks) contain both code to react to events and an implicit binding to the IO loop? Or is your issue that some (not all!) DOM APIs happen to let you attach on-event functions to the same things you can read data out of?
Look at where events come from and where they are sent. How do you associate the action of button A with the data representing button A? The most obvious way is to merge the action and the data into a single primitive. An object as described by OOP. You will have to do this regardless of what an API such as the DOM offers as primitives.
>(assuming those are even opposites, which has historically been debated more or less to death)
They are opposites. This is only up for debate for people who don't truly understand the differences. In OOP as described by JAVA or C++ you have a graph of mute-able objects instantiating other mutable objects and modifying each other. In functional you have a linked list of composed immutable functions with an input on the head and an output on the tail. Nothing is mutated. To get functional working with UI you need to employ obscure tricks as a UI widget is more of an object than it is a function.
They are opposites according to the most common definition of OOP. They are only orthogonal if you get rid of mutation which is NOT the way most OOP is used nowadays.
>Basically, I don't see why UI programming is any more inherently OO or functional
A UI widget cannot just be a function. A widget in-itself is data, the structure, the display, the color ... etc. And It must react to state and IO like a function. It is both data and methods and thus OO.
Without IO the the widget can just be a plain data structure. HTML is basically pure data. You can still keep it functional if you have a function dynamically generate HTML based on a set of parameters (IO without a loop). However when you need to introduce the "loop" and have UI both send and receive data that's when methods need to be attached to the UI widgets.
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?
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?
In general, it sounds like you might be referring to typical JS asynchronous IO (callbacks/promises/async-await and whatnot) when you talk about IO loops. But I can't for the life of me figure out what those things have to do with OOP vs functional programming, nor why using those structures requires you to store state on a "widget".
> Look at where events come from and where they are sent. How do you associate the action of button A with the data representing button A?
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.
> In functional you have a linked list of composed immutable functions with an input on the head and an output on the tail. Nothing is mutated.
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.
At the point where you start talking about linked lists, I begin to think that you're misunderstanding or misusing some fundamental term we're discussing (Mutability? IO? Functional? Object? I'm not sure): a LL is a data structure (which is mutated by adding/removing elements, traditionally), and has absolutely nothing to do with programming style or paradigm.
> A UI widget cannot just be a function. A widget in-itself is data, the structure, the display, the color ... etc.
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.
You can do that in a tightly coupled way and store all your state in the DOM, or you can use any one of many powerful systems that allow you to separate those and perform operations only on data, which can be applied to the external UI state outside of your code. React is a good example of this.
> HTML is basically pure data.
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.
> You can still keep it functional if you have a function dynamically generate HTML based on a set of parameters (IO without a loop).
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.
>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:
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:
>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:
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.
Redux's `store.subscribe()` function is obviously a general event emitter, where the only event is "an action was dispatched", so it doesn't even need a name.
On the actions side, Redux really only has a single "root reducer" function. Since having a gigantic monolithic function for all state updates would be unmaintainable, we split that function up into smaller functions, like any other piece of code.
Since Redux was based on the existing "Flux" concepts, the idea of having multiple "stores" for each different type of data was translated into having multiple "slice reducers", each one responsible for independently updating the data at a given key in your state object. Redux provides a `combineReducers` utility for this use case, which iterates through all the keys in the state object and calls the slice reducer at each key.
If you squint at this reducer setup the right way, you can see it as being a limited pubsub event system as well.
So, it's reasonable to view a Redux store as being a 2-way pubsub system. Different parts of the app dispatch an action to "publish" an event to the mostly-independent slice reducer functions, and the store publishes a single event to let any part of the UI know that the state _may_ have been updated.
Just so you know, on mobile version of your site, on ios, pricing page description overfloats left and you cant see description for the numbers - I guess it's cpu, ram and storage but what is infinite, traffic?
Thank you! Other founder here - I fixed the overflow. The infinite across the board is hosting custom domains (something other providers charge an arm and a leg for)
Not to derail the core message, but one learning approach I've enjoyed in the past is to come up with a list like this and then try to learn a little bit about all of them. Doesn't need to be deep knowledge, just a basic "hello world" or equivalent to get your feet wet. It's a lot harder to get breadth when you stick to technologies that solve a problem you're facing, so sometimes it's fun to just explore a technology for the sake of seeing what it's like. Maybe with a more solid basic understanding, you'll recognize a case in the future where it could be useful or where it would be fun to throw into a side project. Also, some technologies may stand out as more fun and things that you naturally want to dig into further.
Of course, that doesn't mean you now know any of these things, but even some small experience breaks through a psychological barrier, from something intimidating and unknown to something a bit more tangible.
Also, I find that when I start to learn about something, as long as I'm just going thru the motions on a hello world, and actually look up what the things do, I learn the most. Coming in with that beginner mindset you learn faster, then it's kind of a slow crawl to become an expert. The first week of playing with a new language / domain / piece of software I think I learn the most. It's the 80/20 rule at work.
Plus I find just having a small amount of knowledge and understanding where a piece of technology fits in the greater scheme of things to be really useful.
Very surprised that he is not expert at functional programming...
I always assumed that all the folks behind React were driven by a desire to make web programming more functional generally - that this was an ideal toward which they thought we should be working. And furthermore assumed that this was informed by a deep understanding of functional programming generally and the reasons why it is desirable as a programming methodology.
That inspired me to learn more about functional programming... which definitely wasn't a bad thing to do.
But I guess I have just been projecting - I have a friend who I've always considered smarter than me who raves about functional programming... and I guess I just thought this is what smart people generally have come to realise is the god's truth about programming.
It's good to know in a way that Dan is not in fact this religious about it. I wonder how other React devs feel.
I think everybody on the React team is on board with functional principles (like separating side effects from computation and relying on referential transparency).
But there’s a reason “deep” functional programming hasn’t gone mainstream — many people (including me) find it hard to contort their product code to express their thoughts in 100% functional way.
React has always been about taking the pragmatic parts of FP and making them easy to benefit from without buying into learning category theory or something like that.
FWIW the creator of react, Jordan Walke is a lot more along the lines of what you had imagined the react team to be like. He is a massive proponent of ML and is currently working on (also the creator of) ReasonML, a new syntax for OCaml, and react in ReasonML.
I think there’s an interesting point in there as to the attributes needed to build something new vs scale something existing to a new level. They’re both clearly great at the things they seem to prefer doing.
Because there's substantially more 'perceived' pressure when you don't know for a fact that thousands of developers rely on your work or trust your authority via your follower count. Power absolutely changes one's mental context for taking action, and Dan Abramov is one of the most empowered people in the front-end world.
This is a very good article. What stumps me though is how the 10x engineers/architects make such sound technical choices without knowing a lot of things. I perennially feel ignorant of Computer Science concepts that many others seem to possess. This article helps me to understand it's not only me. But I would still like to make the best tech choices most of the times...But the problem is..WHAT TO LEARN NEXT? THERE'S BILLION THINGS, WHAT TO PICK UP?
Your thought process is backwards. Instead of starting with a technology you want to learn, start with a problem that you have. Then do research on tech that can solve your problem and you will learn by solving the problem you have.
Most technology companies are also terrible at explaining what they do so you need to be able to do a bit of reading to understand their value proposition. For example Docker, their website's homepage states.
Future proof your Windows apps and drive continuous innovation
Protect your legacy, invest in your future.
Which is techobabble nonsense, and doesn't tell me a fucking thing about what Docker does. Docker isn't just for windows apps, so I don't know why they are alienating linux users. It makes no sense, and I would assume most people would move on unless they already knew what it was. This is sad, because I like and use Docker and want them to succeed.
How I would describe Docker to the uninitiated. Docker is a file. In that file you can run a series of commands to install and compile all the software necessary to run your application. Once you execute the file, it outputs another file which you can send to someone else who will automatically know how to run it. That's all it is, there is no reason for confusion.
I first started coding professionally in the early 90’s, just as “the web” started to take off. I found myself surrounded by people who talked about the network stack all the time; I put together that there was an important concept called “TCP/IP” in there. So I did what I thought was the most logical thing: I picked up a copy of Richard Steven’s “TCP/IP Illustrated” and read it cover to cover. Then a funny thing happened - I found out I actually knew WAY more about the network stack than all the people around me who were blathering about it non-stop as though they were experts (which I didn’t and still don’t consider myself). That experience has made me take other’s claims of expertise with a grain of salt.
I think a corollary here is that reading a technical book cover to cover isn't really that hard. Personally I'm trying to make it my default approach for learning things - books over articles (where that makes sense; books on continuously changing software are a waste of paper).
I very much enjoy working as a programmer, but, to be honest, there is constantly a little anxiety in the back of my mind that I do not get FP/docker/devops/insert-latest-buzzword-here enough not to look like a clueless coder in a watercooler-side chat with a fellow. So I really appreciated this article, it made me feel better about myself :-)
I was formally educated to do low level development, did operating systems, hardware design, and communications for a living for 15 years. During that time I also learned and regularly used FP, data processing, windows GUI, full stack web development. Every year I pick a new tooling language so that I'm not completely tied to one language or paradigm. Every time I have an opportunity to use the right language or tool for the job I learn it and use it.
The whole point of my education process was not to learn C and Assembly, it was to motivate me to he constantly learning. When I wanted a new job I created a "real world problem" to solve, did actual design docs, took courses online, read books, etc. Was able to get a new job in a completely different field, doubling my pay and reducing my work load. That's all due to the fact that if I had a list of stuff I didnt know I'd be out there learning that stuff every waking minute.
Do not get me wrong, I am learning constantly and like it that way (now I go through a Haskell textbook and have a few MOOCs in my to-do list), but the thing is, I feel like I am still fighting a losing battle; there is just too many new information out there to understand everything. That is the source of anxiety for me.
It’s deeper than that - you won’t just look like a “clueless coder”, you’ll find yourself unemployable. I learned early on that it doesn’t matter what credentials you have or how much experience you have, never admit there’s anything you don’t know, or they’ll pass on you to hire somebody else who confidently insists that he does know absolutely every single thing there is to know. I feel bad for the author of this piece, because putting his name to this _will_ cost him employment at some point in the future.
This is honestly the most ridiculous thing I've ever heard. You think it's acceptable to never admit that you don't know something? You're advising people to pretend to know everything?
I would immediately try to get you fired for lying about your knowledge and qualifications.
One of the best possible things you can do is admit when you don't know something. That should always be safe to do at any GOOD employer.
Interview is over as soon as I find you pretending you know something you don't. Do you really think you're going to trick me when I have literally decades of programming experience? The person hiring you will often be your mentor. Start out on the right foot by trusting them and showing them you can be trusted.
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?).
I would like a list to see what he does know, according to himself. Somehow I get giddy making a comparison between what he knows and doesn’t know. I want to make a mental model of what a real dev looks like, even if it is a biased one.
Don't know: start with Dan's list, it has many similarities. I know more Bash, but not enough to write a shell script more complex than my aliases file. I vaguely know z80 and 6502 assembly. I know Java extremely well, but am faking C++ and C#. I understand flexbox but not CSS floats. I don't even know what sockets and streams even are in this context, they don't sound like the sockets and streams I know. I don't know node. I do know graphics and algorithms.
More don't know: the only front-end frameworks I know are Backbone, raw javascript, and various immediate-mode graphics APIs. I barely understand the AWS services I use. I don't understand matrix decomposition and that's actually relevant to things I do. I have to look up basic SQL commands when I'm writing it.
Do know: graph search algorithms in excessive depth, sequential Bayesian filtering in excessive depth, most of 2D graphics, 3D graphics up until you need to sample the local region in world space, most of procedural terrain generation, 2D computational geometry, 2D physics, sensor error characteristics for various sensors, GPS from the high level down to pseudoranges (but not down to signal analysis), rather a lot about data formats and compression, video game networking models
The "do know" list isn't exhaustive. The "don't know" one even more so.
From your "do know" list you sound like a video game developer. I would think that a video game developer would be strongest in C++. Are you telling me your "do know" list is applied using Java?
This has always felt to me like an inconvenient truth most people are too uncomfortable to voice aloud. Maybe we all fear that we're the singular hapless fool adrift in an industry of savants?
I don’t feel that _I’m_ a hapless fool - I know how much effort I’ve put into learning what I know. I do feel (and have much evidence to support) that all of the non “technical” people that surround me think I’m a hapless fool every time they ask me a question and I don’t know the answer immediately off the top of my head, no matter how many times I did know the answer. I’m surrounded by “product managers” and “agile coaches” who imply that I’d better get everything done in minutes or they’ll “replace me with somebody who does”.
I think there are several elements particular to the tech industry that elevates this problem past ‘classic’ Imposter Syndrome. So that label feels a bit reductionist to me, though not entirely incorrect.
> I was considered by all my masters and my father a very ordinary boy, rather below the common standard of intellect.
-Charles Darwin
> That any civilized human being in this nineteenth century should not be aware that the earth travelled round the sun appeared to be to me such an extraordinary fact that I could hardly realize it.
> “You appear to be astonished,” he said, smiling at my expression of surprise. “Now that I do know it I shall do my best to forget it.”
> “To forget it!”
> “You see,” he explained, “I consider that a man’s brain originally is like a little empty attic, and you have to stock it with such furniture as you choose…”
> “But the Solar System!” I protested.
> “What the deuce is it to me?” he interrupted impatiently; “you say that we go round the sun. If we went round the moon it would not make a pennyworth of difference to me or to my work.”
After reading this, I feel like I've imposter syndrome as well. I know about 80% of those topics pretty well, but I don't think I could ever get a job as a junior dev. Maybe I focus too much on learning things that interest me, and not enough on things that land you that software engineer title.
Hah! Probably. I'd rather learn about distributed systems, the idiosyncrasies of bash, how file systems work, dive into how http/2 & ipv6 will solve some of our problems, etc. Absolutely love fixing bugs in code though, but the actual act of coding an application from scratch bores me. Can't explain it!
(I manage the React team at Facebook.) This is like me! I love fixing stuff and enjoy coding from scratch much less. I don’t have specific tips for you, but I promise it’s possible.
What language though? You can know C+ pretty well but still, suck at many other concepts that can be helpful operations. It really depends on the company you try to land a job with.
I was really surprised to see algorithms on this list. I would have presumed everyone at Facebook would be a cover-to-cover expert at the sorts of algorithms you'd see in coding interviews.
It's good to know algorithms, but in (for example) sorts, it is a much worse error to write your own sort (based on the best algorithm), than to check if your problem has already been well solved by an existing library you can import without great cost. Not everything needs to be an import, but really in over a decade of development for multiple different organizations solving different problems, I've never seen a case where writing your own sort was a good idea. The same is true of many other algorithm categories. Not to say it's not good to know about, but that's how you can be a quite productive programmer without knowing algorithms like bubblesort off the top of your head.
If, for example, you need to hash/salt passwords correctly and you haven't done that lately, even if you remember for certain how to do it, you should look it up to see if the best method has changed in the last year. Knowing algorithms off the top of your head might almost be a negative, if it makes you less likely to check with a bit of research first when it's time to use one.
According to his tweet [1], there is a separate hiring track for front end engineers that does not include that much algorithmic knowledge. I was surprised too.
Facebook can afford (nay, NEEDS) to rise to that level of specialization. But that's only going to be true at the level of a megacorp, like Facebook, or Google, or Microsoft.
For even moderately sized companies, someone with wider knowledge will fare better, because such companies aren't going to spend $500k/yr on someone who doesn't know algorithms (or on someone who ONLY knows algorithms). The marginal cost to Facebook is near zero, the marginal cost to a smaller company certainly is not.
To be clear, once you get in, there is no actual distinction. People can choose any team, and "front end" people sometimes work on the backend or mobile or services or IDE or a compiler, etc. We try to hire generalists.
A really curious aspect of this list is the “scale”/depth of the various topics. Some are very specific: “Node backends”, “GraphQl”; some are very general: “algorithms”, “functional languages”.
It is well established that “knowing more” is not really a thing; we just learn to further understand relations and distinctions, feeding our ability to know of more things we have yet to learn.
What I miss from this article is what he does know. Not to boats, but to contrast. I know some of the things he does not know, and I'm sure he knows things I don't know. But without knowing what his expertise is, it's easy to think you know more than him.
He's one of the most prominent React core developers. The author of Redux etc. Many JavaScript and React developers (myself included) consider him a rockstar.
You don’t think that’s a problem? I don’t think there’s any value in being a name in programming. There is certainly value in a dollar sense (to their own career prospects at least), but I don’t understand why people would be like “wow! It’s $name! They’re famous!”
If someone non-junior knew no shell scripting and had no FP knowledge — or thought that JavaScript counts as FP [spoiler alert: it doesn’t] — I wouldn’t hire them.
Personally I’m not saying JavaScript “counts” as FP — which is why the post says “unless _you_ count”. ;-) But there are certainly FP subcultures in the JS community which only use the functional subset:
If you’re splitting hairs over such definitions without acknowledging the cultural aspect and use that as a hiring criteria I wouldn’t want to work with you either.
Culture means different things to different people. If a candidate were to suggest they were only interested in the “pragmatic parts of FP”, implying that developing an understanding of category theory is somehow frivolous and not pragmatic (which I think you did earlier), I would acknowledge this as a poor culture fit.
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 popular open-source contributors — who don’t have the same anti-intellectual position of rejecting CT because it isn’t “pragmatic”.
my point is exactly not how popular he is but how accomplished he is and how condescending he could be (since he is so popular and accomplished) and how gracious he is being to you. it's like those movies where someone is starting a fight (giving cause) with a person 10x their size and then the bigger person gracefully declining to batter - it should make you reconsider who's the protagonist...
So yes, you are exactly giving special treatment to someone you perceive to be of greater merit owing to their popularity.
Your position is that I should not argue against Dan Abramov because you perceive him to be relatively accomplished. This is an embarrassing point of view.
> 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.
Consider that actual rock stars often aren't the world's best musicians from a purely technical perspective - but they're experts at delivering what their audience wants.
Dan made a bit of a name for himself in a couple of ways I can think of: creating a very popular library (Redux) and communicating extremely well in English about React and Redux.
"Able to communicate about with a broad audience about complex technical topics" is a skill I wish more developers had.
So he's able to create things his audience wants and then communicate to his audience about those things. Sounds exactly like a rock star to me.
That's meant as a compliment, not an insult. The ability to communicate well and the ability to be honest about you don't know are two things the developer community needs more of.
I’ll grant you this: unless you’re actually playing music to sold-out stadiums, “Rock star” is an insipid, meaningless phrase. I’m not trying to debate the definition. Likewise, I’m not interested in the technical qualifications to be a “communicator”. There are clearly few technical standards for fame.
In every other field of engineering, there are standards of knowledge and competency. Software is notable, in that not only are there no standards, but we actually see the glorification of ignorance of even basic knowledge.
There are lots of bad, popular github projects (particularly in the JS universe, where the bar for competency is already quite low) and having a popular project is not prima facie evidence of engineering skill (how many projects was the string-reversing NPM module breaking, again?) Which is to take nothing from the author; I don’t particularly care about his level of skill, nor am I saying his projects are bad. The argument is not about the author.
What I care about is when someone says “hey, I’m ignorant of the basics of the field in which I work, but it’s OK, because I work on a big, famous project.”, and people interpret that to mean that their ignorance is dandy, too. There are dozens of comments to this effect on this page (cf every comment that mentions “impostor syndrome”)
It’s OK to not know things. It’s OK to be a beginner. It’s not OK to excuse yourself from knowing things you really should know as a professional, because someone else got famous without that knowledge.
Way I see it is it's more than OK to not know things -- it's a necessary optimization. Engineering is all about tradeoffs, and skills development is no exception. Follow one path, forego another; dive deep, sacrifice breadth (and vice versa).
So consider that maybe, just maybe, for a developer working full-time on a SPA framework, not knowing Docker or Bash scripting might not be a real impediment to working effectively or delivering quality product. If it were, perhaps React & Redux wouldn't be as great as they are. And since they are great, maybe we should consider that fact not as a celebrity get-out-of-jail-free card, but as counterevidence to your implication that these topics all constitute a universal educational imperative, and that someone lacking in any of these areas is by definition not a professional in the software field.
Being a rockstar is more often a matter of being able to work in your field effectively and efficiently. He's not a savant, and he's not working in a space where knowing sorting algorithms is meaningful to his day to day activity. He's still great at how job and the space he works in, and not knowing these things doesn't heavily affect that
That’s mostly just an indictment of the Javascript space, not a defense of lacking fundamental knowledge.
I don’t routinely write sorting algorithms either, but I know what they are, how they differ, and how to implement them. And it’s useful knowledge - it comes up often in lots of domains.
I see lots of comments about how this is a bold stance against “imposter syndrome”, but at some point, it isn’t a syndrome. There really is basic knowledge that defines professional competence in this field, and it can’t be replaced by github stars.
He knows (is aware of) what he doesn’t know: you can be sure that he will learn by himself or seek someone with more knowledge when he faces a challenge involving a new (to him) topic / concept / technology.
There's a risk of being a "Jack of all trades, master of none" in Software Engineering.
Companies pressure Engineers to be "Generalists" because it lowers salary rates and makes people more replaceable. But it's the Specialists (like Dan) that drive actual innovation.
Do you think companies really have a policy of intentionally pressuring engineers with those motivations in mind? That sounds a little conspiracy theory. In my personal experience what's really happening at your average widget maker is they don't need someone who can write database software or a UI library for browsers. They see that the front-end person can get her work done in 2 days a week, so they try to find something else for her to contribute to. Specialists like Dan don't work for the average company, and he wouldn't even be of much use to them either. And specialists like Dan wouldn't have a job if it weren't for the millions of generalists using his work.
EDIT: In another comment Dan himself mentions that Facebook tries to hire generalists.
I bet if you got fifty programmers (as a representative sample) in a room and asked them to define "T-shaped" you'd get a wide range of answers that generally reflect a T shape but don't really align on what the horizontal part should be.
Hi Dan, I'm surprised and amazed by your patience and cool-headedness here. In my opinion that's the foundational quality of every good developer, everything else comes out of that. Seeing your replies here tells me all I need to know.
Great post. I tackle the problem of being aware of things I don’t yet know or fully understand by maintaining an [open Trello board](https://trello.com/b/cu32qF3q) that lists topics I want to learn in a visual way.
I then mark off topics I am focusing on learning now and topics I want to learn ‘Next’. This helps me greatly. I also try to learn things in context of projects I am working on and the direct knowledge I need to solve the problems I have.
I don't know anything about the person who wrote this, but I know almost everything they don't know. Am I a much better programmer/engineer than I thought?
I’ve been programming for almost 30 years, know most of the things on his list, but a few years ago I got an email from a guy interested in one of my apps and he told me about the apps he built and how much money he was making. He had nearly zero programming experience or skill, but his apps were more successful than mine.
My point is that knowing 20 different programming languages did not make me more successful or better. This guy kind of sort of knew one language and was crushing me in sales.
On an unrelated note, I knew a guy that knew every new tool and language under the sun. Was always learning the latest thing. Terrible engineer —- everything too complicated and abstracted. Hard to follow, hard to work with.
I don’t believe knowing more necissarily makes for a better enginner at all.
LOL I didn’t want to be the first person to say that, so I’m glad you said it. In the spirit of charity, though, I’m sure that his list of the things that he does know overlaps my list of things I don’t know.
You're either way more knowledgable than most, or there's a bit of Dunning-Kruger in play. Hard to tell. What you know is only a small part of the game anyways.
Dan previously used C#, so he knows what static types are. He just said he hasn't used _TypeScript_ specifically.
Redux is a simple library that you can read through in a few minutes. It's working great for hundreds of thousands of users. Why would Dan's background scare you off from using it?
As for React, there's more than just Dan on the React team. (In particular, Seb Markbage is an incredibly deep thinker, and the rest of the team is great too).
It scares me off for the same reason that hundreds of thousands of people use dynamic languages, and I still believe that this is far from being a good idea.
The same way that hundreds of millions of people believe in god, and I still think this is absurd.
Yeah, I mean I see this article as a not-so-subtle middle finger to computer science elitists, so I don't think backlash was unexpected (on the contrary, welcomed).
React itself represents a shift in webdev thought where, instead of desperately trying to establish itself as a "respectable" programming field (see: any Google web technology), it instead focuses on being as accessible as possible and embraces the populist nature of the web. This article is just an extension of that ideology.
And, as you've indicated, anyone who would be horrified by that ideology probably is already horrified by the web to begin with.
Meh. I wrote C# for 13 years of my career, starting with .NET 1.0. I worked at Microsoft, writing C# services, I worked for consultancies writing C# servers, clients, and web apps.
I’ve been doing full time JS with some Ruby for the past 5 years. I doubt I could write anything more than “Hello world” in C# without a lot of Googling.
I’ve worked on C# codebases professionally for about four years. They’re not open source because half of that time I worked on enterprise software (ASP .NET MVC, Entity Framework, NHibernate) and another half was a closed source product (Xamarin aka MonoTouch, Rx). Prior to that I worked a little on an open source static analysis tool (Gendarme) using Mono Cecil.
Prior to that I was moderating the .NET section on one of the largest Russian programming forums and translated documents like LINQ Overview when they came out. I also have a silver C# badge on StackOverflow. (https://stackoverflow.com/help/badges/39/c-sharp?userid=4581...)
I know how types work. My remark was that I haven’t worked with C# for about four years. I’m not aware of changes between versions 5 and 9, and might have forgotten some of the C# syntax for things like lambdas, having worked a lot with JS since then.
> It scares me off for the same reason that hundreds of thousands of people use dynamic languages, and I still believe that this is far from being a good idea.
> The same way that hundreds of millions of people believe in god, and I still think this is absurd.
Well, that takes the idea of a 'programming language holy war' to a very literal place.
I will admit I am a terrible programmer, but I will say using Redux scared me away from using React at first.
Maybe my React needs are minimal, but I tried following a tutorial using React and Redux and I was immensely confused. Once I struck out on my own and ditched Redux for just straight React, everything became so much clearer and simpler.
Hi, I'm a Redux maintainer. Anything specific that confused you? Which tutorials were you looking at?
We're currently planning a revamp of the Redux docs. I'd really appreciate any feedback on what things caused problems, so we can know how to make the docs better.
[not OP but I can remember feeling the same, also I haven't done a big redux project in about a year]
I haven't looked at the docs in a while but I'm not sure that's where the big problem lies. The hard thing about Redux is that you need to "get" the core concepts (not that complex), and how they interplay with how (and when) React renders component subtrees (very complex - this requires a new understanding of react you didn't need before).
After you learn React and finally "get" it you definitely won't get Redux. Not because of Redux perse, but because the way you structure your application is so different. After that you'll encounter more subjective questions like do we put this (semi localized) state in Redux? And there are no right answers anymore, just opinions.
Yeah, the docs can't solve everything, but I'm hoping we can improve the structure, the content, the reading flow, and how the prerequisite concepts are handled.
As part of that, I definitely want to have new category sections on "Using Redux with a UI" (which would include both how that works in general, and specific pages for use with React, Angular, Vue, Ember, etc), and "Real World Usage" (which could cover things like app structure, code splitting, choosing a side effects approach, and so on).
As for the "boilerplate" line... everyone throws around this word, and everyone means something different. Could you clarify what specific things you're thinking of when you say that?
FWIW, we have a new package called `redux-starter-kit`, which is specifically intended to help simplify several common Redux use cases. It includes utilities that help with store setup, reducer definitions, immutable update logic, and even creating entire "slices" of state automatically without having to write any action types or action creators yourself. I'd encourage everyone to try it out, and let us know how much it helps improve your apps and what else ought to be included:
> As for the "boilerplate" line... everyone throws around this word, and everyone means something different. Could you clarify what specific things you're thinking of when you say that?
As stated before I haven't done a big JS project for about a year now. In the last project I did we used redux in a create-react-app. At the time the best practice was creating presentational and container components[1].
The biggest boilerplate was:
- Whenever we added a react component (presentational) we would need to create a container component to wrap it in, this would always result in ~20 or basically the same lines (in our project we did things pretty verbose, so we didn't have a HoC or whatever people use).
- "immutable update logic", reducing deeply nested objects is a pain an error prone (using es6 spread or Object.assign), I've heard about some libraries that can help with this, but we didn't use anything at the time).
> FWIW, we have a new package called `redux-starter-kit`
I am most definitely going to use this for an upcoming project!
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 that in the upcoming Redux docs revamp, I'd like to have the tutorials and examples switch from a "folder-by-type" approach to either a "feature folder" or even a "ducks" approach, and maybe even cut down on having separate action constant variables. There's valid reasons to do things in multiple files, but it's also not _necessary_, and I want to simplify things.
Yes, I totally agree immutable update logic is a pain to write and write correctly, which is why Immer is awesome, and why the starter kit uses Immer internally. 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.
Please let me know how well it works for you, and if you've got any other suggestions for what it should include!
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" and we had to do spread notation gymnastics in all our es-2025 code that we are compiling to es5 anyway. From an abstraction point of view this is how I feel consensus about state management changed over time in the frontend world (or the part/frameworks I was involved in):
- 2010: jQuery will help you update the DOM anywhere (looking at IE6) - but you have to solve state yourself. A deeply nested object attached at `window` was considered best practice.
- 2012: We need to manage state properly, here is a nice Backbone "model" class: pass it a schema and use getters/setters to update so you can glue state change events to your view logic.
- 2014: Angular (first version) is great! Don't worry about managing your state yourself, just attach whatever you want to $scope and we will simply use dirty checking to check everything whenever something changes.
- 2015: React uses a vdom which behaves similar: change whatever you want and keep rendering it and React will figure out what actually changed. And for your state we made this flux thing which you implement as a bunch of different data stores (in my mind similar to backbone models except they only go "one way").
- 2016 (redux): here is a single store that also flows one way. Oh yea you need to do everything functional and you can't mutate any objects anymore or things will break. These 20 lines of code show you how to change the property of object with another property called id with value "x" in a nested list. This is better because it makes diffing faster in the vdom. You have to make sure you never mutate so here is a way to "freeze" your objects which will make sure you don't do this.
- 2017 Immer (I haven't used this yet): We realize it's a pain to change big objects if you can't mutate, so here is a dummy object you can mutate, we will clone it to make sure it's a different object. This is a proxy to the objects that will end up in your store (and exposed to your view layer).
I understand how we got to needing Immer, but it's a solution to a problem we only have because of how frameworks like React figure out what changed (strict equality). But it's too verbose and error prone for us to do manually. React only got designed as it did because too many people got tired of OO style state management. Right now I'm noticing a lot of people are getting tired of the verbosity, boilerplate and complex abstractions that come with doing things the "proper React way" (updating state represented in an object is the main example here, but that whole chain is verbose: you need to create actions you can dispatch, you need to write a reducer to catch those actions and mutate your objects, you need to glue the correct state to each component).
React is great tech, but in a lot of ways it's a counter movement. Countering complexities you get when managing state the OO way. But now it has gotten very complex itself, we now need a solution (immer) introduced by a solution (redux) that was needed to manage state inline with React. In other words, also very complex.
It feels almost as if I took the Backbone code, renamed it and marketed as "a simpler way to manage your UI" I could get a lot of people to switch away from React + redux + immer + immutable + redux-thunk + etc...
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.
> As part of that, I definitely want to have new category sections on "Using Redux with a UI" (which would include both how that works in general, and specific pages for use with React, Angular, Vue, Ember, etc), and "Real World Usage" (which could cover things like app structure, code splitting, choosing a side effects approach, and so on).
Those new sections sound awesome! Kudos for thinking about adding them to the docs.
It wasn't the Redux docs, it was the entire mindframe of Redux. This connects to that which connects to that and sets this while this gets that. Like I said, I'm a terrible programmer and I have a hard time keeping complex interactions in my mind. If this block of code needs to change a variable, I want it to just change the variable right there and move on. Having to write the code that needs to change the variable, then switching to another file to write the code that actually changes the variable, then switching to another file to write the code that returns that new variable to my original function is just... so damn unnecessary. There's just too many moving parts that can (and do) break. It's so complex, and when something doesn't work I struggle to debug why.
I will admit I did not choose to use Redux, it was part of a tutorial I was following on Udemy. I never got the hang of it, and once I figured out React Native well enough, I quickly scaled back my reliance on Redux. It's made my life a lot easier.
My day job is a technical consultant for a major tech company, and we have meetings to discuss the meeting we're going to have before the meeting. The administrative overhead of Redux reminds me of that in a very bad way. Instead of my Facebook login button calling auth_actions.js which then returns the auth token to auth_reducer.js which then returns the auth token to auth_screen.js (but don't forget to add it to the combineReducers in index.js), I just put the authentication code in 'await doAuth()' inside of the auth_screen.js file. I've never heard a convincing reason as to why I shouldn't do that, even though the tutorial I followed said it's a bad idea.
Redux, IMO is a beautiful state management library.
Were you following Dan’s tutorial on Redux? Because that is a beautifully made tutorial as well. (https://egghead.io/redux)
If you have tried to build a substantially big app with React alone, you will find yourself lost in passing down the props and callbacks and hoisting variables and what not. You definitely need a state management library where you can CRUD from all your React components. Thats where Redux/Mobx comes into picture, unless you want to write a new one.
I agree that Redux needs a lot of boilerplate though.
It very well could be a problem with the tutorial I was using, where the author leaned too heavily on using Redux for everything. I wildly scaled back my usage of Redux after I got going. It's just too many moving parts, and I've never figured out how to debug it when something doesn't work. I end up with 'console.log("we made it to the action")' and 'console.log("we made it to the reducer")' and then 'console.log("we made it to mapstatetoprops")' followed by 'console.log("so why the hell is this.state.fbToken still null!?")'. Then I come to find out I forgot to add auth_reducer to the combineReducers in my reducers/index.js.
I can't count the number of hours I've lost to stuff like this.
Per my other comment just above ( https://news.ycombinator.com/item?id=18784238 ), please try out our new `redux-starter-kit` package and see how much it simplifies things for you:
A software should be judged only based on how functional and performant it is. Judging a software based on the author’s biodata is firstly, not fair and secondly, too presumptuous.
To be honest, knowing your limitations that well is a ver good thing.
Probably many people would say "yes, I know" knowing not much more than what he summarized for some of the items of the list with just a few words.
Could it be that Dan's personal threshold for "knowing" things is just higher than that of most of us? Surely there are things on that list which he could pick up effortlessly if need be (eg: flexbox, sass).
Knowing what you don't know is better than not knowing what you don't know. It shows a wide breadth of knowledge and I suspect that with the desire and time, you could become an expert in any of these things.
I know most of these things in detail, I can understand them and use most of them daily. I know NOTHING about JavaScript at all. It's ok, you work on frontend, I'm on backend.
Nope. Dan wrote it in JS originally, then handed off maintainership of it a while back (possibly before he wrote Redux in 2015). Looks like it may have been ported to TS this year: https://github.com/react-dnd/react-dnd/pull/1017
It’s kind of scary that Dan Abramov doesn’t know about ML languages or typescript... I hope that he is just being humble, because otherwise I wonder if it was a complete lie when Facebook said that they were pushing on ReasonML instead of react.js. I know that he was not initially involved and that the first prototype used ocaml as a primary language before falling back to JavaScript.
I really appreciate Dan work and his multiple and very helpful posts, but as someone that enjoys functional languages and hopes to see a full featured ML react, or at least a full support for typescript, I really hope that Dan can see the advantages in the “functional way” given that he is now one of the main actors.
I think you’re a bit confused here. Facebook isn’t “pushing” anything.
There’s a React team. I’m on that team. We develop React. Facebook uses it all over the place.
There’s also a Reason team. (Its creator also wrote React originally.) They work on Reason and its React bindings. Facebook uses it in some places.
We talk to the Reason team of course. But there has never been a plan to force all React users to use Reason. I don’t know where you heard that. If you like it, that’s cool. If not, that’s cool too. We’re just sharing what we use.
I’m not sure what your practical concerns are (are Reason bindings or TS typings not good enough?) but I’d like to hear them!
Of course I know “about” ML and TS. If I didn’t know about them I wouldn’t mention them. :-) I haven’t developed anything meaningful in either of them but it’s not like I’m clueless about what types are. I’ve been using C# for years.
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.
Sometimes there’s an unrealistic expectation that engineers know everything, but senior engineers I’ve worked with and hired knew most of that list... at least somewhat.
Yes, comfort with bash and a knowledge of how networking actually works is something I expect someone working on computer software for 10+ years to have gotten familiar with at some point.
I also expect people who build libraries inspired by prior work (FRP) to actually learn a bit about the prior work. I’m surprised he has not dabbled with functional programming.
It would be great if we all met each others' expectations. And yet it doesn't work that way. A step up from where you're at is to realize that tech, ANY tech, is easy. If brute-forced by rote it can be even be learnt by those without the aptitude.
No, tech is not easy. I dont think I’ve met a software engineer in my entire 20 year career who would characterize programming as “easy”. I don’t think of law, medicine, and architecture as easy either. I’m sure I could have been an architect, if I spent years learning it like I did programming. But that doesn’t make it easy.
Software engineers command huge salaries because it’s not easy. Just because anyone can learn anything doesn’t make everything is easy.
I don’t understand why tech celebrates amateurism and ignorance... We don’t all know everything but we shouldn’t wear our ignorance like a badge of honor either.
Mastering tech is easy relative to mastering people. I know. I've done the former for 32 years at companies like Microsoft and Nokia. Still learning the latter. Not sure how this celebrates amateurism or ignorance.
How effective is an NDA in this case? A lot of NDA's are effective because BIGCO you signed the NDA with has piles of money & resources to sue you. If a developer is ghostcoding for ROCKSTAR and it gets out ROCKSTAR hires ghostcoders. ROCKSTAR is screwed and maybe he was making pretty comfortable money at BIGCO but his pockets are exponentially smaller than BIGCO's. And he doesn't have a legal department to handle the lawsuit either. He'll have to handle it himself, while he's being dragged & disgraced in tech news and on Twitter.
And even if the NDA is with you the agency, do you have a legal team? If you do is your agency big enough or is it worth business enough for you to get into a big fight with one of your former contractors to defend ROCKSTAR? Especially when ROCKSTAR is the one who looks bad to the public and not necessarily your agency?
I'm not saying you're not telling the truth, it sounds plausible but I wonder about the model.
This is disgusting. I’m not condemning you for finding a gap in the market — that’s totally fair play. But the fact that this can exist and that we have a culture of celebrity in software development at all (especially in such a dishonest way) is just disgusting.
It also didn’t happen. This guy is trolling HN. Maybe it breaks the guidelines to post this, but take a look through his history, he just posts conflicting, self aggrandising statements and low content noise. It’s a shame to see people wasting their effort replying to him.
How was your flight to New York to sell your $7.5 million in bitcoin? Also how is your nurse girlfriend, the one I assume you’re seeing on the side, since you also mention how you outsourcing your coding work allows you to spend so much time with your wife and kids.
All you do is post inflammatory lies and boasts to get a reaction. I’m surprised you’ve not been banned.
I wasn’t clear enough. I have no problem with the “ghost-coding” business.
I have a problem with the culture in which we will hear about some open-source coder and then idolise them to the point that they aren’t held to an equal standard, for example in the hiring process.
It certainly flies in the face of the ideals of a meritocracy [spare me the “meritocracy is a myth!” trope] when we hire for a technical role on the basis of being a personality in the industry. I knew this happened to some degree as I think I’ve taken advantage of it myself, but I didn’t know it’s so prevalent that people can start “ghost-coding” businesses off the back of it.
To be absolutely clear: I am not implying this applies specifically to Dan Abramov.
"Here’s why I think it’s important.
First, there is often an unrealistic expectation that an experienced engineer knows every technology in their field."
> this need to think you’re “the greatest” at everything and then beat yourself up when you realise you can’t be.
That's exactly the kind of mindset that Dan is trying to dispel.
You might not mean to do it, but the tone in this message seems to be quite condescending.
I believe you are making a generalization that is quite unnecessary. Surely not all Americans are like that, and I am sure plenty of Europeans share that mindset. (I am one of them, I like being the best in something as I am competitive. In sports, games or programming).
In my neck of the woods, the stereotype for this kind of behaviour would be Japanese more than American btw.
Either way, I do agree that this post is a bit useless. No one is expected to know absolutely everything there is to known. Why know the web when you program embedded devices for the car industry, for example :)
Is that guy really an experienced developer? He's obviously talented but experience and talent are different things. It sounds like he has less than 10 years under his belt.
Is 10 years the bar for what counts as an experienced developer? Why is 10 the magic number?
I would say someone with 5 years experience could be senior to someone with 10 years under their belt, granted the former worked on the right projects that gave them valuable experience, with some combination of design, understanding trade offs, implementation, and social/management skills managing delivery of their features or taking complexity and simplifying it (both technically and from a requirements perspective). You could work 10 years and not hit those points.
I expect someone with 10 years is hands down more experienced than someone with just one year under their belt, but otherwise, looking at how long you’ve been in the industry is kind of meaningless without understanding what it is that you did.
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.
> People often assume that I know far more than I actually do. That’s not a bad problem to have and I’m not complaining.
It is also not a good problem to have, either. There will always be a few people who think you know everything, and a few people who think you know nothing. The only plausible reason why everybody would think you know everything is that you act like you know everything around everybody. Put differently, if most people think you know more than you do, it would imply that you are not very humble in your interactions with most people.
> Folks from minority groups often suffer the opposite bias despite their hard-earned credentials, and that sucks.
Does it suck, though? It is much better to be underestimated than to be overestimated. I've read a lot of Dan's articles. He offers a lot of interesting insight and advice in pretty much every article he's written. The guy comes off as a know-it-all! Not saying it's bad, but it something to introspect on if you constantly find people overestimating your abilities.
I wouldn’t say he comes across as a know-it-all.. everything he’s written that I’ve read has to do with React or a few closely related subjects. And his writing never has a tone of superiority or “this should be obvious” that is, IMO, a requirement to be a know-it-all
I personally kind of figured he knew a lot about everything Webdev related since he knows so much about React, but that’s obviously not the case now that he’s listed all that out. In fact, now I don’t feel like the extent my knowledge is as limited as I did because I have a basis for comparison! Which I.. figure might be the point of the article?
That's the mainstream narrative as regards to minority groups in tech :-)
I too am not convinced that being underestimated sucks. Being overestimated may be stressful when you keep trying to fit the image that others may have formed of you and to meet their expectations. When underestimated, the most likely way is upwards, towards greater appreciation; when overestimated, one quite possible way is downwards, amid general disappointment of those who had higher expectations of you.
2, things you don't know about (this article as an example)
3, things you don't know you don't know about (hackernoon and medium are full of this kind of c*ap, people creaming their pants over switching their computer on for the first time)
There's absolutely zero value in the last two, they add so much noise and worse they make the author look like a complete idiot, even if they're not. I genuinely don't understand why people are so insistent on broadcasting their ignorance/stupidity though?
The only article of worth is the first kind, writing about your subject area, that adds value and is how people learn.
It's interesting and notable because of who wrote it. The author created one of the most-used programming frameworks, yet there are a lot of things he doesn't know. This type of article can actually be super helpful for people with impostor syndrome, as it shows that you don't need to be an expert in everything to create work that millions of people use and love.
There is more to writing than just the content. The history and the background of the author plays a significant role. Let me give some reasons WRT this article:
1. In this article, the author says that he does not know streams. Now, when he learns it well, he can write about "How he learned about streams", and a beginner would empathize more with this article rather than some expert ranting about it in their blog.
2. It is inspiring for the readers. It sends a message: "If you master one skill and master it well, you can still add a lot of value to the world. Knowing everything in the field is not really important".
3. Many people write not just for others, but also for themselves. Making your insecurities public is a good way to acknowledge and face them.
> Containers. I have no idea about how to use Docker or Kubernetes. (Are those related?) I have a vague idea that they let me spin up a separate VM in a predictable way. Sounds cool but I haven’t tried it.
> Deployment and devops. I can manage to send some files over FTP or kill some processes but that’s the limit of my devops skills.
I'm working hard on trying to tease out a method to educate developers about DevOps / Kubernetes... It's hard to explain to people who have not been on-call or walked into a company on their first day as a devops, but I am strongly in the camp of "Kubernetes is live-saving, game-changing, etc". I tend to fail to explain to most product-focused developers successfully - Either too low level, too high level and hand-wavey, or they walk away with a sense of "man one day, that might be cool", rather than "We could get going on this _today_!". The most success I've had is in demonstrations (I have a raspberry Pi Kube cluster with 4 pies, with which I can physically unplug power, network, disk, etc and show off Kube's self-healing and auto-discovery powers), but at companies with day to day stresses, not so much. Plus the demo only scratches the service of cool features of even the Deployment API object.
Shameless self promo, but I'm working on a project with a friend that hopefully helps. I want product-focused developers to have a "Heroku" moment about kube and understand the immense benefits they get from designing their applications with a "cloud-native" mindset. That the small cost is _vastly_ worth the benefit. The project is here: https://kubesail.com/.
My "thing I dont know as of 2018", just for good measure: How to build complex front-end applications without making a complete mess of things!