【问题标题】:Avoiding duplicate code while handling exception处理异常时避免重复代码
【发布时间】:2015-08-22 13:07:16
【问题描述】:

对于我的应用程序,我需要使用两种略有不同的算法来持久化实体:

def persistRandomAlias(self, alias):
    self.em.persist(alias)
    try:
        self.em.flush()
    except DBALException as e:
        if e.previous.code != 23000:
            raise e
        self.reloadEM()

        self.persistRandomAlias(alias)



def persistCustomAlias(self, alias):
    self.em.persist(alias)
    try:
        self.em.flush()
    except DBALException as e:
        if e.previous.code != 23000:
            raise e
        self.reloadEM()

        existing = self.findByNaturalKey(alias.name)
        if existing != alias:
            raise DuplicateNameException('The requested name is already taken', e)

它们之间的区别在于负责异常处理的部分代码。我考虑将通用代码放在一个方法中,其余操作传递到一个接受异常对象的函数中,如下所示:

def persistAlias(self, alias, exHandler):
    self.em.persist(alias)
    try:
        self.em.flush()
    except DBALException as e:
        if e.previous.code != 23000:
            raise e
        self.reloadEM()

        exHandler(e)

def persistRandomAlias(self, alias):
    self.persistAlias(alias, lambda e: self.persistRandomAlias(alias))            

def persistCustomAlias(self, alias):
    def exHandler(e):
        existing = self.findByNaturalKey(alias.name)
        if existing != alias:
            raise DuplicateNameException('The requested name is already taken', e)

    self.persistAlias(alias, exHandler)

但是,我不确定将未使用的参数传递给函数是否正确。

我也想过将通用代码重构为抽象方法对象类,像这样:

def execute(self):
    self.em.persist(alias)
    try:
        self.em.flush()
    except DBALException as e:
        if e.previous.code != 23000:
            raise e
        self.reloadEM()
        self.e = e

        self.handleE()

handleE() 将在实现 execute() 方法的类的子类中实现,它可以访问或不访问异常对象,具体取决于实现。

我应该选择其中一种方法来处理代码重复吗?哪一个更好?您有更好的解决方案吗?

【问题讨论】:

标签: python oop dry anonymous-function code-duplication


【解决方案1】:

哪一行会引发异常?最好在 try 语句中隔离会导致异常的行。你可以这样做:

def persistAlias(self, alias, is_custom=False):
    try:
        self.em.persist(alias)
        self.em.flush()
    except DBALException as e:
        if e.previous.code != 23000:
            raise e
        self.reloadEM()

        if is_custom:
            existing = self.findByNaturalKey(alias.name)
            if existing != alias:
                raise DuplicateNameException(
                    'The requested name is already taken', e)
        else:
            self.persistAlias(alias)

【讨论】:

  • 它在我提供的代码中不可见,但有一些原因我不会选择你的建议。首先,别名的实际类型取决于用户提供自定义名称值,还是留空。在persistAlias 方法中对is_custom 的测试将是多余的,因为它将由负责创建别名对象和调用persist 方法的代码执行。第二件事是,作为对异常的响应,再次运行 persistAlias() 时,请求的别名类型(自定义与随机)不会改变,这也会使测试变得多余。
  • 至于导致异常的行:它的self.em.flush()。我将编辑问题以解决它。
猜你喜欢
  • 2017-10-17
  • 1970-01-01
  • 2014-07-18
  • 2022-01-05
  • 2014-03-07
  • 1970-01-01
  • 2014-03-29
相关资源
最近更新 更多