ビジネスの成長に合わせて Django アプリを進化させる

ジャンゴアプリ2
Django を使用して最初の Web アプリケーションのプロトタイプを作成し始めるときは、常に Django アプリを XNUMX つ作成し、すべてのモデルをそのアプリに入れる傾向があります。 理由は簡単です。モデルの数がそれほど多くなく、ビジネス ロジックが単純だからです。 しかし、ビジネスの成長に伴って、より多くのモデルやビジネス ロジックが追加されます。ある日、アプリケーションが厄介な立場に置かれていることに気づくかもしれません。バグを見つけるのがますます困難になり、新しい機能が追加されたとしても、追加するのにますます時間がかかります。単純。 このブログでは、さまざまな Django アプリを使用してモデルとビジネス ロジックを再編成し、ビジネスの成長に合わせて拡張する方法について説明します。 また、その変化の流れを簡単なケーススタディで説明します。

プロトタイピング段階 – 簡単なケーススタディ

ユーザーがブログを作成して公開できるようにする「Weblog」と呼ばれる単純なアプリケーションから始めます。 weblog というアプリを作成します。 そしてモデルは以下の通りです。
In ウェブログ/models.py:

class Author(models.Model): user = models.OneToOneField('authentication.User') ... class Blog(models.Model): author = models.ForeignKey(Author) category = models.CharField( Choices=((TECH , 'Tech'), (SPORT, 'Sport'), (FASHION, 'Fashion')), max_length=10 ) content = models.TextField( max_length=10240,blank=True ) is_published = models.BooleanField(default=False) ) ...

ここで、アプリケーションの残りの部分が上記のモデルに基づいて完了したと仮定します。 ユーザーは、アプリケーションを使用してログインし、ブログを作成し、公開できるようになりました。
進化するアプローチ I – 同じアプリに新しいビジネス ロジックを追加し続ける
新しい要件があるとします。 より多くの作成者にアプリケーションを使用してコンテンツを作成してもらうために、閲覧数に基づいて作成者に支払います。 料金は 10 ビューごとに 1000 ドルです。 そして、支払いは月に一度送られます。
新しい要件は非常に単純に聞こえるため、新しいモデルとロジックを既存のアプリに組み込む通常のアプローチで十分です。 まず、以下のように「ウェブログ」アプリに新しいモデルを追加します。
In ウェブログ/models.py:

...クラス MonthlyViewCount(models.Model): ブログ = models.ForeignKey(Blog) 月 = models.DateField() カウント = models.PositiveIntegerField(default=1) ...

ブログの新しいビューごとに、月に基づいてカウントを増やすか、新しいビューを作成します。 月間表示回数 これが今月の最初のビューであるかどうかを記録します。 コードは次のようになります。

class Blog(models.Model): ... def増加_view_count(self): now = timezone.now() month = datetime(year=now.year, month=now.month, day=1) view_count, created = \ MonthlyViewCount .objects.get_or_create( blog=self, month=month ) 作成されていない場合: view_count.count += 1 view_count.save()

毎月の終わりに、各作成者のすべての閲覧数を集計し、それに応じて支払いを行う cron タスクを実行します。 疑似コードは次のとおりです。
In ウェブログ/task.py:

@periodic_task(run_every=crontab(day_of_month=1,hour=0,minut=1)) def send_viewcount_payment_to_authors(): 著者の場合、Authors.objects.authors_with_viewscounts( month=previous_month): total_view_count = author.get_total_view_count_for_month( month=previous_month )payment_amount = (総閲覧数 / 1000) * 10.00 著者.send_payment(payment_amount)

上記のアプローチは、このような単純な変更リクエストを処理する場合には適切であると思われます。 しかし、常に新しい要件が発生します。
進化するアプローチ II – ビジネス ロジックをさまざまな Django アプリに編成する
ここで、新しい要件ができました。 著者が特定のカテゴリでコンテンツを作成することを奨励するために、ビジネス チームは、受賞戦略をカテゴリベースの戦略に調整したいと考えています。 カテゴリごとに異なる賞金額が設定されます。 特典価格表が次のようになっているとします。

 価格(1000ビューあたり)
テク$15
スポーツ$10
ファッション$5

