Šablonai kuriant programinę įrangą: pažvelkite giliau
1. Įvadas
Pradėjęs savo kelionę nuo programavimo, pastebėjau įdomų modelį: dauguma programų yra šabloninės. Taip, tai grynas faktas! Tiesiog sustokite čia, šio straipsnio pradžioje, ir pradėkite galvoti apie visus savo sukurtus projektus.
Ką jie turi bendro? Jei atidžiai pažvelgsite, pamatysite, kad daugelis pagrindinių funkcijų yra pakartotinai naudojamos įvairiuose projektuose. Šios pagrindinės funkcijos dažnai apima vartotojo autentifikavimą, mokėjimų apdorojimą, vartotojų valdymą ir kt.
Šiame straipsnyje norėčiau pabrėžti, kad visus šiuos modelius jau sukūrė programuotojai iš praeities.Iš tikrųjų beveik viskas, ką naudojame šiuo metu, jau buvo įgyvendinta. Tiesiog modifikuojame kai kurias funkcijas pagal konkretų projektą.
Supažindinsiu jus su pavyzdžiais iš „Python“ kūrimo perspektyvos, tačiau tai gali būti taikoma bet kuriai programavimo kalbai ar bet kuriai programinės įrangos inžinerijos sričiai.
Taigi, ką bendro turi visos užpakalinės programos? Pažiūrėkime!
Pastaba: Jei esate susipažinę su OOP (objektiniu programavimu), šabloninius modulius laikykite aukščiausiu abstrakcijos lygiu, tačiau taikymo lygis kad tai turėtų būti rašoma pagal šį principą.
2. Autentifikavimas ir autorizacija
Kiekvieną kitą skyrių norėčiau suskirstyti į pagrindinius komponentus, kuriuos galima pritaikyti beveik bet kuriai užpakalinei programai.
Pagrindiniai komponentai
- Vartotojo modelis: Naudotojo atvaizdas, apimantis tokius atributus kaip vartotojo vardas, slaptažodis, el. pašto adresas, vaidmenys ir kt.
- Slaptažodžio valdymas: Slaptažodžių maišos ir tikrinimo funkcijos.
- Žetonų generavimas: Žetonų generavimo ir tikrinimo mechanizmas (JWT, OAuth2 ir kt.).
- Tarpinė programinė įranga / dekoratorius: Apsaugokite maršrutus/galinius taškus, kuriems reikalingas autentifikavimas.
- Vaidmenų valdymas: Priskirkite ir patikrinkite vartotojo vaidmenis ir leidimus.
2.1 Vartotojo modelis
Mes apibrėžiame bendriausią klasę User
su atributais, kuriuos galima pritaikyti bet kuriam konkrečiam vartotojui.
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 Žetonų valdymas
JWT naudojimas žetonų autentifikavimui yra geras pasirinkimas kibernetinio saugumo ir geriausios vidinės sistemos kūrimo praktikos požiūriu.
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 Dekoratoriai
- Dekoratorius, kuris patikrina, ar vartotojui leidžiama pasiekti puslapį.
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
- Apdailininkas, kad patikrintų vartotojo vaidmenį.
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
Ir iš esmės, viskas! Šią iš anksto nustatytą funkciją galite naudoti autentifikavimui visuose projektuose!
3. Mokėjimai ir atsiskaitymas
Beveik bet kuri programa tvarko finansines operacijas. Nesvarbu, ar tai vietinė mėsinė, ar didelė įmonė, mokėjimams rinkti turėsite naudoti veiksmingą sistemą.
Pagrindiniai komponentai
- Mokėjimo šliuzo integravimas: Prisijungimas prie mokėjimo šliuzų, pvz
Stripe
arbaPayPal
- Mokėjimo modeliai: Mokėjimo duomenų tvarkymo modelių nustatymas.
- Mokėjimo apdorojimas: Mokėjimo gyvavimo ciklo tvarkymas (inicijuoti, patvirtinti ir pan.).
3.1 Mokėjimo šliuzo integravimas
Tai gali būti naudojama kaip pagrindas integruoti skirtingus mokėjimo šliuzus, konkrečiai įgyvendinant Stripe. Paprastai mano asmeninis pasirinkimas yra naudoti StripeAPI
už mokėjimus, kaip ir ilgą laiką rinkoje, ir tikrai, lengvai integruojamas į bet kurį projektą.
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
Tai yra bendriausias mokėjimo šliuzo pavyzdys ir galite sutelkti dėmesį į konkretų įgyvendinimą pagal savo poreikius.
3.2 Mokėjimo modeliai
Apibrėžkite mokėjimo informacijos saugojimo modelius. Šis pavyzdys gali būti pritaikytas naudoti su ORM. Jei reikia, galite sukurti sudėtingesnę klasių hierarchiją, tačiau šiame pavyzdyje šio fragmento turėtų pakakti.
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 = []
Išsaugokite visus mokėjimus į duomenų bazę ir nustatykite a Celery
operacijų apdorojimo užduotis, skirta 3.3 skyriui. Duomenų bazės įrašai turėtų atrodyti taip:
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
Dabar sukūrėme sudėtingą sistemą, kurią galima integruoti į bet kurį projektą. Ar vis dar laikotės modelio? Tai gali būti naudojama VISUR!
Galų gale, galite apibrėžti kitą šių duomenų vizualizavimo programą. Jūs supratote mintį apie šablonų kūrimą! 😉
4. El. pašto ir pranešimų paslaugos
El. paštas ir pranešimai informuoja naudotojus apie jūsų programos veikimą ir juos įsitraukia. Nesvarbu, ar tai būtų paskyros patvirtinimas, slaptažodžio nustatymas iš naujo ar rinkodaros pranešimai, patikima el. pašto paslauga yra būtina bet kokio tipo projektams.
- El. pašto paslaugų integravimas: Prisijungimas prie el. pašto paslaugų, pvz
SendGrid
arbaAmazon SES
. - El. pašto šablonai: Įvairių tipų el. pašto šablonų apibrėžimas.
- Laiškų siuntimas: Funkcijos siųsti el. laiškus naudojant integruotą paslaugą.
4.1 El. pašto paslaugų integravimas
Apibrėžkite pagrindinę logiką SendGrid
laiškų siuntimui viduje EmailService
klasė.
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)
Kaip ir mokėjimo šliuzo atveju, jums nereikia susitelkti į konkrečias rinkoje esančias paslaugas ar produktus. Tai tik pavyzdys, kaip jį galima apibendrinti ir pritaikyti bet kokiam projektui.
4.2 El. pašto šablonai
Mano mėgstamiausias tokių sistemų modelis yra tvarkyklių modelis; tiesiog pridedate vis daugiau raktų į žodyną kaip el. laiško tipą ir kelią į failą su turiniu.
email_templates = {
'welcome': “welcome.html”,
'reset_password': "<h1>Reset Your Password</h1><p>Click <a href='{link}'>here</a> to reset your password.</p>"
}
Priešingu atveju būtų malonu apibrėžti Enum
tiems patiems tikslams.
4.3 Laiškų siuntimas
Mums reikia funkcijos, kad magija įvyktų! Parašykime taip:
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)
Kitas svarbus dalykas būtų kelių failų įtraukimas į visus backend projektus, pvz README
.env
config.py
, pyproject.toml,
.pre-commit.yml
ir sugalvoti pagrindinę failų struktūrą projekto viduje.
Nors siūloma struktūra yra šiek tiek sugriežtinta iki Python diegimo, kaip jau minėjau anksčiau, tą patį galite padaryti bet kuriai kitai kalbai ar sričiai.
Taip pat svarbu pažymėti, kad šablonų kūrimas aukščiausiu abstrakcijos lygiu ir geros programos struktūros palaikymas gali būti
pakartotinai naudojamas kitiems projektams kaip paketas arba mikro paslaugų architektūros priedas.
5. Išvada
VISKAS GALI BŪTI ŠABLONIS!
Čia pateikti pavyzdžiai yra tik pradžia – šie modeliai gali būti išplėsti ir patobulinti, kad apimtų sudėtingesnius scenarijus vystantis jūsų projektams. Galite pridėti caching
nustatyti k8s
, docker
, Devops
infrastruktūra, CI/CD
ir vamzdynai.
Prisiminkite vieną paprastą teiginį: Tinkamai atlikę savo darbą, galėsite atlikti tą patį darbą atlikdami kitą.
Tikslas yra, kad projektas, infrastruktūra, komponentai ir paslaugos būtų pakartotinai naudojami įvairiose programose!
Pasigaminkite puodelį arbatos ir pagalvokite, kurias programų dalis galima pakartotinai naudoti įvairiose programose. Pabandykite sukurti panašias paslaugas ir automatizuoti savo darbą, pakoreguodami tik kai kurias kodo dalis!
Ačiū, kad skaitėte, ir laimingo šablono!