构造函数验证和构造函数违规

Validation in Constructor and Constructor Violation

我在这里读了一些书(1,2),我想知道确保初始化期间提供的参数正确是否违反了构造函数不应该工作的准则。

例如(Python):

class Employee:
    def __init__(self, empFirstname, empLastname, empEmail):

        self._validate_employee(empFirstname, "First Name")
        self._validate_employee(empLastname, "Last name")
        self._validate_employee(empEmail, "Email")
        self._validate_email(empEmail, "Email")

        self.empFirstname = empFirstname
        self.empLastname = empLastname
        self.empEmail = empEmail

    @property
    def email(self):
        return self.empEmail

    def _validate_employee(self, parameter, error_message):
        if not parameter:
            raise TypeError("{0} {1}" .format(error_message, "is missing"))

    def _validate_email(self, email, parameter):
        if "@" not in email or "." not in email:
            raise TypeError("{0} {1}" .format(parameter, " is invalid"))

在我的示例中,我检查以确保名字和姓氏不为空并且电子邮件有效。我违反了指南吗?

更新: 我不是在问它是否应该抛出,我是在问我是否违反了构造函数在验证我的参数时不应该工作的准则。

不,验证参数和输入对所有函数都至关重要,包括构造函数。在没有 checking/error 处理的情况下盲目设置参数会导致严重的问题,从意外的性能到恶意行为者能够以非预期的方式操纵您的程序。

提供满足特定条件的参数的要求是Design by Contract的一部分,即它对应于前提条件。客户端(在您的情况下是构造函数)应保证参数符合预期。如果不是这种情况,供应商(您的情况下的构造函数)无法确保生成的对象在构造函数 returns 之后处于有效状态。在原生支持按合同设计的语言中,人们会关联一个 class 不变量,声明名称不为空并且电子邮件地址遵循命名约定。这只有在传递给构造函数的参数有效时才能实现。

您提到的条件将被写为先决条件,并且可以根据软件开发过程中制定的策略打开或关闭。启用后,在执行其主体之前,将在进入构造函数时检查它们。从这个角度来看,您的代码没有做任何额外的工作,而是确保参数正确。在确保前提条件始终得到满足的程序验证之后,或者进行了广泛的测试,使客户感觉前提条件没有被客户端违反后,可以将它们禁用,从而删除任何 "additional work".

总结一下:

  • 您示例中的 "additional code" 是先决条件
  • 先决条件是软件合同的一部分
  • 可以根据采用的策略启用或禁用合同检查,只要所有客户保证不违反先决条件,就可以安全地禁用它们,从而从构造函数中删除任何 "additional work" (或任何其他软件组件)