Introducere: Provocarea notificării în SaaS

Produsele moderne SaaS se bazează pe notificări la timp, personalizate pentru a angaja utilizatorii, mentinerea de drive-uri, și comunicarea evenimentelor critice de sistem. Utilizatorii se așteaptă să primească alerte prin canalele lor preferate . Email, SMS, împinge notificări, în-appe mesaje, sau chiar webhooks la servicii terțe părți. Pe măsură ce produsul evoluează, numărul de canale crește, și gestionarea lor prin logica condiționată dispersate devine un coșmar de întreținere. O arhitectura curată, scalabilă este necesară.

Directus, un CMS fără cap și platforma backend, oferă o bază flexibilă pentru construirea aplicațiilor SaaS. Modelul său de date, Motorul debitelor și cârligele extensibile fac din acesta un mediu ideal pentru implementarea unui sistem robust de notificare. Prin aplicarea unui model de creație clasic . . Fabrica de model . Puteți să încapsulați logica de creare specifică canalului, să decuplați codul de afaceri de bază din detaliile de livrare, și adăugați fără efort noi canale ca produsul dumneavoastră mature.

Înţelegerea modelului de fabrică

Modelul de fabrică este un model de proiectare creațional care oferă o interfață pentru crearea obiectelor într-o super-clasă, dar permite subclaselor să modifice tipul de obiecte care vor fi create. Promovează cuplarea liberă și aderă la declarațiile Deschide/Closed Principle: entitățile software ar trebui să fie deschise pentru extensie, dar închise pentru modificare. În loc să-ți strice aplicația cu sau să decidă care obiect de notificare pentru instanție, vă deleagă această responsabilitate unei fabrici dedicate.

Acest model strălucește atunci când aveți o familie de obiecte conexe și tipul exact de instanțiere este determinat la rulare pe baza de intrare dinamică . Cum ar fi o preferințele de notificare utilizator sau evenimentul fiind declanșat. Într-un context de notificare, fiecare canal este un produs diferit . Dar toate au o interfață comună (de exemplu, o ] metodă.

Canale de notificare într-un produs SaaS

Printre canalele comune de notificare se numără:

  • Email
  • SMS
  • Anunțuri de presă
  • Notificările în cadrul App
  • Webhooks
  • Slack / Discord

Fără un model, codul tău ar putea arăta aşa:

function sendNotification(channel, message, recipient) {
 if (channel === 'email') {
 // Email logic here
 } else if (channel === 'sms') {
 // SMS logic here
 } else if (channel === 'push') {
 // Push logic here
 } else {
 throw new Error('Unknown channel');
 }
}

Această abordare funcționează pentru câteva canale, dar fiecare canal nou te forțează să-ți modifici funcția de trimitere și să retestezi toate logicile existente. Modelul fabricii elimină această fragilitate.

Punerea în aplicare a modelului de fabrică pentru notificări

Mai jos vom merge printr-o implementare TypeScript care poate fi adaptata pentru un SaaS Directus. TipScript este natural pentru Directus deoarece platforma in sine este construita cu ea si ofera un sistem de tip bogat.

1. Definirea interfeței de notificare

interface Notification {
 send(message: string, recipient: string): Promise<void>
}

2. Clase de notificare beton

class EmailNotification implements Notification {
 async send(message: string, recipient: string): Promise<void> {
 // Use Directus’s internal mailer or an external SDK
 console.log(`Sending email to ${recipient}: ${message}`);
 }
}

class SMSNotification implements Notification {
 async send(message: string, recipient: string): Promise<void> {
 // Call Twilio API
 console.log(`Sending SMS to ${recipient}: ${message}`);
 }
}

class PushNotification implements Notification {
 async send(message: string, recipient: string): Promise<void> {
 // Use Firebase or OneSignal SDK
 console.log(`Sending push to ${recipient}: ${message}`);
 }
}

3. Fabrica de notificare

type ChannelType = 'email' | 'sms' | 'push';

class NotificationFactory {
 static createNotification(channel: ChannelType): Notification {
 switch (channel) {
 case 'email':
 return new EmailNotification();
 case 'sms':
 return new SMSNotification();
 case 'push':
 return new PushNotification();
 default:
 throw new Error(`Unknown notification channel: ${channel}`);
 }
 }
}

4. Utilizarea fabricii în aplicaţia dumneavoastră

async function notifyUser(event: string, userId: string, channel: ChannelType) {
 const notification = NotificationFactory.createNotification(channel);
 await notification.send(event, userId);
}

Codul clientului nu trebuie să cunoască niciodată tipul de beton. Depinde doar de interfața . Această decuplare face ca testarea unității să fie simplă. Puteți să vă bateți joc de obiectul notificării fără să atingeți fabrica sau clasele de beton.

Integrarea modelului de fabrică cu Directus

Directus oferă mai multe puncte de intrare pentru declanșarea notificărilor:

  • Flows
  • Hooks
  • Cele mai bune puncte de trecere
  • Webhoks