この新しい要件も非常に単純に見えるため、既存のアプリでカテゴリの基本価格を保存する新しいモデルを作成し、合計を集計するときにカテゴリベースの価格を検索するように cron タスクを更新するだけで済みます。 変更全体は 30 分もかからずに完了します。
しかし、メインの「ウェブログ」アプリに新しいモデルやビジネス ロジックをどんどん組み込むことには、XNUMX つの大きな問題があります。

  1. メイン アプリは、さまざまなドメイン知識のビジネス ロジックを担当します。 クラス ファイルが大きくなり、保守できなくなります。
  2. 問題のデバッグが難しくなり、新機能の追加が遅くなるため、俊敏性が損なわれます。

Django では、さまざまなアプリを使用してさまざまなドメインのビジネス ロジックを整理し、シグナルを使用してアプリ間の通信を処理できます。 この例では、すべての課金関連のモデルとメソッドを「billing」という新しいアプリに移動しようとします。
まず、すべての課金関連モデルを新しい課金アプリに移動します。
In billing/models.py:

... クラス MonthlyViewCount(models.Model): ブログ = models.ForeignKey('weblog.Blog', relationship_name='+') 月 = models.DateField() カウント = models.PositiveIntegerField(default=1) ... クラスcategoryBasedPrice(models.Model): category = models.CharField(choices=((TECH, 'Tech'), (SPORT, 'Sport'), (FASHION, 'Fashion')), 価格 = models.MoneyField(... ) ...

ブログ記事の新しいビューごとに、課金アプリに通知して、それに応じて記録できるようにする必要があります。 そのためには、「ウェブログ」アプリでシグナルを定義し、「請求」アプリで受信したシグナルを処理する単一のハンドラーを作成します。
私たちは、 Blog.increase_view_count()請求/受信者.py シグナルハンドラーとして:

def raise_view_count(sender, blog, **kwargs): now = timezone.now() month = datetime(year=now.year, month=now.month, day=1) view_count, created = \ MonthlyViewCount.objects.get_or_create( blog=blog, month=month ) 作成されていない場合: view_count.count += 1 view_count.save()

次に、新しい信号が作成されます ウェブログ/signals.py:

from django.dispatch import 請求インポート受信者からのシグナル ... blog_viewed = Signal(providing_args=['blog']) blog_viewed.connect(receivers.increase_view_count)

また、いずれかのビュー メソッドにシグナル送信スニペットを挿入する必要があります。 ウェブログ/views.py:

from weblog.signals import blog_viewed ... def view_blog(request, blog_id): try: blog = Blog.objects.get(blog_id) ValueError を除く: raise Http404() blog_viewed.send(Blog, blog=blog) response.write( blog.render_content()) 応答を返す

最後に、請求関連の cron タスクを移動できます。 send_viewcount_payment_to_authors から ウェブログ/task.py 〜へ 請求/task.py 新しいカテゴリベースの価格設定を処理するための新しいロジックを追加します。
新しいものをすべてメインアプリに組み込むだけの通常のアプローチと比較すると、上記のアプローチにはより多くのコード変更とリファクタリングが必要ですが、価値のあるいくつかのメリットがあります。

  1. 特定のドメインのビジネス ロジックは他のドメインから分離されているため、コード ベースの保守が容易になります。
  2. 実行時に問題が発生した場合、症状に基づいてアプリの範囲内で原因を即座に特定できます。 これにより、デバッグ時間が短縮されます。
  3. 新しい開発者がオンボーディングすると、最初に XNUMX つのアプリで作業を開始できるため、学習曲線が緩和されます。
  4. 特定のドメイン内のビジネス ロジックのセット全体を廃止することにした場合 (たとえば、すべての課金機能が不要になった場合)、そのアプリを削除するだけで済み、他のすべては通常どおり実行し続けることができます。

まとめ
多くのスタートアップ企業が Django を使用して製品やサービスのプロトタイプを作成しています。 さらに、Django はビジネスの成長にもうまく対応できます。 重要な側面は、ビジネス ロジックを時々再考してさまざまなアプリに再編成し、各アプリの責任を可能な限りシンプルに保つことです。

類似の投稿