paint-brush
软件开发中的模板:深入了解经过@pro1code1hack
377 讀數
377 讀數

软件开发中的模板:深入了解

经过 Yehor Dremliuha8m2024/07/16
Read on Terminal Reader

太長; 讀書

许多核心功能在不同项目中重复使用。这些功能包括用户身份验证、支付处理、用户管理等。在本文中,我想指出的是,所有这些模式都是过去的程序员已经创建的。我们现在使用的几乎所有东西都已经实现。我们只是根据具体项目修改一些功能。
featured image - 软件开发中的模板:深入了解
Yehor Dremliuha HackerNoon profile picture
0-item
1-item

1. 简介

自从我开始编程之旅以来,我注意到一个有趣的模式:大多数应用程序都是模板化的。是的,这是事实!就在这里,在这篇文章的开头停下来,开始思考你开发的所有项目。


它们有什么共同点?如果你仔细观察,你会发现许多核心功能在不同项目中重复使用。这些核心功能通常包括用户身份验证、支付处理、用户管理等。


在本文中,我想指出的是,所有这些模式都是过去的程序员已经创建的。实际上,我们现在使用的几乎所有东西都已经实现了。我们只是根据具体项目修改了一些功能。


我将从 Python 中的后端开发角度向您介绍示例,但这可以应用于任何编程语言或软件工程领域的任何领域。


那么,所有后端应用程序都有哪些共同点?让我们来看看!


注意:如果您熟悉 OOP(面向对象编程),请将模板模块视为最高抽象级别,但在应用程序级别,因此应根据此原则进行编写。

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. 支付网关集成:连接StripePayPal等支付网关
  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 = []


将所有付款保存到数据库中,并针对 3.3 部分设置一个Celery任务来处理交易。数据库记录应如下所示:

 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. 电子邮件服务集成:连接SendGridAmazon SES等电子邮件服务。
  2. 电子邮件模板:定义各种电子邮件类型的模板。
  3. 发送电子邮件:使用集成服务发送电子邮件的功能。


4.1 电子邮件服务集成

EmailService类中定义SendGrid发送电子邮件的主要逻辑。

 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.pypyproject.toml, .pre-commit.yml ,并提出项目内部文件的基本结构。


虽然建议的结构对于 Python 实现来说有点紧,但正如我之前提到的,您可以对任何其他语言或领域执行相同的操作。


还需要注意的是,在最高抽象级别上进行模板化并维护应用程序的良好结构可以

可以作为包或微服务架构的补充重新用于其他项目。



图 1-微服务架构示例

5. 结论

一切都可以模板化!


这里提供的示例仅仅是开始 — 随着项目的发展,这些模式可以扩展和改进,以涵盖更复杂的场景。您可以添加caching建立k8sdockerDevops基础设施、 CI/CD和管道。


记住一个简单的说法:一旦你正确地完成了你的工作,你就可以在完成另一项工作时使用相同的工作。


目标是使项目、基础设施、组件和服务可以在不同的应用程序之间重复使用!


给自己泡杯茶,思考一下您的应用程序的哪些部分可以在不同的应用程序中重复使用。尝试创建类似的服务并自动化您的工作,只需调整一些代码片段!


感谢您的阅读,祝您模板制作愉快!