- Imperative Programming
- Characteristics: statements mutate program state directly (let, loops, assignments)
- Architecture Influence: stateful services, command-driven architecture
- Procedural Programming
- Characteristics: step-by-step, linear control flow, mutable state
- Architecture Influence: transaction script, single responsibility units, shallow call graphs
- Object-Oriented Programming
- Characteristics: classes/objects, encapsulation, inheritance, polymorphism
- Architecture Influence: DDD, layered architecture, clean architecture, hexagonal
- Prototype-based Programming
- Characteristics: objects inherit from other objects, delegation over inheritance
- Architecture Influence: flexible object composition, dynamic plugin systems
- Functional Programming
- Characteristics: pure functions, immutability, no shared state, higher-order functions, pattern matching, curry, single argument functions, composition
- Architecture Influence: functional pipelines, stateless services, async stream processing
- Closure-based Programming
- Characteristics: functions hold private state via closures, encapsulated behavior
- Architecture Influence: lightweight encapsulation, reactive units, factory patterns
- Actor Model
- Characteristics: message passing, no shared memory, isolated context, transparent concurrency units
- Architecture Influence: distributed systems, concurrency-safe services, microservices
- Structural Programming
- Blocks, No goto
- Declarative Programming
- Characteristics: emphasizes what over how, side-effect free, high-level code, DSLs, self-descriptive
- Architecture Influence: configuration-over-code, rule engines
- Contract programming
- Characteristics: difine contracts
- Architecture Influence: stable and clear, self-descriptive
- Reactive Programming
- Characteristics: observable streams, event-driven, push-based, backpressure-aware
- Architecture Influence: UIs, data stream processing, feedback loops, real-time pipelines
- Finite-State Machines / Automata
- Characteristics: explicit states, transitions, events, deterministic flow
- Architecture Influence: workflow engines
- Metaprogramming
- Characteristics: code generation, reflection, macros, introspection
- Architecture Influence: high flexibility, scaffolding
- Control Flow
- Statements, algorithm steps
constuser=read({id: 15});if(user.name==='marcus'){console.log(user.age);}
- Expression
({ id })=>(fn)=>fn({ id,name: 'marcus',age: 42})({id: 15})(({ name, age })=>name==='marcus' ? (log)=>log(age) : ()=>{})(console.log);
- Do-notation
Do({id: 15}).chain(({ id })=>({ id,name: 'marcus',age: 42})).chain(({ name, age })=>name==='marcus' ? (log)=>log(age) : ()=>{}).run()(console.log);
- Declarative style
execute({read: {id: 15},then: {match: {name: 'marcus'},success: {effect: {log: 'age'}},fail: {effect: 'noop'},},})(reader,console.log)();
- Pipeline operator
(({id: 15})|>read|>(({ name, age })=>name==='marcus' ? (log)=>log(age) : ()=>{}))(console.log);
- Pipe (composition)
pipe({id: 15},read,({ name, age })=>name==='marcus' ? (log)=>log(age) : ()=>{})(console.log);
- Identifiers
- Assignment statement
leta=10;constb=20;a=a+b;
- Call arguments
((a,b)=>a+b)(5,3);
- Only callable
consta=()=>10;constb=()=>20;constsum=(x,y)=>()=>x()+y();constc=sum(a,b);
- State
- Mutable state and form
constcounter={value: 0};counter.value+=1;
- Mutable form
counter.ready=true;
- Immutable state
constpoint=Object.freeze({x: 10,y: 20});constmove=(p)=>({ x, y })=>({x: p.x+x,y: p.y+y});constmoved=move(point)({x: 3,y: 7});
- Copy-on-write
constp1={x: 10,y: 20};constp2=Object.create(p1);p2.x=7;
- Stateless functions
consttwice=(x)=>x*2;
- Context
- Objects
constpoint={x: 10,y: 20,move(dx,dy){this.x+=dx;this.y+=dy;}};
- Records
constpoint={x: 10,y: 20};constmove=(p,d)=>{p.x+=d.x;p.y+=d.y;};
- Closures
constcreateCounter=(count=0)=>()=>++count;
- Boxing
constprimitive=42;constinstance=newNumber(42);constboxed=Box.of(42);
- Containers
Box.of(42);Either.right(42);Promise.resolve(42);letmaybe: number|null=42;typePair={a?: number;b?: number};typeOption<T>={kind: 'some'; value: T}|{kind: 'none'}; std::optional<int>; std::tuple<int>; std::reference_wrapper<int>;Nullable<int>maybe=42;newStrongBox<int>(value);Tuple.Create(myIntValue);
- Modules
constcache=newMap();exportconstget=(key)=>cache.get(key);exportconstset=(key,value)=>cache.set(key,value);
- Branching
- Conditional statement
if(x>0){console.log('positive');}elseif(x<0){console.log('negative');}else{console.log('zero');}
- Conditional expression
constsign=x>0 ? 'positive' : x<0 ? 'negative' : 'zero';
- Guards
constprocess=(x)=>{if(x===null)returnnull;if(x<0)returnnull;returnx*2;};
func process(_ x:Int?)->Int?{guardlet v = x else{returnnil}guard v >=0else{returnnil}return v *2}
- Pattern matching
fnprocess(x:Option<i32>) -> Option<i32>{match x {None => None,Some(v)if v < 0 => None,Some(v) => Some(v *2),}}
constmatch=(variant,handlers)=>handlers[variant.tag](variant);match({tag: 'point',x: 10,y: 20},{point: ({ x, y })=>`(${x}, ${y})`,circle: ({ r })=>`radius: ${r}`});
- Iteration
- Loops (for, while, do)
for(leti=0;i<10;i++)console.log(i);while(condition){/* steps */}do{/* steps */}while(condition);
- Recursion calls (incl. tail recursion)
constfactorial=(n)=>n<=1 ? 1 : n*factorial(n-1);consttailFact=(n,acc=1)=>n<=1 ? acc : tailFact(n-1,n*acc);
- Iterators / Generators
function*range(start,end){for(leti=start;i<end;i++)yieldi;}for(constnofrange(0,5))console.log(n);
- Streams For Node.js
constres=awaitfetch('/api/endpoint');forawait(constchunkofres.body)console.log(newTextDecoder().decode(chunk));
constr=Readable.from(gen());
- Instantiation
- Operator
newconstpoint=newPoint(10,20);
- Creational patterns like Factory, Builder
constp=Point.create(10,20);constq=awaitQuery.select('cities').where({country: 10}).order('population');
- Closures
constp=createPoint(10,20);constq=awaitselect('cities').where({country: 10}).order('population');
- Containers
classMaybe<T=unknown>{constructor(value?: T);getvalue(): T|undefined;isEmpty(): boolean;match<R>(some: (value: T)=>R,none: ()=>R): R;}
- Cloning
constclone1={ ...original};constclone2=Object.assign({},original);constclone3=structuredClone(original);
- Pattern GOF:Flyweight
- Inheritance
- Classes
classSavingAccountextendsAccount
- Interfaces (
implements)classCursorimplementsIterator<Account>
- Prototype programming
constlogger=Object.create(console,{log: {value: (s)=>process.write(s)}});
- Mixins
constlogger={};logger.log=console.log;Object.assign(logger,{info: ()=>{}});
- Structural composition
classLogger{constructor(name){this.stream=fs.createWriteStream(name);}}
- Partial/Curry
constadd=(a,b)=>a+b;{constadd5=(b)=>add(5,b);}constcurriedAdd=(a)=>(b)=>a+b;{constadd5=curriedAdd(5);}{constadd5=add.bind(add,null,5);}
- Traits TypeScript alternative
pubtraitToJson{fnto_json(&self) -> String;}pubstructUser{pubid:u32,pubname:String,}implToJsonforUser{fnto_json(&self) -> String{format!(r#"{{"id":{},"name":"{}"}}"#,self.id,self.name)}}
interfaceToJson{toJson: ()=>string}classUserimplementsToJson{readonlyid: numberreadonlyname: stringconstructor(id: number,name: string){this.id=idthis.name=name}toJson=(): string=>{return`{"id":${this.id},"name":"${this.name}"}`}}
- Primitive values
- Scalars
constnumber=42;
- Boxing
constnumber=42;constboxed=Object(number);constunboxed=Number(boxed);
- Value Objects
classInteger{privatereadonlyvalue: number;// implement constructor and math operations}consta=newInteger(7);constb=newInteger(3);constc=a.add(b);
- Containers
- Asynchronity
- Callback
constfetchData=(callback)=>setTimeout(()=>callback('data'),100);fetchData((result)=>console.log(result));
- Promise
constfetchData=()=>Promise.resolve('data');fetchData().then((result)=>console.log(result));
- Async/await
constdata=awaitfetchData();
- Future, Task
constfs=require('node:fs');constfuturify=(fn)=>(...args)=>newFuture((reject,resolve)=>fn(...args,(error,result)=>error ? reject(error) : resolve(result)),);constreadFuture=futurify(fs.readFile);constwriteFuture=futurify(fs.writeFile);readFuture('future.js','utf8').map((text)=>text.toUpperCase()).chain((text)=>writeFuture('future.md',text)).fork((error)=>console.error('FS error:',error),()=>console.log('Done'),);
- Async compose
constprepareReport=pipe(read,parse,calculate,render);constchecks=parallel(checkBalance,checkAvailability,checkFraud);
- Observer (EventEmitter, EventTarget, Signal)
- Streams and other abstractions
- Purity
- Pure functions
constadd=(a,b)=>a+b;constsquare=(x)=>x*x;
- Functions with side effects
letcounter=0;constincrement=()=>++counter;
- IO monads
- First-class citizens
- Higher-order functions
- Passing behaviour as object
- Evaluation Flow
- Function composition
- Nested calls
- Pipeline
|>constresult=input|>validate|>transform|>process;
- Point style
- Point-free style:
const f = compose(g, h) - Point style:
const f = (x) => g(h(x))
- Dependencies
- Pass all dependencies as arguments
constcreateService=(db,logger)=>{/* implementation */};
- Dependency injection
classService{constructor(db,logger){this.db=db;this.logger=logger;}}
- Global namespaces
constuser=application.auth.getUser('marcus');
- Service locators
constServiceLocator={services: {},register(name,service){this.services[name]=service;},get(name){returnthis.services[name];}};
- Module systems
- Structural Control (see Branching)
- Nested
if/elseconditionalsif(x>0){if(x>10){console.log('large');}else{console.log('small');}}else{console.log('negative');}
- Pattern matching
- Guards
- Error handling
- Total functions
constsafeDivide=(a,b)=>a/b;
- Throwing exceptions
constdivide=(a,b)=>{if(b===0)thrownewError('Division by zero');returna/b;};
- Error codes
- Return
null,undefined,NaN - Null objects
constnullUser={name: 'Guest',isAuthenticated: false,login: ()=>{}};constuser=getUser()??nullUser;
- Option / Either / Result / Promise
classEither<L=unknown,R=unknown>{constructor(params: {left?: L|null;right?: R|null});staticleft<L>(value: L): Either<L,null>;staticright<R>(value: R): Either<null,R>;getleft(): L|null;getright(): R|null;isLeft(): boolean;isRight(): boolean;map<U>(fn: (value: R)=>U): Either<L,U>;match<T>(leftFn: (left: L)=>T,rightFn: (right: R)=>T): T;}
- Stability of Effects
- Idempotent operations
new Set().add(3).add(3) - Order-sensitive operations
((a) => (a.push(3), a.push(7), a))([]) - Commutative / associative operations
add(a, b) === add(b, a)
- Semantic Transparency
- Non-Referential transparent
classCounter{ #value =0;inc=()=>(++this.#value);}
- Referential transparency
classCounter{ #value;constructor(value=0){this.#value =value;}inc=()=>newCounter(this.#value +1);value=()=>this.#value;}
- Equational reasoning
constf=(x)=>x*2;constg=(x)=>x+1;// f(g(x)) === (x + 1) * 2 === 2x + 2// Can reason about code as equations
- Deterministic evaluation
constpure=(x)=>x*2;constimpure=()=>Math.random();
- No hidden state
- Caching
- Hash-table caching
constcache=newMap();constget=(key)=>cache.get(key);constset=(key,value)=>cache.set(key,value);
- Memoization
constfib=memoize((n)=>n<=1 ? n : fib(n-1)+fib(n-2));
- Resource Control
- Manual destruction
classResource{constructor(){this.handle=acquire();}dispose(){release(this.handle);}}constresource=newResource();try{// use resource}finally{resource.dispose();}
- RAII / disposables New JavaScript Disposables:
constusing=(resource,fn)=>{try{returnfn(resource);}finally{resource.dispose();}};
Symbol.dispose,Symbol.asyncDisposeconstmain=async()=>{awaitusinglogger=awaitnewLogger('output.log');awaitlogger.log('Open');awaitlogger.log('Do something');};
- Region-based allocation
constwithRegion=(fn)=>{constregion=[];try{returnfn(region);}finally{region.forEach(cleanup);}};
- Ownership allocate/free
- Concurrency Model
- Shared-memory concurrency
- Stateless functions
- Message passing (Actor model)
- Transactional memory
- Locking, Semaphor, Mutex
- Data Ownership
- Copy semantics
- Move semantics
- Shared vs exclusive references
- Granularity
- One-liners
- Long code blocks
- Moderate granularity
constgetTomorrowDate=()=>{consttimeout=86400000;returnnewPromise((resolve)=>{setTimeout(()=>{resolve(newDate());},timeout)});};constCoin=(v)=>({map: (f)=>Coin(f(v))});constflip=()=>crypto.getRandomValues(newUint8Array(1))[0];Coin(flip()).map((r)=>(r&1 ? '🪙' : '💩')).map(console.log);constfindMeaningOfLife=()=>{constoffset=0;constdelay=Infinity;returnnewPromise((resolve)=>{setTimeout(()=>{resolve(42+offset);},delay);});};classComing{constructor(){returnnewPromise((resolve)=>setTimeout(()=>{resolve(this);},DAY_OF_JUDGMENT-Date.now()));}}constsecondComing=awaitnewComing();((<Fextends()=>void>(Function: F={}asF)=>Function())())classFuture{constructor(){const{name: key}=this.constructor;constvalue=void[].length;thrownewError(`${key} is ${value}`);}}newFuture();