1. Введение
С тех пор как я начал свой путь в программировании, я заметил интересную закономерность: большинство приложений шаблонны. Да это чистый факт! Просто остановитесь прямо здесь, в начале этой статьи, и начните думать обо всех проектах, которые вы разработали.
Что они имеют общего? Если вы присмотритесь, вы увидите, что многие основные функции повторно используются в разных проектах. Эти основные функции часто включают аутентификацию пользователей, обработку платежей, управление пользователями и многое другое.
В этой статье я хотел бы подчеркнуть, что все эти шаблоны уже были созданы программистами прошлого. Действительно, почти все, что мы сейчас используем, уже реализовано. Мы просто модифицируем некоторый функционал исходя из конкретного проекта.
Я познакомлю вас с примерами серверной разработки на Python, но это можно применить к любому языку программирования или любой области разработки программного обеспечения.
Итак, что общего у всех серверных приложений? Давайте взглянем!
Примечание . Если вы знакомы с ООП (объектно-ориентированным программированием), считайте свои шаблонные модули высшим уровнем абстракции, но на уровне приложения , поэтому их следует писать в соответствии с этим принципом.
2. Аутентификация и авторизация
Я хотел бы разбить каждый следующий раздел на базовые компоненты, которые можно применить практически к любому серверному приложению.
Основные компоненты
- Модель пользователя: представление пользователя, включающее такие атрибуты, как имя пользователя, пароль, адрес электронной почты, роли и т. д.
- Управление паролями: функции для хэширования и проверки паролей.
- Генерация токенов: механизм генерации и проверки токенов (JWT, OAuth2 и т. д.).
- Промежуточное программное обеспечение/декоратор: защищает маршруты/конечные точки, требующие аутентификации.
- Управление ролями: назначение и проверка ролей и разрешений пользователей.
2.1 Модель пользователя
Мы определяем наиболее общий класс User
с атрибутами, которые можно применить к любому конкретному пользователю.
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 Управление токенами
Использование JWT для аутентификации на основе токенов — хороший выбор с точки зрения кибербезопасности и лучших практик серверной разработки.
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 Декораторы
- Декоратор, проверяющий, разрешен ли пользователю доступ к странице.
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
- Декоратор для проверки роли пользователя.
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
И, в принципе, вот и все! Вы можете использовать эту предопределенную функцию для аутентификации во всех проектах!
3. Платежи и выставление счетов
Практически любое приложение обрабатывает финансовые транзакции. Будь то местная мясная лавка или крупный гигант, вам потребуется использовать эффективную систему сбора платежей.
Основные компоненты
- Интеграция платежных шлюзов: подключение к платежным шлюзам, таким как
Stripe
илиPayPal
- Модели оплаты: определение моделей для обработки платежных данных.
- Обработка платежей: обработка жизненного цикла платежа (инициирование, подтверждение и т. д.).
3.1 Интеграция платежного шлюза
Это можно использовать в качестве основы для интеграции различных платежных шлюзов с конкретной реализацией Stripe. В целом я лично предпочитаю использовать StripeAPI
для платежей, поскольку он уже давно присутствует на рынке и действительно легко интегрируется в любой проект.
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
Это наиболее общий пример платежного шлюза, и вы можете сосредоточиться на конкретной реализации в соответствии с вашими потребностями.
3.2 Модели оплаты
Определите модели для хранения платежной информации. Этот пример можно адаптировать для использования с ORM. При необходимости вы можете создать более сложную иерархию классов, но для этого примера следующего фрагмента будет вполне достаточно.
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 = []
Сохраните все платежи в базу данных и настройте задачу Celery
для обработки транзакций, для раздела 3.3. Записи базы данных должны выглядеть следующим образом:
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
Теперь мы создали сложную систему, которую можно интегрировать в любой проект. Вы все еще следуете шаблону? Это можно использовать ВЕЗДЕ!
Ведь вы можете определить другое приложение для визуализации этих данных. Вы поняли суть шаблонов! 😉
4. Службы электронной почты и уведомлений
Электронная почта и уведомления позволяют пользователям быть в курсе событий и участвовать в жизни вашего приложения. Будь то проверка учетной записи, сброс пароля или маркетинговые коммуникации, надежная служба электронной почты необходима для любого типа проекта.
- Интеграция службы электронной почты: подключение к службам электронной почты, таким как
SendGrid
илиAmazon SES
. - Шаблоны электронной почты: определение шаблонов для различных типов электронной почты.
- Отправка электронных писем: функции для отправки электронных писем с помощью интегрированной службы.
4.1 Интеграция службы электронной почты
Определите основную логику SendGrid
для отправки электронных писем внутри класса EmailService
.
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)
Как и в случае с платежным шлюзом, вам не нужно сосредотачиваться на каких-либо конкретных утилитах или продуктах на рынке. Это всего лишь пример того, как это можно обобщить и шаблонизировать для любого проекта.
4.2 Шаблоны электронных писем
Мой любимый шаблон для подобных систем — шаблон обработчиков; вы просто добавляете в словарь все больше и больше ключей как типа письма, так и пути к файлу с содержимым.
email_templates = { 'welcome': “welcome.html”, 'reset_password': "<h1>Reset Your Password</h1><p>Click <a href='{link}'>here</a> to reset your password.</p>" }
В противном случае было бы неплохо определить Enum
для тех же целей.
4.3 Отправка электронных писем
Нам нужна функция, чтобы творить волшебство! Напишем следующее:
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)
Еще одним важным моментом будет добавление нескольких файлов во все серверные проекты, таких как README
.env
config.py
, pyproject.toml,
.pre-commit.yml
, и создание базовой структуры файлов внутри проекта.
Хотя предложенная структура немного ограничена реализацией Python, как я уже упоминал ранее, вы можете сделать то же самое для любого другого языка или области.
Также важно отметить, что создание шаблонов на самом высоком уровне абстракции и поддержание хорошей структуры приложения могут быть эффективными.
повторно использоваться для других проектов в качестве пакета или дополнения к архитектуре микросервиса.
5. Вывод
ВСЕ МОЖНО СДЕЛАТЬ ПО ШАБЛОНУ!
Приведенные здесь примеры — это только начало: эти шаблоны можно расширять и уточнять, чтобы охватить более сложные сценарии по мере развития ваших проектов. Вы можете добавить caching
установить k8s
, docker
, инфраструктуру Devops
, CI/CD
и конвейеры.
Запомните одно простое утверждение: как только вы выполнили свою работу должным образом, вы можете использовать ту же работу при выполнении другой.
Цель состоит в том, чтобы сделать проект, инфраструктуру, компоненты и сервисы повторно используемыми в различных приложениях!
Заварите себе чашку чая и подумайте, какие части ваших приложений можно повторно использовать в других приложениях. Попробуйте создать подобные сервисы и автоматизировать свою работу, корректируя лишь некоторые участки кода!
Спасибо за прочтение и удачного создания шаблонов!