paint-brush
Templating in der Softwareentwicklung: Ein genauerer Blickby@pro1code1hack
235

Templating in der Softwareentwicklung: Ein genauerer Blick

Yehor Dremliuha8m2024/07/16
Read on Terminal Reader

Viele Kernfunktionen werden in verschiedenen Projekten wiederverwendet. Zu diesen Funktionen gehören Benutzerauthentifizierung, Zahlungsabwicklung, Benutzerverwaltung und mehr. In diesem Artikel möchte ich darauf hinweisen, dass alle diese Muster bereits von Programmierern in der Vergangenheit erstellt wurden. Fast alles, was wir jetzt verwenden, war bereits implementiert. Wir ändern lediglich einige Funktionen je nach Projekt.
featured image - Templating in der Softwareentwicklung: Ein genauerer Blick
Yehor Dremliuha HackerNoon profile picture
0-item
1-item

1. Einleitung

Seit ich mit dem Programmieren begonnen habe, ist mir ein interessantes Muster aufgefallen: Die meisten Anwendungen basieren auf Vorlagen. Ja, das ist eine reine Tatsache! Bleiben Sie einfach hier, am Anfang dieses Artikels, stehen und denken Sie an all die Projekte, die Sie entwickelt haben.


Was haben sie gemeinsam? Wenn Sie genau hinschauen, werden Sie feststellen, dass viele Kernfunktionen in verschiedenen Projekten wiederverwendet werden. Zu diesen Kernfunktionen gehören häufig Benutzerauthentifizierung, Zahlungsabwicklung, Benutzerverwaltung und mehr.


In diesem Artikel möchte ich darauf hinweisen, dass all diese Muster bereits von Programmierern in der Vergangenheit erstellt wurden. Tatsächlich war fast alles, was wir jetzt verwenden, bereits implementiert. Wir ändern lediglich einige Funktionen je nach Projekt.


Ich werde Ihnen Beispiele aus der Perspektive der Backend-Entwicklung in Python vorstellen, aber dies kann auf jede Programmiersprache oder jedes Feld im Bereich der Softwareentwicklung angewendet werden.


Was haben also alle Backend-Anwendungen gemeinsam? Werfen wir einen Blick darauf!


Hinweis : Wenn Sie mit OOP (objektorientierter Programmierung) vertraut sind, betrachten Sie Ihre Modulvorlagen als höchste Abstraktionsebene, allerdings auf Anwendungsebene , sodass diese gemäß diesem Prinzip geschrieben werden sollten.

2. Authentifizierung und Autorisierung

Ich möchte jeden weiteren Abschnitt in die Grundkomponenten zerlegen, die auf nahezu jede Backend-Anwendung angewendet werden können.


Grundlegende Bestandteile

  1. Benutzermodell: Eine Darstellung des Benutzers, die Attribute wie Benutzername, Passwort, E-Mail, Rollen usw. enthält.
  2. Kennwortverwaltung: Funktionen zum Hashen und Verifizieren von Kennwörtern.
  3. Token-Generierung: Mechanismus zum Generieren und Überprüfen von Token (JWT, OAuth2 usw.).
  4. Middleware/Decorator: Schützen Sie Routen/Endpunkte, die eine Authentifizierung erfordern.
  5. Rollenverwaltung: Weisen Sie Benutzerrollen und -berechtigungen zu und überprüfen Sie diese.


2.1 Benutzermodell

Wir definieren die allgemeinste Klasse des User mit Attributen, die auf jeden bestimmten Benutzer angewendet werden können.

 from werkzeug.security import generate_password_hash, check_password_hash class User: def __init__(self, username, password, email): self.username = username self.password_hash = generate_password_hash(password) self.email = email self.roles = [] def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password)


2.2 Token-Verwaltung

