Node.js
for Enterprise
Chief Technology Architect at Metarhia
CTO at Salucyber, Lecturer at KPI & KSE
github.com/tshemsedinov
Timur Shemsedinov
Is Node.js ready for Enterprise?
Is Node.js ready for Enterprise?
Yes, sure
Is Node.js ready for Enterprise?
Yes, sure
Node.js is ready
Is Node.js ready for Enterprise?
Yes, sure
Node.js is ready
But JavaScript developers...
Is Node.js ready for Enterprise?
Yes, sure
Node.js is ready
But JavaScript developers are not
New features
● Multithreading for calculations and scale
(added in v10, stable in v12)
● WASI, Node-API 8, V8 v9 for Node.js v16, npm 7
● API: diagnostic API, perf_hooks, timer promises,
AbortController, vm, v8, scrypt, Web crypto api,
async_hooks, AsyncLocalStorage, etc.
● QUIC or HTTP/3 especially for mobile and 5G
Monkey job
Everything repeats every time we start a project
● Let’s discuss scaling, we expect highload
● We need microservices, REST and ORM
● People, vision and setup processes
● Application architecture and structure
● Select tools, libraries, frameworks
● Code conventions, repository maintenance
Node.js challenges
● Enterprise requirements: Reliability,
Maintainability, High Availability, Security,
Isolation, Compatibility
● Community culture: meetups, conferences,
fundamental SC knowledge, consensus
● Reputation and trust: education, certification,
success stories
Your code
With the code of your colleagues
With node_modules
Application in Node.js runtime
libuv
V8
openssl
zlib
c-ares
llhttp
Node.js in infrastructure
node
cron
postgres
autovacuum
logger
writer
statistics
statistics
checkpointer
redis systemd
journald
networkd
docker
How to think about you code
It’s glue and business-logic code
Semantically and syntactically flexible
Very expressive (you can create DSL)
Simple for maintenance and changes
Simple and readable for everyone
Works everywhere
Easy to integrate
Engineering culture
● Architecture: DDD and clean code, layered
architecture, domain in the middle
● Principles and patterns: GRASP, SOLID, GoF,
IoC, DI, coupling и cohesion, Law of Demeter
● Project structure: framework-agnostic
● Techniques: error handling, asynchronous and
parallel programming, metaprogramming...
Important aspects
● Application is the place for applied code
● Declarative code is better than imperative
● State: reliability, performance, interactivity
● Configuration and infrastructure in the code
● Getting rid of dependencies
● We use layered architecture
Related to Node.js
● Context isolation and v8 sandboxes
● Don’t block event-loop
● Avoiding race conditions and leaks
● Avoid reference pollution and mixins
● Don’t use middlewares
● Implement graceful shutdown
● Limit concurrency (async queue or semaphore)
Important for Enterprise
● Business needs quick prototyping (TTM)
● We need security audit and certifications,
so get rid of dependencies
● Enterprise prefers low-code
● Modeling visualisation
(BPMN, ERD, state diagram, process flow)
Layered (onion) Architecture
Domain
model
Domain services
Application services
Presentation
Infrastructure
Persistence
Postgres
Redis
External API
Logger
Configs
Scheduler
Health mon
Validation
Cryptography
Sessions
App firewall
AAA
Web UI
Mobile UI
API gateway
Middleware: big ball of mud
models
controllers
logger
configs
AAA
validation
cryptography
sessions
routing
middlewares
db
configs
rendering
ORM antipattern
models
controllers
logger
configs
AAA
validation
cryptography
sessions
routing
middlewares
ORM
db
configs
rendering
Express architecture
models
controllers
logger
configs
AAA
validation
cryptography
sessions
routing
middlewares
ORM
db
configs
rendering
High coupling
● References are passed to other parts of the
application (examples: req, res, socket, person,
payment, logger, session, scheduler...)
● Passed objects mutations due to mixins will
breaks our expectations
● Remaining references are visible from contexts
so memory leaks and we need restarts
“Talk is cheap.
Show me the code.”
What we get
● Framework-agnostic application
● Transport-agnostic communications
● No race conditions in asynchronous code
● No memory leaks and resource leaks
● Errors are handled properly
● Code reuse, no code duplication
● A few and reliable dependencies
What we get
● DI (dependency-injection)
● Automatic routing (directory based)
● Context isolation
● Parse cookie without middlewares
● Sessions without middlewares
● Authentication without middlewares
● Concurrency control with semaphores
graceful shutdown
metawatch
semaphore
contract checking
metaschema
Schema-centric approach
Domain model
Schema
Domain services External interfaces
DB structure
API specs
Data structs
Validation
Use cases
BL Scenarios
User interfaces
Web UI
Mobile UI
Reporting
Schemas example
Schemas/SystemUser.js
({
login: { type: 'string', unique: true, length: 30 },
password: { type: 'string', length: 10 },
fullName: { 'string' required: false },
});
SystemUser
SystemGroup SystemSession
Schemas example
Schemas/SystemGroup.js
({
name: { type: 'string', unique: true },
users: { many: 'SystemUser' },
});
SystemUser
SystemGroup SystemSession
Schemas example
Schemas/SystemSession.js
({
user: 'SystemUser',
token: { type: 'string', unique: true },
ip: 'string',
data: 'json',
});
SystemUser
SystemGroup SystemSession
Autogenerated SQL DDL
CREATE TABLE "SystemUser" (
"systemUserId" bigint generated always as identity,
"login" varchar(30) NOT NULL,
"password" varchar(10) NOT NULL,
"fullName" varchar
);
ALTER TABLE "SystemUser"
ADD CONSTRAINT "pkSystemUser"
PRIMARY KEY ("systemUser");
Autogenerated SQL DDL
CREATE TABLE "SystemGroup" (
"systemGroupId" bigint generated always as identity,
"name" varchar NOT NULL
);
ALTER TABLE "SystemGroup"
ADD CONSTRAINT "pkSystemGroup"
PRIMARY KEY ("systemGroup");
Autogenerated SQL DDL
CREATE TABLE "SystemGroupSystemUser" (
"systemGroupId" bigint NOT NULL,
"systemUserId" bigint NOT NULL
);
ALTER TABLE "SystemGroupSystemUser"
ADD CONSTRAINT "pkSystemGroupSystemUser"
PRIMARY KEY ("systemGroupId", "systemUserId");
Autogenerated SQL DDL
ALTER TABLE "SystemGroupSystemUser"
ADD CONSTRAINT "fkSystemGroupSystemUserSystemGroup"
FOREIGN KEY ("systemGroupId")
REFERENCES "SystemGroup" ("systemGroupId");
ALTER TABLE "SystemGroupSystemUser"
ADD CONSTRAINT "fkSystemGroupSystemUserSystemUser"
FOREIGN KEY ("systemUserId")
REFERENCES "SystemUser" ("systemUserId");
Autogenerated SQL DDL
CREATE TABLE "SystemSession" (
"systemSessionId" bigint generated always as identity,
"userId" bigint NOT NULL,
"token" varchar NOT NULL,
"ip" varchar NOT NULL,
"data" jsonb NOT NULL
);
ALTER TABLE "SystemSession"
ADD CONSTRAINT "pkSystemSession"
PRIMARY KEY ("systemSession");
Autogenerated SQL DDL
ALTER TABLE "SystemSession"
ADD CONSTRAINT "fkSystemSessionUser"
FOREIGN KEY ("userId")
REFERENCES "SystemUser" ("systemUserId");
Autogenerated typings
interface SystemUser {
systemUserId: number;
login: string;
password: string;
fullName: string;
}
interface SystemGroup {
systemGroupId: number;
name: string;
}
Autogenerated typings
interface SystemSession {
systemSessionId: number;
userId: number;
token: string;
ip: string;
data: string;
}
Powered by schemas
● Contracts and data-structures validation
● Autogenerated .d.ts typings
● SQL DDL (database structure)
● Automated-migrations and structure versioning
● Scaffolding for DB access
● UI (web and mobile)
● Declarative data projections and aggregations
GRASP
General responsibility assignment software
patterns
“Applying UML and Patterns: An Introduction to
Object-Oriented Analysis and Design and Iterative
Development” // Craig Larman
GRASP
General responsibility assignment software
patterns
• Low Coupling • High Cohesion
• Information Expert • Creator
• Controller • Polymorphism
• Pure Fabrication • Indirection
• Protected Variations
GRASP: Information Expert
Problem: What is a basic principle by which to
assign responsibilities to objects?
Solution: Assign responsibility to the class that has
the information needed to fulfill it.
Benefits: Low Coupling, High Cohesion, Code
simplicity, Better encapsulation, Code reuse.
GRASP: Cohesion & Coupling
Cohesion (связность)
inside class, module,
component. etc.
Coupling (зацепление)
between classes
and other components
GRASP: Creator
Problem: Who creates object instance?
(who holds reference or destroy it)
Solution: composition containers (who aggregate
instances), who works with it and closely use it,
who have initializing information for instances.
Benefits: Low Coupling
Examples: constructor, factory, object pool.
GRASP: Controller
Problem: Who should be responsible for handling
an input system event?
Solution: Controller - communication entry point,
all system operations; delegates BL.
Benefits: protection, handle concurrency,
asynchronity, and parallel programming issues.
Examples: command, facade, layer isolation.
GRASP: Polymorphism
Polymorphism - alternative behaviour based on
type (see SOLID: LSP, OCP).
Problem: how to handle behavioral alternatives
based on type (or class)?
Solution: assign responsibility to the classes,
select one of type/class instead of if-statements,
access by interface or abstract class.
GRASP: Indirection
Indirection - intermediate object will decrease
coupling between two abstractions.
Benefits: Low Coupling, Code reuse.
Examples: GoF Mediator pattern (посредник),
MVC, С - controller.
GRASP: Pure fabrication
Pure fabrication - an abstraction that does not
exist in the subject area. It often reduces the
overlapping of domain classes.
Examples: Socket, DB Query, EventEmitter,
Promise, Asynchronous queue.
GRASP: Protected variations
Problem: How to design objects, subsystems, and
systems so that the variations or instability in
these elements does not have an undesirable
impact on other elements?
Solution: Identify points of predicted variation or
instability; assign responsibilities to create a stable
interface around them.
Summarize the approach
● Architecture: DDD and clean code, layered
architecture, domain in the middle
● Principles and patterns: GRASP, SOLID, GoF,
IoC, DI, coupling и cohesion, Law of Demeter
● Project structure: framework-agnostic
● Techniques: error handling, asynchronous and
parallel programming, metaprogramming...
LoD (Law of Demeter)
● Module should “knows” less about others
(low coupling), access through interfaces (ISP)
● All components communicates only with
neighbors and talks explicitly
● A class method works with its arguments,
other methods and properties of the instance
and its first-level structural parts
What we get
● Code reuse, no boilerplate
● A few and reliable dependencies
(pg 803 kb, ws 118 kb = 921 kb)
● System code 6 kb, applied code: 837 b
● Metarhia (5 June): 286 kb (JavaScript: 155 kb)
● Characteristics: Portability, Reliability, Security,
Isolation, Maintainability, High Availability
timur.shemsedinov@gmail.com
github.com/tshemsedinov
youtube.com/TimurShemsedinov
Largest Node.js and JavaScript course
github.com/HowProgrammingWorks/Index
t.me/HowProgrammingWorks
t.me/NodeUA
github.com/metarhia

