プログラミングの旅を始めて以来、私は興味深いパターンに気づきました。それは、ほとんどのアプリケーションがテンプレート化されているということです。はい、これは純粋な事実です。この記事の冒頭で立ち止まって、これまでに開発したすべてのプロジェクトについて考えてみましょう。
これらに共通するものは何でしょうか?よく見ると、多くのコア機能がさまざまなプロジェクト間で再利用されていることがわかります。これらのコア機能には、多くの場合、ユーザー認証、支払い処理、ユーザー管理などが含まれます。
この記事では、これらのパターンはすべて過去のプログラマーによってすでに作成されていたという点を指摘したいと思います。実際、現在使用しているものはほとんどすべて、すでに実装されていました。特定のプロジェクトに基づいて一部の機能を変更するだけです。
ここでは、Python でのバックエンド開発の観点から例を紹介しますが、これはどのプログラミング言語にも、またソフトウェア エンジニアリングの領域内のどの分野にも適用できます。
では、すべてのバックエンド アプリケーションに共通するものは何でしょうか? 見てみましょう。
注: OOP (オブジェクト指向プログラミング) に精通している場合は、テンプレート化されたモジュールをアプリケーション レベルでの最高レベルの抽象化と見なし、この原則に従って記述する必要があります。
各セクションを、ほぼすべてのバックエンド アプリケーションに適用できる基本コンポーネントに分解したいと思います。
基本コンポーネント
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
基本的にはこれで完了です。この定義済み機能をすべてのプロジェクトにわたる認証に使用できます。
ほとんどすべてのアプリケーションは金融取引を処理します。地元の肉屋でも大企業でも、支払いを収集するには効果的なシステムを使用する必要があります。
基本コンポーネント
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 = []
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
これで、あらゆるプロジェクトに統合できる複雑なシステムが作成されました。まだパターンに従っていますか?これはどこでも使用できます。
結局のところ、このデータを視覚化するための別のアプリケーションを定義できます。テンプレート化のポイントは理解できました! 😉
メールと通知により、ユーザーはアプリの最新情報を入手し、アプリの利用を継続できます。アカウントの確認、パスワードのリセット、マーケティング コミュニケーションなど、どのようなプロジェクトでも、信頼性の高いメール サービスは不可欠です。
SendGrid
やAmazon SES
などの電子メール サービスと接続します。
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)
もう 1 つの重要なポイントは、 README
.env
config.py
、 pyproject.toml,
.pre-commit.yml
などのいくつかのファイルをすべてのバックエンド プロジェクトに追加し、プロジェクト内のファイルの基本構造を作成することです。
提案された構造は Python 実装に少し限定されていますが、前述したように、他の言語や分野でも同様に行うことができます。
また、最高レベルの抽象化でテンプレート化を行い、アプリケーションの適切な構造を維持することは、
パッケージとして、またはマイクロサービス アーキテクチャへの追加として、他のプロジェクトに再利用されます。
すべてをテンプレート化できます!
ここで紹介した例はほんの始まりに過ぎません。これらのパターンは、プロジェクトの進化に合わせて拡張および改良し、より複雑なシナリオに対応できます。 caching
を追加して、 k8s
、 docker
、 Devops
インフラストラクチャ、 CI/CD
、パイプラインを構築することもできます。
1 つの簡単なステートメントを覚えておいてください。自分の仕事を適切に完了したら、同じ仕事を使用して別の仕事を完了することができます。
目標は、プロジェクト、インフラストラクチャ、コンポーネント、およびサービスをさまざまなアプリケーション間で再利用できるようにすることです。
お茶を淹れて、アプリケーションのどの部分を別のアプリで再利用できるか考えてみましょう。コードの一部だけを調整して、同様のサービスを作成し、作業を自動化してみてください。
読んでいただきありがとうございます。テンプレート作成を楽しんでください!