我应该如何重构一段存在于许多不同函数中但包含 return 语句的代码

发布于 2024-10-07 15:43:41 字数 1081 浏览 4 评论 0原文

代码片段来自django视图代码,但这并不重要。

假设我有以下代码...

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() ,它与上面的函数执行完全相同的操作,除了它执行 sub.is_active = True

在这种情况下,组织代码的最佳方式是什么,以便 #block#endblock 之间的代码不重复?我想一般来说,这个问题可以写成:

有一个代码块被复制并粘贴到许多不同的函数上。但是,此代码块包含 return 语句。在这种情况下,抽象出这段逻辑的最佳方法是什么?

编辑:固定代码片段。

EDIT2:实际上,解决这个问题的简单方法是创建一个函数,例如toggle_active_status,它接受 request 和一个布尔值。 (我在发布问题后就弄清楚了)。

但是,我想知道函数之间的不同逻辑超过 1 行的情况...例如,#block 和 #endlbock 之间的代码仅进行输入验证,并且可能会出现任何任意应用程序逻辑。

The code snippet is coming from django view code, but it doesn't matter much.

Let's say I have the following piece of code...

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)

and say, I have another function resubscribe() that does exactly same thing as the above function, except it does sub.is_active = True.

In that case, what would be the best way to organize the code, so that code between #block and #endblock aren't duplicated? I guess in general, this question can be written as:

There's a block of code that is copy-and-pasted over many different functions. however, this block of code contains return statement. in that case, what would be the best way to abstract this piece of logic out?

EDIT: fixed code snippet.

EDIT2: Actually, the easy way to solve this question is by creating a function say, toggle_active_status, which takes request and a boolean. (I figured it out after posting out the question).

However, i'm wondering about the case where the different logic between the functions is more than 1 line... like, say, code between #block and #endlbock only does input validation, and potentially any arbitrary application logic can come after.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

牵你的手,一向走下去 2024-10-14 15:43:41

分解出重复的块并传入差异,创建传递差异的包装函数:

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)

Factor out the duplicated chunk and have the difference be passed in, creating wrapper functions that pass in the difference:

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)
青春有你 2024-10-14 15:43:41

尚未显示的几个选项:

由于这是一个验证例程,因此使用异常来指示失败,并使用正常的 None(忽略)返回来指示成功:

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 是动态类型的,因此调用 < code>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)

A couple options that haven't been shown yet:

Since this is a verification routine, use exceptions to indicate failure, and a normal None (ignored) return to indicate success:

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)])

Or, since Python is dynamically typed and it's apparently OK to call ajax_response in a couple different ways: return the arguments used to construct the response, and check the value of the first one.

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)
等待圉鍢 2024-10-14 15:43:41

一种方法是简单地创建一个包含重复功能的单独函数。您可以使用函数的参数来引入必要的差异。

如果代码片段返回某些内容,那么您可以使用约定,例如如果函数不应返回则返回 None ,否则返回对象。在调用函数中,只需测试返回的参数是否为 None ,如果不是 None 则返回返回的变量。

One way is to simply create a separate function containing the duplicated functionality. You can use the parameters of the function to introduce the necessary differences.

If the code snippet returns something, then you might use a convention, such as to return None if the function should not return, or an object otherwise. In your caller function, just test whether the returned parameter is None or not, and return the returned variable if it isn't None.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文