Node.js for enterprise - JS Conference

  • 1.
    Node.js for Enterprise Chief TechnologyArchitect at Metarhia CTO at Salucyber, Lecturer at KPI & KSE github.com/tshemsedinov Timur Shemsedinov
  • 2.
    Is Node.js readyfor Enterprise?
  • 3.
    Is Node.js readyfor Enterprise? Yes, sure
  • 4.
    Is Node.js readyfor Enterprise? Yes, sure Node.js is ready
  • 5.
    Is Node.js readyfor Enterprise? Yes, sure Node.js is ready But JavaScript developers...
  • 6.
    Is Node.js readyfor Enterprise? Yes, sure Node.js is ready But JavaScript developers are not
  • 7.
    New features ● Multithreadingfor calculations and scale (added in v10, stable in v12) ● WASI, Node-API 8, V8 v9 for Node.js v16, npm 7 ● API: diagnostic API, perf_hooks, timer promises, AbortController, vm, v8, scrypt, Web crypto api, async_hooks, AsyncLocalStorage, etc. ● QUIC or HTTP/3 especially for mobile and 5G
  • 8.
    Monkey job Everything repeatsevery time we start a project ● Let’s discuss scaling, we expect highload ● We need microservices, REST and ORM ● People, vision and setup processes ● Application architecture and structure ● Select tools, libraries, frameworks ● Code conventions, repository maintenance
  • 9.
    Node.js challenges ● Enterpriserequirements: Reliability, Maintainability, High Availability, Security, Isolation, Compatibility ● Community culture: meetups, conferences, fundamental SC knowledge, consensus ● Reputation and trust: education, certification, success stories
  • 10.
  • 11.
    With the codeof your colleagues
  • 12.
  • 13.
    Application in Node.jsruntime libuv V8 openssl zlib c-ares llhttp
  • 14.
  • 15.
    How to thinkabout you code It’s glue and business-logic code Semantically and syntactically flexible Very expressive (you can create DSL) Simple for maintenance and changes Simple and readable for everyone Works everywhere Easy to integrate
  • 16.
    Engineering culture ● Architecture:DDD and clean code, layered architecture, domain in the middle ● Principles and patterns: GRASP, SOLID, GoF, IoC, DI, coupling и cohesion, Law of Demeter ● Project structure: framework-agnostic ● Techniques: error handling, asynchronous and parallel programming, metaprogramming...
  • 17.
    Important aspects ● Applicationis the place for applied code ● Declarative code is better than imperative ● State: reliability, performance, interactivity ● Configuration and infrastructure in the code ● Getting rid of dependencies ● We use layered architecture
  • 18.
    Related to Node.js ●Context isolation and v8 sandboxes ● Don’t block event-loop ● Avoiding race conditions and leaks ● Avoid reference pollution and mixins ● Don’t use middlewares ● Implement graceful shutdown ● Limit concurrency (async queue or semaphore)
  • 19.
    Important for Enterprise ●Business needs quick prototyping (TTM) ● We need security audit and certifications, so get rid of dependencies ● Enterprise prefers low-code ● Modeling visualisation (BPMN, ERD, state diagram, process flow)
  • 20.
    Layered (onion) Architecture Domain model Domainservices Application services Presentation Infrastructure Persistence Postgres Redis External API Logger Configs Scheduler Health mon Validation Cryptography Sessions App firewall AAA Web UI Mobile UI API gateway
  • 21.
    Middleware: big ballof mud models controllers logger configs AAA validation cryptography sessions routing middlewares db configs rendering
  • 22.
  • 23.
  • 24.
    High coupling ● Referencesare passed to other parts of the application (examples: req, res, socket, person, payment, logger, session, scheduler...) ● Passed objects mutations due to mixins will breaks our expectations ● Remaining references are visible from contexts so memory leaks and we need restarts
  • 25.
    “Talk is cheap. Showme the code.”
  • 26.
    What we get ●Framework-agnostic application ● Transport-agnostic communications ● No race conditions in asynchronous code ● No memory leaks and resource leaks ● Errors are handled properly ● Code reuse, no code duplication ● A few and reliable dependencies
  • 27.
    What we get ●DI (dependency-injection) ● Automatic routing (directory based) ● Context isolation ● Parse cookie without middlewares ● Sessions without middlewares ● Authentication without middlewares ● Concurrency control with semaphores
  • 28.
  • 29.
    Schema-centric approach Domain model Schema Domainservices External interfaces DB structure API specs Data structs Validation Use cases BL Scenarios User interfaces Web UI Mobile UI Reporting
  • 30.
    Schemas example Schemas/SystemUser.js ({ login: {type: 'string', unique: true, length: 30 }, password: { type: 'string', length: 10 }, fullName: { 'string' required: false }, }); SystemUser SystemGroup SystemSession
  • 31.
    Schemas example Schemas/SystemGroup.js ({ name: {type: 'string', unique: true }, users: { many: 'SystemUser' }, }); SystemUser SystemGroup SystemSession
  • 32.
    Schemas example Schemas/SystemSession.js ({ user: 'SystemUser', token:{ type: 'string', unique: true }, ip: 'string', data: 'json', }); SystemUser SystemGroup SystemSession
  • 33.
    Autogenerated SQL DDL CREATETABLE "SystemUser" ( "systemUserId" bigint generated always as identity, "login" varchar(30) NOT NULL, "password" varchar(10) NOT NULL, "fullName" varchar ); ALTER TABLE "SystemUser" ADD CONSTRAINT "pkSystemUser" PRIMARY KEY ("systemUser");
  • 34.
    Autogenerated SQL DDL CREATETABLE "SystemGroup" ( "systemGroupId" bigint generated always as identity, "name" varchar NOT NULL ); ALTER TABLE "SystemGroup" ADD CONSTRAINT "pkSystemGroup" PRIMARY KEY ("systemGroup");
  • 35.
    Autogenerated SQL DDL CREATETABLE "SystemGroupSystemUser" ( "systemGroupId" bigint NOT NULL, "systemUserId" bigint NOT NULL ); ALTER TABLE "SystemGroupSystemUser" ADD CONSTRAINT "pkSystemGroupSystemUser" PRIMARY KEY ("systemGroupId", "systemUserId");
  • 36.
    Autogenerated SQL DDL ALTERTABLE "SystemGroupSystemUser" ADD CONSTRAINT "fkSystemGroupSystemUserSystemGroup" FOREIGN KEY ("systemGroupId") REFERENCES "SystemGroup" ("systemGroupId"); ALTER TABLE "SystemGroupSystemUser" ADD CONSTRAINT "fkSystemGroupSystemUserSystemUser" FOREIGN KEY ("systemUserId") REFERENCES "SystemUser" ("systemUserId");
  • 37.
    Autogenerated SQL DDL CREATETABLE "SystemSession" ( "systemSessionId" bigint generated always as identity, "userId" bigint NOT NULL, "token" varchar NOT NULL, "ip" varchar NOT NULL, "data" jsonb NOT NULL ); ALTER TABLE "SystemSession" ADD CONSTRAINT "pkSystemSession" PRIMARY KEY ("systemSession");
  • 38.
    Autogenerated SQL DDL ALTERTABLE "SystemSession" ADD CONSTRAINT "fkSystemSessionUser" FOREIGN KEY ("userId") REFERENCES "SystemUser" ("systemUserId");
  • 39.
    Autogenerated typings interface SystemUser{ systemUserId: number; login: string; password: string; fullName: string; } interface SystemGroup { systemGroupId: number; name: string; }
  • 40.
    Autogenerated typings interface SystemSession{ systemSessionId: number; userId: number; token: string; ip: string; data: string; }
  • 41.
    Powered by schemas ●Contracts and data-structures validation ● Autogenerated .d.ts typings ● SQL DDL (database structure) ● Automated-migrations and structure versioning ● Scaffolding for DB access ● UI (web and mobile) ● Declarative data projections and aggregations
  • 42.
    GRASP General responsibility assignmentsoftware patterns “Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development” // Craig Larman
  • 43.
    GRASP General responsibility assignmentsoftware patterns • Low Coupling • High Cohesion • Information Expert • Creator • Controller • Polymorphism • Pure Fabrication • Indirection • Protected Variations
  • 44.
    GRASP: Information Expert Problem:What is a basic principle by which to assign responsibilities to objects? Solution: Assign responsibility to the class that has the information needed to fulfill it. Benefits: Low Coupling, High Cohesion, Code simplicity, Better encapsulation, Code reuse.
  • 45.
    GRASP: Cohesion &Coupling Cohesion (связность) inside class, module, component. etc. Coupling (зацепление) between classes and other components
  • 46.
    GRASP: Creator Problem: Whocreates object instance? (who holds reference or destroy it) Solution: composition containers (who aggregate instances), who works with it and closely use it, who have initializing information for instances. Benefits: Low Coupling Examples: constructor, factory, object pool.
  • 47.
    GRASP: Controller Problem: Whoshould be responsible for handling an input system event? Solution: Controller - communication entry point, all system operations; delegates BL. Benefits: protection, handle concurrency, asynchronity, and parallel programming issues. Examples: command, facade, layer isolation.
  • 48.
    GRASP: Polymorphism Polymorphism -alternative behaviour based on type (see SOLID: LSP, OCP). Problem: how to handle behavioral alternatives based on type (or class)? Solution: assign responsibility to the classes, select one of type/class instead of if-statements, access by interface or abstract class.
  • 49.
    GRASP: Indirection Indirection -intermediate object will decrease coupling between two abstractions. Benefits: Low Coupling, Code reuse. Examples: GoF Mediator pattern (посредник), MVC, С - controller.
  • 50.
    GRASP: Pure fabrication Purefabrication - an abstraction that does not exist in the subject area. It often reduces the overlapping of domain classes. Examples: Socket, DB Query, EventEmitter, Promise, Asynchronous queue.
  • 51.
    GRASP: Protected variations Problem:How to design objects, subsystems, and systems so that the variations or instability in these elements does not have an undesirable impact on other elements? Solution: Identify points of predicted variation or instability; assign responsibilities to create a stable interface around them.
  • 52.
    Summarize the approach ●Architecture: DDD and clean code, layered architecture, domain in the middle ● Principles and patterns: GRASP, SOLID, GoF, IoC, DI, coupling и cohesion, Law of Demeter ● Project structure: framework-agnostic ● Techniques: error handling, asynchronous and parallel programming, metaprogramming...
  • 53.
    LoD (Law ofDemeter) ● Module should “knows” less about others (low coupling), access through interfaces (ISP) ● All components communicates only with neighbors and talks explicitly ● A class method works with its arguments, other methods and properties of the instance and its first-level structural parts
  • 54.
    What we get ●Code reuse, no boilerplate ● A few and reliable dependencies (pg 803 kb, ws 118 kb = 921 kb) ● System code 6 kb, applied code: 837 b ● Metarhia (5 June): 286 kb (JavaScript: 155 kb) ● Characteristics: Portability, Reliability, Security, Isolation, Maintainability, High Availability
  • 55.
    timur.shemsedinov@gmail.com github.com/tshemsedinov youtube.com/TimurShemsedinov Largest Node.js andJavaScript course github.com/HowProgrammingWorks/Index t.me/HowProgrammingWorks t.me/NodeUA github.com/metarhia