有人告诉我要在公司中设计一个新的API,在编码实践方面我面临着一个难题。
我的API必须先进行多项检查,然后才能运行,并且通常需要运行多个级别的功能。
一切都很好,直到这里。但是我的大多数检查(从子到子到子)功能都需要主API返回,而无需执行任何操作。我几乎所有的check函数都必须返回下一个check函数使用的一些数据,这就是我的问题所在。由于这种结构,我必须在每个检查函数的末尾以及处理后的数据返回一个状态,并且在调用该函数之后,必须在进入下一个函数之前检查状态。
示例代码:
def check1a():
if some_process():
return True, data_positive
return False, data_negative
#data_positive and data_negative cannot be used to identify whether the check passed or not.
def check1():
stats,data = check1a()
if not status:
return False, data
status, data = check1b(data)
if not status:
return False, data
status, data = check1c(data)
if not status:
return False, data
return status, data
def mainAPI():
status, data = check1(data)
if not status:
return data
status, data = check2(data)
if not status:
return data
status, data = check3()
if not status:
return "Failed"
return data
作为“ DRY”概念的虔诚追随者,如果感觉使用异常以下列方式运行代码将是最好的。
def check1a():
if some_process():
return data_positive
exception1a = Exception("Error in check 1 a")
exception.data = data_negative
raise exception
def check1():
data = check1a()
data = check1b(data)
data = check1c(data)
return data
def mainAPI():
try:
data = check1(data)
data = check2(data)
data = check3(data)
return data
except Exception as e:
return e.data #I know exceptions don't always have data, but this is an illustration of what I think I should implement
不幸的是,我的公司不愿在代码中引发异常以实现这种工作。
这是我的问题。
答案 0 :(得分:3)
这可能不是一个很好的答案,其他人可以提供更多帮助。
这是一个基于意见的主题。如果他们说不喜欢您使用try exception
这样的话,那么他们可能不相信“要求宽恕胜于允许” 原则。
话虽这么说,扔一个Exception
并不坏;但是,捕获一般Exception
被认为是不好的。如果某个软件未按预期运行(即以某种未知的方式运行),则您希望它失败,因此您应该仅捕获想要捕获的特定 Exception
。
您可以在此处找到大量可行的例外,只需选择一个似乎合理的例外即可使用:Python Programming Exceptions
如果您不想捕获先前存在的异常之一,则可以随时创建自己的异常:
class MyAPIException(Exception):
def __init___(self, val):
self.val = val
Exception.__init__(self, "APIException with with arguments {0}".format(self.val))
def do_stuff(a,b,c):
raise MyAPIException({
'a' : a,
'b' : b,
'c' : c,
})
try:
do_stuff(1, 2, 3)
except MyAPIException as e:
print("API Exception:", e)
您可以使用 DRY 进行帮助的另一种方法是使用列表进行通话。
def check1():
# List of functions you want to call in order
calls = [check1a, check1b, check1c]
for index, call in enumerate(calls):
# If it is the first function we will not pass any data
status, data = call() if index == 0 else call(data)
if not status:
return False, data
return status, data
如果您想返回每个函数调用的结果,则此实现还可以轻松将其实现为生成器。
答案 1 :(得分:2)
The answer by Error - Syntactical Remorse is a good one。使用API定义的异常来处理控制流。为了进一步扩展答案,您的API无需公开此类异常,您的内部函数可以将它们捕获为处理控制流的一部分:
class MyAPIException(Exception):
pass
class SensorMiscalibrated(MyAPIException):
pass
def mainAPI():
try:
data = check1(data)
data = check2(data)
data = check3(data)
return True, data
except SensorMiscalibrated as e:
return False, data
整洁的是,check1,check2…引发的有关文件权限或进程错误的任何其他异常都将冒泡并被异常处理程序忽略。
在Python中鼓励使用异常,并且与其他以不同方式实现它们的语言不同,它们不会造成性能损失。