2010-12-15 8 views
0

は、コードスニペットは、Djangoのビューコードから来ているでreturnステートメントを持っているコードの一部をリファクタリングする必要がありますが、それはあまり重要ではないん。それはsub.is_active = Trueを行う以外 は、どのように私は、多くの異なる機能に存在しているが、それ

のは、私は次のコードがあるとしましょう

...

def unsubscribe(request): 
    #start of block 
    user = request.user 
    sid = request.POST.get('subscription_id') 
    try: 
    sub = Subscription.objects.get(id=sid) 
    except ObjectDoesNotExist: 
    return ajax_response(False, [('subscription', 'Given subscription does not exist.')]) 
    if sub.user != user: 
    return ajax_response(False, [('subscription', 'Invalid permission.')]) 
    #end of block. 
    sub.is_active = False 
    sub.save() 
    return ajax_response(True) 

と言うが、私は、上記の関数とまったく同じことを別の関数resubscribe()を持っています。

この場合、#block#endblockの間のコードは重複しないように、コードを整理する最良の方法は何ですか?一般的には、この質問は次のように書くことができます:

多くの異なる機能にコピー&ペーストされるコードブロックがあります。ただし、このコードブロックにはreturn文が含まれています。その場合、このロジックを抽象化する最良の方法は何でしょうか?

EDIT:固定コードスニペット。

EDIT2:実は、この質問を解決する簡単な方法は、言うrequestとブール値を取るtoggle_active_statusを、関数を作成することです。 (私は質問を掲示した後にそれを理解した)。

しかし、関数間のロジックが1行以上異なる場合、#blockと#endlbockの間のコードは入力の検証だけでなく、任意のアプリケーションロジック後で来ることができます。

答えて

1

まだ示されていないカップルのオプション:

この以来失敗を示すために例外を使用し、検証ルーチンであり、成功を示すために、通常なし(無視)リターン:

def verify_permissions(request): 
    user = request.user 
    sid = request.POST.get('subscription_id') 
    try: 
    sub = Subscription.objects.get(id=sid) 
    except ObjectDoesNotExist: 
    raise PermissionError, 'Given subscription does not exist.' 
    if sub.user != user: 
    raise PermissionError, 'Invalid permission.' 

def subscribe(request): 
    try: 
    verify_permissions(request) 
    sub.save() 
    return ajax_response(True) 
    except PermissionError, why: 
    return ajax_response(False, [('subscription', why)]) 

それとも、Pythonは動的に入力されているので応答を構築するために使用された引数を返し、最初の値を確認してください。ajax_responseを呼び出すことは明らかです。

def verify_permissions(request, purpose): 
    user = request.user 
    sid = request.POST.get('subscription_id') 
    try: 
    sub = Subscription.objects.get(id=sid) 
    except ObjectDoesNotExist: 
    return (False, [(purpose, 'Given subscription does not exist.')]) 
    if sub.user != user: 
    return (False, [(purpose, 'Invalid permission.')]) 
    return (True,) 

def subscribe(request): 
    result = verify_permissions(request, 'subscription') 
    if result[0]: sub.save() 
    return ajax_response(*result) 
+0

私は実際にあなたの提案が好きです...この質問がどのように行くか見てみましょう。 –

1

1つの方法は、複製された機能を含む別の機能を簡単に作成することです。関数のパラメータを使用して、必要な差異を導入することができます。コードスニペットが何かを返す

場合は、関数が返すべきでない場合Noneを返すか、オブジェクトそうするなど、規則を使用する場合があります。呼び出し元関数では、返されたパラメータがNoneかどうかをテストし、返された変数がNoneでない場合はそれを返します。重複チャンクアウト

+0

私は実際にそれを考えて、関数 'デフ_toggle_subscription(リクエスト、toggle_to)作成しました:'行を '持っsub.is_active = toggle_to' ...しかし、私は悪用きたように感じますこの例が提供されたコードの間にこのような小さな違いを持っ​​ているという事実です。 2つの機能の違いが分かればどうでしょうか? –

+0

違いがかなりある場合、私はそれがコードの重複とみなされません。 –

+0

申し訳ありませんが、私は具体的ではなかったと思います...私が "差異"を参照するとき、私は非共通ロジックの違いを指摘することを意味しました。提供された例では、subscribe()とunsubscribe()の違いはsub.is_active = False(またはTrue)になります。しかし、#blockと#endblockの間のコードがちょうど予備チェックであり、その後の実際のロジックがより複雑な場合はどうでしょうか? –

3

因子との差が差を渡すラッパー関数を作成し、渡されたことがあります

def alter_subscription(request, make_active): 
    # start of block 
    # (...) 
    # end of block 
    sub.is_active = make_active 
    sub.save() 
    return ajax_response(True) 

def unsubscribe(request): 
    return alter_subscription(request, False) 

def resubscribe(request): 
    return alter_subscription(request, True) 
+0

共通コードが検証を実行しているだけの場合は、ラッパーから呼び出して戻り値を確認します。これがdjangoの質問で、検証をしようとしているなら、おそらくミドルウェアやデコレータを見ますか? –

+0

しかし、パラメータ "bool"は、組み込み関数(型の名前)をマスクするため、呼び出さないでください。 :) –

+0

fixed(re: "bool")ty、Karl。 :) –

関連する問題