-
Notifications
You must be signed in to change notification settings - Fork 9
Open
Description
Ciao a tutti,
propongo un talk sull'AOP (Aspect Oriented Programming) in JavaScript, ho sviluppato una libreria apposita (AOPlà) che permette di facilitare il lavoro con i cosiddetti "cross-cutting concerns" e mi piacerebbe condividere la mia esperienza, sempre che l'argomento possa interessare a qualcuno.
Gli argomenti trattati:
- Che cos'è l'AOP e quando può aver senso utilizzare questo paradigma lavorando con codice OOP;
- Come creare aspetti utilizzando AOPlà e implementare funzionalità riusabili come caching, logging, ecc...;
- Quali alternative ad AOPlà sono presenti ad oggi sempre nel mondo JavaScript e quali sono le principali differenze;
- Under the hood, com'è implementata AOPlà e che cosa c'è effettivamente sotto il cofano: Proxy composition tramite ES6 Proxy API con
pigretto, i decorator in JavaScript (legacy/stage-1estage-2), design pattern come Chain of Responsibility;
Di seguito un piccolo esempio di come si può implementare una funzionalità di caching (molto semplificata) senza e con la libreria.
Senza AOPlà:
class SomeService {
/**
* Sample cache.
*/
cache = void 0;
cacheInterval = void 0;
/**
* Sample method which performs a heavy computation, each time caching the result for subsequent calls
* with a TTL (Time To Live) of 5 seconds.
*/
async performHeavyComputation() {
if (this.cache) {
// Cache hit:
console.log("Cache hit!");
await this.cache;
return;
}
// Cache miss:
console.log("Cache miss...");
// Business logic code:
await new Promise(
(resolve) => setTimeout(resolve, 8000) // Heavy computation timeout.
);
// Ugly cache management code mixed with business logic code:
console.log("Caching.");
this.cache = Promise.resolve();
this.cacheInterval && clearInterval(this.cacheInterval);
this.cacheInterval = setTimeout(() => {
// Invalidating the cache after 5 seconds.
console.log("Cache invalidation.");
this.cache = void 0;
}, 5000);
}
}
// Run:
(async () => {
const someService = new SomeService();
// Cache miss.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
// Cache hit.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
// Waiting TTL expiration.
await new Promise((resolve) => setTimeout(resolve, 6000));
// Cache miss.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
// Cache hit.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
})();Con AOPlà:
import AOPla, { tag, aroundCall } from "aopla";
const Cacheable = tag("Cacheable");
class CacheAspect {
cache = void 0;
cacheInterval = void 0;
@aroundCall(Cacheable)
async advice({ proceed }) {
if (this.cache) {
// Cache hit:
console.warn("Cache hit!");
await this.cache;
return;
}
// Cache miss:
console.warn("Cache miss...");
await proceed();
// Cache management code only.
console.warn("Caching.");
this.cache = Promise.resolve();
this.cacheInterval && clearInterval(this.cacheInterval);
this.cacheInterval = setTimeout(() => {
// Invalidating the cache after 5 seconds.
console.warn("Cache invalidation.");
this.cache = void 0;
}, 5000);
}
}
AOPla.registerAspects(CacheAspect);
class SomeService {
/**
* Sample method which performs a heavy computation, no other fancy code.
*/
@Cacheable // Tagging this method as cacheable.
async performHeavyComputation() {
await new Promise(
(resolve) => setTimeout(resolve, 8000) // Heavy computation timeout.
);
}
}
// Run:
(async () => {
const someService = new SomeService();
// Cache miss.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
// Cache hit.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
// Waiting TTL expiration.
await new Promise((resolve) => setTimeout(resolve, 6000));
// Cache miss.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
// Cache hit.
await someService
.performHeavyComputation()
.then(() => console.log(`Heavy computation completed.`));
})();MarcoMengoli and hanna97
Metadata
Metadata
Assignees
Labels
No labels