Într-un proiect Directus, ați putea instala fabrica de notificare ca serviciu în interiorul unui modul personalizat sau ca extensie. De exemplu, în interiorul unei Flow] ați putea apela un obiectiv intern API care instanțiează canalul corect bazat pe preferințele stocate ale utilizatorului. Alternativ, puteți împacheta fabrica într-o hook] care trage după un nou sign-up utilizator și trimite un e-mail de bun venit, o confirmare SMS și o notificare de împingere către aplicația mobilă.

Deoarece fabrica trăiește într-un singur loc, puteți actualiza cartografiile sale fără a atinge fiecare cârlig sau flux. Și, din moment ce Directus Fluxuri poate trece date JSON arbitrare, puteți alimenta cu ușurință fabrica cu identificatori canal din baza de date.

Beneficiile abordării tipare a fabricii

Scalabilitate

Adăugând un nou canal înseamnă a scrie o nouă clasă care implementează și a adăuga o linie la declarația de comutare a fabricii. Nu sunt necesare modificări de cod ale clienților. Acest lucru este deosebit de valoros în produsele multi-tenante SaaS, unde chiriașii diferiți pot permite diferite seturi de canale.

Mentenabilitatea

Logica de livrare a notificării este izolată de logica de afaceri. Fiecare clasă de beton poate fi menținută independent. Dacă furnizorul de SMS își schimbă API-ul, modificați doar . Fabrica și toți consumatorii rămân neschimbate.

Testabilitatea

Puteți uni fiecare clasă de notificare în izolare, și puteți râde de interfața atunci când testați funcții de nivel superior. Fabrica însăși poate fi verificată cu un test simplu care verifică dacă returnează cazuri de tipul corect pentru fiecare canal.

Flexibilitate

Fabrica poate fi extinsa pentru a construi obiecte complexe. De exemplu, poate doriti sa treceti de configurare (chei API, politici de rejudecare) la momentul crearii. Puteti supraîncărca metoda fabricii sau puteti folosi un model Builder in interiorul fabricii pentru a asambla obiecte de notificare complet configurate. Variabilele de mediu direct sau setările bazei de date (de exemplu, un tabel sunt surse ideale pentru o astfel de configuratie.

Posibile retrageri și analize

În timp ce modelul fabricii este o unealtă puternică, nu este un glonţ de argint:

  • Dacă aveți doar două canale și nu aveți planuri de a adăuga mai mult, o condiție simplă ar putea fi în regulă. Modelul introduce fișiere și abstractii suplimentare.
  • Logica deciziei încă există:[ Fabrica însăşi foloseşte o declaraţie de comutare. Dacă aveţi zeci de canale, consideraţi un model de înregistrare în care canalele se autoînregistrează sau utilizează un model de strategie care schimbă algoritmii mai degrabă decât obiectele. Ambele pot completa fabrica.
  • Injecție de urgență: Dacă clasele de notificare depind de servicii externe (de exemplu, un client HTTP sau un logger), trebuie să vă injectați aceste dependențe. Fabrica trebuie fie să accepte un container DI, fie să primească dependențele ca parametri; ți-ai propus ceva pentru timpuriu.

Într-o extensie Directus, puteți pârghie de injectare de dependență built-in (] funcție și servicii) pentru a trece în situații comune, cum ar fi logger sau acces de baze de date la fabrică.

Exemplu real-World: Notificări multiple în cadrul unui B2B SaaS

Luați în considerare un instrument de gestionare a proiectelor construit pe Directus. Atunci când este atribuită o sarcină, sistemul trebuie să notifice:

  • persoana împuternicită să facă obiectul unei cereri de autorizare prin e-mail (dacă preferă acest lucru)
  • asignatul prin intermediul unui toast în aplicație
  • canalul de proiect pe Slack

Folosind fabrica, codul sub un cârlig Directus devine:

import { NotificationFactory } from './services/NotificationFactory';

async function onTaskCreate(payload, { accountability }) {
 const { assigneeId } = payload;
 const userPreferences = await getUserNotificationPreferences(assigneeId);
 for (const channel of userPreferences.channels) {
 const notifier = NotificationFactory.createNotification(channel);
 await notifier.send(`You have a new task!`, assigneeId);
 }
}

Fiecare clasă de notificare se ocupă de propria livrare idiomatică. Fabrica rămâne singura sursă de adevăr pentru cartografierea canalului.

Pentru a vedea o implementare completă a unui astfel de sistem, se referă la Dirous

Concluzie

Fabrica de model oferă o modalitate curată, de întreținere pentru a gestiona canale multiple de notificare într-un produs SaaS. Prin încapsularea creației de obiecte, vă decuplați logica de aplicare de bază de la specificul de livrare, ceea ce face ușor de a adăuga, elimina, sau modifica canalele fără efecte de undă peste baza de cod. Atunci când combinat cu Directus flexibil cârlige și fluxuri, veți câștiga o arhitectura de notificare care scale cu creșterea produsului dumneavoastră.

Fie că construiți un simplu notificator de e-mail sau un motor complex multi-canal, începând cu modelul fabricii, se plătește mai devreme pe măsură ce setul de caracteristici se extinde. Investiția într-o cantitate mică de abstractizare astăzi salvează zile de reajustare mâine.