我应该如何重构一段存在于许多不同函数中但包含 return 语句的代码
代码片段来自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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
分解出重复的块并传入差异,创建传递差异的包装函数:
Factor out the duplicated chunk and have the difference be passed in, creating wrapper functions that pass in the difference:
尚未显示的几个选项:
由于这是一个验证例程,因此使用异常来指示失败,并使用正常的 None(忽略)返回来指示成功:
或者,由于 Python 是动态类型的,因此调用 < code>ajax_response 有几种不同的方式:返回用于构造响应的参数,并检查第一个参数的值。
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:
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.一种方法是简单地创建一个包含重复功能的单独函数。您可以使用函数的参数来引入必要的差异。
如果代码片段返回某些内容,那么您可以使用约定,例如如果函数不应返回则返回 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 isNone
or not, and return the returned variable if it isn'tNone
.