paint-brush
Шаблоны в разработке программного обеспечения: более глубокий взглядк@pro1code1hack
381 чтения
381 чтения

Шаблоны в разработке программного обеспечения: более глубокий взгляд

к Yehor Dremliuha8m2024/07/16
Read on Terminal Reader

Слишком долго; Читать

Многие основные функции повторно используются в разных проектах. Эти функции включают аутентификацию пользователей, обработку платежей, управление пользователями и многое другое. В этой статье я хотел бы подчеркнуть, что все эти шаблоны уже были созданы программистами прошлого. Почти все, что мы используем сейчас, уже реализовано. Мы просто модифицируем некоторый функционал исходя из конкретного проекта.
featured image - Шаблоны в разработке программного обеспечения: более глубокий взгляд
Yehor Dremliuha HackerNoon profile picture
0-item
1-item

1. Введение

С тех пор как я начал свой путь в программировании, я заметил интересную закономерность: большинство приложений шаблонны. Да это чистый факт! Просто остановитесь прямо здесь, в начале этой статьи, и начните думать обо всех проектах, которые вы разработали.


Что они имеют общего? Если вы присмотритесь, вы увидите, что многие основные функции повторно используются в разных проектах. Эти основные функции часто включают аутентификацию пользователей, обработку платежей, управление пользователями и многое другое.


В этой статье я хотел бы подчеркнуть, что все эти шаблоны уже были созданы программистами прошлого. Действительно, почти все, что мы сейчас используем, уже реализовано. Мы просто модифицируем некоторый функционал исходя из конкретного проекта.


Я познакомлю вас с примерами серверной разработки на Python, но это можно применить к любому языку программирования или любой области разработки программного обеспечения.


Итак, что общего у всех серверных приложений? Давайте взглянем!


Примечание . Если вы знакомы с ООП (объектно-ориентированным программированием), считайте свои шаблонные модули высшим уровнем абстракции, но на уровне приложения , поэтому их следует писать в соответствии с этим принципом.

2. Аутентификация и авторизация

Я хотел бы разбить каждый следующий раздел на базовые компоненты, которые можно применить практически к любому серверному приложению.


Основные компоненты

  1. Модель пользователя: представление пользователя, включающее такие атрибуты, как имя пользователя, пароль, адрес электронной почты, роли и т. д.
  2. Управление паролями: функции для хэширования и проверки паролей.
  3. Генерация токенов: механизм генерации и проверки токенов (JWT, OAuth2 и т. д.).
  4. Промежуточное программное обеспечение/декоратор: защищает маршруты/конечные точки, требующие аутентификации.
  5. Управление ролями: назначение и проверка ролей и разрешений пользователей.


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. Платежи и выставление счетов

Практически любое приложение обрабатывает финансовые транзакции. Будь то местная мясная лавка или крупный гигант, вам потребуется использовать эффективную систему сбора платежей.


Основные компоненты

  1. Интеграция платежных шлюзов: подключение к платежным шлюзам, таким как Stripe или PayPal
  2. Модели оплаты: определение моделей для обработки платежных данных.
  3. Обработка платежей: обработка жизненного цикла платежа (инициирование, подтверждение и т. д.).


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. Службы электронной почты и уведомлений

Электронная почта и уведомления позволяют пользователям быть в курсе событий и участвовать в жизни вашего приложения. Будь то проверка учетной записи, сброс пароля или маркетинговые коммуникации, надежная служба электронной почты необходима для любого типа проекта.

  1. Интеграция службы электронной почты: подключение к службам электронной почты, таким как SendGrid или Amazon SES .
  2. Шаблоны электронной почты: определение шаблонов для различных типов электронной почты.
  3. Отправка электронных писем: функции для отправки электронных писем с помощью интегрированной службы.


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, как я уже упоминал ранее, вы можете сделать то же самое для любого другого языка или области.


Также важно отметить, что создание шаблонов на самом высоком уровне абстракции и поддержание хорошей структуры приложения могут быть эффективными.

повторно использоваться для других проектов в качестве пакета или дополнения к архитектуре микросервиса.



Рисунок 1. Пример микросервисной архитектуры.

5. Вывод

ВСЕ МОЖНО СДЕЛАТЬ ПО ШАБЛОНУ!


Приведенные здесь примеры — это только начало: эти шаблоны можно расширять и уточнять, чтобы охватить более сложные сценарии по мере развития ваших проектов. Вы можете добавить caching установить k8s , docker , инфраструктуру Devops , CI/CD и конвейеры.


Запомните одно простое утверждение: как только вы выполнили свою работу должным образом, вы можете использовать ту же работу при выполнении другой.


Цель состоит в том, чтобы сделать проект, инфраструктуру, компоненты и сервисы повторно используемыми в различных приложениях!


Заварите себе чашку чая и подумайте, какие части ваших приложений можно повторно использовать в других приложениях. Попробуйте создать подобные сервисы и автоматизировать свою работу, корректируя лишь некоторые участки кода!


Спасибо за прочтение и удачного создания шаблонов!