JS trends uncovered
x 0
JavaScript & OOP
Typescript
React
Redux
Express
MERN
The computer industry is the only industry that is more fashion-driven than women's fashion.
If you have first-class functions, all these OOP patterns are just 3-liners not deserving names
Dan Abramov
class Rabbit {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, i am ${this.name}`);
}
}
function Rabbit(name) {
this.name = name;
}
Rabbit.prototype.sayHello = function() {
console.log(`Hello, i am ${this.name}`);
}
class Rabbit {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, i am ${this.name}`);
}
}
class OddRabbit extends Rabbit {
construnctor(name) {
super(name);
}
howLongIsForver() {
console.log(`Sometimes, just a second.`)
}
}
function Rabbit(name) {
this.name = name;
}
Rabbit.prototype.sayHello = function() {
console.log(`Hello, i am ${this.name}`);
}
function OddRabbit(name) {
Rabbit.call(this, name);
}
OddRabbit.prototype = Object
.create(Rabbit.prototype);
OddRabbit.prototype
.howLongIsForver = function() {
console.log(`Sometimes, just a second.`)
}
but the thing is classes in JS are not at all like classes in other languages!
class Rabbit {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, i am ${this.name}`);
}
}
const r = new Rabbit('Oleg');
r.sayHello()
// Hello, i am Oleg
Rabbit.prototype.sayHello = () => console.log('Hey');
r.sayHello()
// Hey
Class defines an instantiable type
Prototype is a living instance
Using inheritance is not the only way to extend a class behavior. But definitely is the most dangerous and harmful one.
// singleton.js
export default Object.freeze({ ...data });
// decorator.js
function decorated(fn) {
return function(...args) {
console.log('With logger', ...args);
return fn(...args)
}
}
//strategy.js
function(strategy) {
this.strategy = strategy;
};
Greeter.prototype.greet = function() {
return this.strategy();
};
new Greeter(myStrategy).greet();
// templateMethod.js
// your homework :)
Bad programmers worry about the code. Good programmers worry about data structures and their relationships
Autocomplete
Refactoring
More safe
Self doocumentation
Property 'someProp' does not exist on type 'STNValue<ModelInstanceTypeProps<ModelPropertiesDeclarationToProperties<{ someProp: ISimpleType<boolean>; someType: ICustomType; }>>, IModelType<ModelPropertiesDeclarationToProperties<{ someProp: ISimpleType<boolean>; someType: ICustomType; }>, {}, _NotCustomized, _NotCustomized>>'.
export function reduce<V, A>(accumulator: (acc: V | A, value: V, index: number) => A, seed?: any): OperatorFunction<V, V | A> {
return operate(scanInternals(accumulator, seed, arguments.length >= 2, false, true));
}
@Module({
imports: [CatsModule],
providers: [
{
provide: CatsService,
useClass: MyClass,
},
];
})
export class AppModule {}
// Controller file next
@Controller()
export class CatsController {
constructor(connection: CatsService) {
// Oh no, the CatsService might be any object
}
}
type Metadata = {};
type UserMetadata = Map<string, Metadata>;
const cache: UserMetadata = new Map();
// later
const cacheCopy: UserMetadata = { ...cache };
cacheCopy.get('foo');
the spread operator doesn't copy prototypes
interface A {
x: number;
}
let a: A = { x: 3 }
let b: { x: number | string } = a;
b.x = "unsound";
let x: number = a.x; // unsound
a.x.toFixed(0); // WTF is it?
No compilation errors neither
but it's not a silver bullet
Why do most developers fear to make continuous changes to their code? They are afraid they’ll break it! Why are they afraid they’ll break it? Because they don’t have tests
Robert C. Martin
Reactivity is a programming paradigm that allows us to adjust to changes in a declarative manner
let name = 'Cat';
const App = () => (
<div>{ name }</div>
);
name = 'Dog'
To make it reactive we have to use third-party tools
October 2019
October 2020
25%
50%
75%
100%
25%
Learning curve
Boilerplate code
Performance
Central store
No built-in way to handle side-effects
State of JS 2020
Is it dead ?
Use react features/hooks instead ?
No.
You need a single source of truth
You want to maintain an undo history
You need a serializable state/actions
Travel between the state history in development
Provide alternative UI without disturbing too much of the business logic
Unopinionated framework
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const pg = require('pg');
const hash = require('./hash.js');
const PORT = 8000;
const app = express();
const pool = new pg.Pool({
host: '127.0.0.1',
port: 5432,
database: 'example',
user: 'marcus',
password: 'marcus',
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/user', (req, res) => {
console.log(`${req.socket.remoteAddress} GET /user`);
pool.query('SELECT * FROM users', (err, data) => {
if (err) throw err;
res.status(200).json(data.rows);
});
});
app.post('/user', async (req, res) => {
const { login, password } = req.body;
const user = JSON.stringify({ login, password });
console.log(`${req.socket.remoteAddress} POST /user ${user}`);
const sql = 'INSERT INTO users (login, password) VALUES ($1, $2)';
const passwordHash = await hash(password);
pool.query(sql, [login, passwordHash], (err, data) => {
if (err) throw err;
res.status(201).json({ created: data.insertId });
});
});
app.get('/user/:id', (req, res) => {
const id = parseInt(req.params.id);
console.log(`${req.socket.remoteAddress} GET /user/${id}`);
pool.query('SELECT * FROM users WHERE id = $1', [id], (err, data) => {
if (err) throw err;
res.status(200).json(data.rows);
});
});
app.put('/user/:id', async (req, res) => {
const id = parseInt(req.params.id);
const { login, password } = req.body;
const user = JSON.stringify({ login, password });
console.log(`${req.socket.remoteAddress} PUT /user/${id} ${user}`);
const sql = 'UPDATE users SET login = $1, password = $2 WHERE id = $3';
const passwordHash = await hash(password);
pool.query(sql, [login, passwordHash, id], (err, data) => {
if (err) throw err;
res.status(201).json({ modified: data.insertId });
});
});
app.delete('/user/:id', (req, res) => {
const id = parseInt(req.params.id);
console.log(`${req.socket.remoteAddress} DELETE /user/${id}`);
pool.query('DELETE FROM users WHERE id = $1', [id], (err, data) => {
if (err) throw err;
res.status(200).json({ deleted: data.insertId });
});
});
app.listen(PORT, () => {
console.log(`Listen on port ${PORT}`);
});
Timur Shemsedinov example of bad code using express
Clean architecture
& middlewares
var express = require('express');
var app = express();
var requestTime = function (req, res, next) {
req.requestTime = Date.now();
next();
};
app.use(requestTime);
app.get('/', function (req, res) {
var responseText = 'Hello World!';
responseText += 'Requested at: ' + req.requestTime + '';
res.send(responseText);
});
app.listen(3000);
Official guide
Autocannon performance comparison link
Express
Bare Node
Simplicity is a great virtue but it requires hard work to achieve it and education to appreciate it. And to make matters worse: complexity sells better
Edsger W. Dijkstra
Bad programmers worry about the code. Good programmers worry about data structures and their relationships
The computer industry is the only industry that is more fashion-driven than women's fashion.
Why do most developers fear to make continuous changes to their code? They are afraid they’ll break it! Why are they afraid they’ll break it? Because they don’t have tests
Simplicity is a great virtue but it requires hard work to achieve it and education to appreciate it. And to make matters worse: complexity sells better
In most cases we can live without OOP
TypeScript is not that safe
React is not reactive
Redux doesn't have to be used on most project
Time to stop using Express
2021
Slides