Python,IoC,异常和松耦合

时间:2015-05-18 13:15:01

标签: python exception inversion-of-control loose-coupling

假设我们有两个类Class A,其中包含一个经常抛出的自定义错误,它是其功能的一部分。

#a.py
class AError(Exception):
  """This exception flags a functional error"""
  pass


class A(object):
  def work(self):
    """Throws AError when it is tired"""
    raise AError() #This exception is raised eventually, business code removed for clarity

Class B,它使用A类执行某些操作。

#b.py
import a
class B(object):
  def make_him_work(self, afected):
     try:
       afected.work()
     except a.AError:
       pass #This was expected, here will go some business logic

这很好用,但是当我有不同类型的A时它会成为一个问题。理想情况下,我想完全将A与B分离,所以我可以传递任何满足相同界面的A类,但是我不能由于异常(因为它不是界面本身的一部分)

在C ++中,我将有一个头文件,其中包含我的接口的定义以及具体类将实现的异常。这通常如何在Python中解决?或者说另一种方式,什么是最pythonic的方法?

我认为有以下几种选择:

1。创建具有异常的模块,可能是基类/元类(C ++ / Java方式)

#common.py
class AErrorBase(Exception):
  pass


class AIface(object):
  def work(self):
    raise NotImplemented()

#a.py
import common
class AError(common.AErrorBase):
  pass


class A(common.AIface):
  def work(self):
    """Throws AError when it is tired"""
    raise AError()

#b.py
import common
class B(object):
  def make_him_work(self, afected):
     try:
       afected.work()
     except common.AErrorBase:
       pass #This was expected

2。将异常作为参数传递

#a.py
class AError(Exception):
  pass


class A(object):
  def work(self):
    """Throws AError when it is tired"""
    raise AError()

#b.py
class B(object):
  def make_him_work(self, afected, ex_type):
     try:
       afected.work()
     except ex_type:
       pass #This was expected

第3。作为类的属性的异常,因此它成为接口的一部分。

#a.py
class A(object):
  def work(self):
    """Throws AError when it is tired"""
    raise AError()
  class AError(Exception):
    pass

#b.py
class B(object):
  def make_him_work(self, afected):
     try:
       afected.work()
     except afected.AError:
       pass #This was expected

4。不要使用异常,只需返回代码。 !C天回来了!

还有其他选择吗?你有什么更多" pythonic"?

编辑:添加注释以阐明异常的目的。它需要在B

中处理

注意:这可能完全是因为我正在接近旧C ++背景的问题,我只想知道当我们有异常时如何在python中应用IoC。随意说我的所有方法都是垃圾,我应该用另一种方式来做

1 个答案:

答案 0 :(得分:1)

我的课程看起来像这样:

class A(object):
  def can_work(self):
    "returns True if an A can work otherwise False (e.g. is an A is tired)"
    return ...

  def work(self):
    assert not self._is_tired, "Test if self.can_work() first!"
    ...

这样您就可以让A的用户测试他们是否应该使用工作。 断言对于调试很有用,并确保您或其他人不会忘记接口。

B类将使用A如下:

class B(object):
  def make_him_work(self, afected):
     if afected.can_work():
       afected.work()