Die Verwendung von JWT zur tokenbasierten Authentifizierung ist im Hinblick auf Cybersicherheit und Best Practices in der Backend-Entwicklung eine gute Wahl.

 def generate_token(user): payload = { 'username': user.username, 'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1) } return jwt.encode(payload, SECRET_KEY, algorithm='HS256') def verify_token(token): try: payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return payload['username'] except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None


2.3 Dekorateure

  • Dekorator, um zu überprüfen, ob der Benutzer auf die Seite zugreifen darf.
 from functools import wraps from flask import request, jsonify, session def is_authenticated(func): @wraps(func) def decorated_function(*args, **kwargs): if 'user' not in session: return jsonify({"error": "User not authenticated"}), 401 return func(*args, **kwargs) return decorated_function


  • Dekorator zum Überprüfen der Rolle des Benutzers.
 def roles_required(*roles): def decorator(func): @wraps(func) def decorated_function(*args, **kwargs): user_roles = session.get('roles', []) if not any(role in user_roles for role in roles): return jsonify({"error": "User does not have the required role"}), 403 return func(*args, **kwargs) return decorated_function return decorator


Und das ist im Grunde schon alles! Sie können diese vordefinierte Funktion zur Authentifizierung in allen Projekten verwenden!

3. Zahlungen und Abrechnung

Fast jede Anwendung verarbeitet Finanztransaktionen. Egal, ob es sich um eine lokale Metzgerei oder einen großen Konzern handelt, Sie benötigen ein effektives System, um Zahlungen abzuwickeln.


Grundlegende Bestandteile

  1. Zahlungsgateway-Integration: Verbindung mit Zahlungsgateways wie Stripe oder PayPal
  2. Zahlungsmodelle: Definieren von Modellen zur Handhabung von Zahlungsdaten.
  3. Zahlungsabwicklung: Handhabung des Zahlungslebenszyklus (initiieren, bestätigen usw.).


3.1 Zahlungsgateway-Integration

Dies kann als Grundlage für die Integration verschiedener Zahlungsgateways mit einer konkreten Implementierung für Stripe verwendet werden. Generell bevorzuge ich persönlich die Verwendung von StripeAPI für Zahlungen, da es schon lange auf dem Markt ist und sich wirklich einfach in jedes Projekt integrieren lässt.


 class PaymentGateway(ABC): @abstractmethod def create_payment_intent(self, amount, currency='gbp'): pass @abstractmethod def confirm_payment(self, payment_id): pass @abstractmethod def handle_webhook(self, payload, sig_header): pass

Dies ist das allgemeinste Beispiel für das Zahlungsgateway. Sie können sich entsprechend Ihren Anforderungen auf die spezifische Implementierung konzentrieren.


3.2 Zahlungsmodelle

Definieren Sie Modelle zum Speichern von Zahlungsinformationen. Dieses Beispiel kann für die Verwendung mit ORM angepasst werden. Sie können bei Bedarf eine komplexere Klassenhierarchie erstellen, aber für dieses Beispiel sollte der folgende Codeausschnitt völlig ausreichen.

 class Payment: def __init__(self, user_id, amount, currency): self.id = uuid.uuid4() self.user_id = user_id self.amount = amount self.currency = currency self.status = status payments = []


Speichern Sie alle Zahlungen in der Datenbank und richten Sie eine Celery Aufgabe zur Verarbeitung von Transaktionen für Abschnitt 3.3 ein. Die Datenbankeinträge sollten wie folgt aussehen:

 id | user_id | amount | currency | status --------------------------------------+-----------------------------------+--------+----------+---------- e532d653-7c8b-453a-8cd4-3ab956863d72 | 1ff9efb3-d5e8-4e53-854f-4246ba9ff638 | 100.00 | USD | Failed 35985d41-5d54-4021-bed6-82d7233cc353 | a0984002-bace-478e-b6f9-6e4459e1b5ba | 250.50 | EUR | Pending 1ff9efb3-d5e8-4e53-854f-4246ba9ff638 | 9f896874-dc43-4592-8289-d0f7f8b8583a | 99.99 | GBP | Completed


Jetzt haben wir ein komplexes System geschaffen, das in jedes Projekt integriert werden kann. Folgen Sie noch dem Muster? Dies kann ÜBERALL verwendet werden!


Schließlich können Sie eine andere Anwendung zur Visualisierung dieser Daten definieren. Sie verstehen, was Sie mit der Templating-Methode meinen! 😉

4. E-Mail- und Benachrichtigungsdienste

E-Mails und Benachrichtigungen halten Benutzer über den Betrieb Ihrer App auf dem Laufenden und binden sie ein. Ob zur Kontoüberprüfung, zum Zurücksetzen von Passwörtern oder für Marketingkommunikation – ein zuverlässiger E-Mail-Dienst ist für jede Art von Projekt unerlässlich.

  1. Integration von E-Mail-Diensten: Verbindung mit E-Mail-Diensten wie SendGrid oder Amazon SES .
  2. E-Mail-Vorlagen: Definieren von Vorlagen für verschiedene E-Mail-Typen.
  3. E-Mail-Versand: Funktionen zum Versenden von E-Mails über den integrierten Dienst.


4.1 E-Mail-Dienstintegration

Definieren Sie die Hauptlogik von SendGrid zum Senden von E-Mails innerhalb EmailService Klasse.

 import sendgrid from sendgrid.helpers.mail import Mail class EmailService: def __init__(self, api_key): self.sg = sendgrid.SendGridAPIClient(api_key) def send_email(self, from_email, to_email, subject, html_content): email = Mail( from_email=from_email, to_emails=to_email, subject=subject, html_content=html_content ) try: response = self.sg.send(email) return response.status_code except Exception as e: return str(e)


Wie beim Zahlungsgateway müssen Sie sich nicht auf bestimmte Dienstprogramme oder Produkte auf dem Markt konzentrieren. Dies ist nur ein Beispiel dafür, wie es verallgemeinert und für jedes Projekt verwendet werden kann.


4.2 E-Mail-Vorlagen

Mein Lieblingsmuster für derartige Systeme ist das Handler-Muster; man fügt dem Wörterbuch einfach immer mehr Schlüssel als E-Mail-Typ und den Pfad zur Datei mit einem Inhalt hinzu.


 email_templates = { 'welcome': “welcome.html”, 'reset_password': "<h1>Reset Your Password</h1><p>Click <a href='{link}'>here</a> to reset your password.</p>" }


Andernfalls könnte es sinnvoll sein, für dieselben Zwecke ein Enum zu definieren.


4.3 E- Mail-Versand

Wir brauchen eine Funktion, um die Magie geschehen zu lassen! Schreiben wir Folgendes:

 def send_email(email_service, from_email, to_email, subject, template_name, **template_vars): """ Send an email using the specified email service. """ html_content = get_email_template(template_name, **template_vars) return email_service.send_email(from_email, to_email, subject, html_content)


Ein weiterer wichtiger Punkt wäre das Hinzufügen mehrerer Dateien zu allen Backend-Projekten, z. B. README .env config.py , pyproject.toml, .pre-commit.yml , und das Erstellen einer Basisstruktur der Dateien innerhalb des Projekts.


Obwohl die vorgeschlagene Struktur, wie bereits erwähnt, etwas auf die Python-Implementierung beschränkt ist, können Sie dasselbe für jede andere Sprache oder jedes andere Feld tun.


Es ist auch wichtig zu beachten, dass Templating auf der höchsten Abstraktionsebene und die Aufrechterhaltung einer guten Struktur der Anwendung

für andere Projekte als Paket oder Ergänzung zur Microservice-Architektur wiederverwendet werden.



Abbildung 1 – Beispiel einer Microservice-Architektur

5. Schlussfolgerung

ALLES KANN ALS VORLAGE ERSTELLT WERDEN!


Die hier bereitgestellten Beispiele sind nur der Anfang – diese Muster können erweitert und verfeinert werden, um im Laufe der Entwicklung Ihrer Projekte komplexere Szenarien abzudecken. Sie können caching hinzufügen, um k8s , docker , Devops Infrastruktur, CI/CD und Pipelines einzurichten.


Denken Sie an eine einfache Aussage: Wenn Sie Ihre Arbeit ordnungsgemäß erledigt haben, können Sie dieselbe Arbeit nutzen, während Sie eine andere erledigen.


Das Ziel besteht darin, das Projekt, die Infrastruktur, die Komponenten und die Dienste über verschiedene Anwendungen hinweg wiederverwendbar zu machen!


Machen Sie sich eine Tasse Tee und überlegen Sie, welche Teile Ihrer Anwendungen in anderen Apps wiederverwendet werden können. Versuchen Sie, ähnliche Dienste zu erstellen und Ihre Arbeit zu automatisieren, indem Sie nur einige Codeteile anpassen!


Danke fürs Lesen und viel Spaß beim Erstellen der Vorlage!