静态类型很有用,但也有局限性


在代码库内部,静态类型系统可以是一个强大的工具。良好的类型系统使编译器能够检查代码的各个部分是否看起来内部一致:

  • 您是否使用正确的参数调用过程?
  • 您是否实现了接口定义的所有方法?
  • 您是否正确初始化了对象?

虽然类型系统对于此类工作很有用,但还必须意识到它们的局限性。

编译器可以检查代码库的内部模型是否有意义,但它无法验证运行时发生的情况。

对于在运行时进入(或离开)应用程序的数据,类型系统无法执行有用的健全性检查。您可能会尝试对输入应该是什么样子进行建模,这样做甚至可能很有用,但重要的是要承认现实可能不是您想象的模型。

每次与外部系统交互时,它都存在与您的系统不一致的风险。静态类型无法保护您免受这种情况的影响。

ORM幻觉
关系数据库(尤其是 ORM)的许多悲伤和麻烦源于这样一种错觉:ORM“实体”是数据库模式的静态类型视图。通常,您可以以代码优先或数据库优先的方式使用像实体框架这样的 ORM,但无论您选择什么,您都会有关于数据库的两个相互竞争的“事实”:数据库表结构和实体类。

你需要保持这两种观点同步,我并不是说这是不可能的。我只是建议明确承认静态类型可能并不代表应用程序边界另一侧实际内容的任何真相,这可能是值得的。

我认为 ORM 无用的 (许多)原​​因之一正是因为它们坚持一种超越其用处的幻觉。相反,我更喜欢使用较低级别的 API 来实现与数据库通信的协议,例如 ADO.NET:

private static Reservation ReadReservationRow(SqlDataReader rdr)
{
    return new Reservation(
        (Guid)rdr["PublicId"],
        (DateTime)rdr[
"At"],
        new Email((string)rdr[
"Email"]),
        new Name((string)rdr[
"Name"]),
        new NaturalNumber((int)rdr[
"Quantity"]));
}

实际上,这并不是一个特别好的协议实现,因为它没有考虑到波斯特尔定律(Postel 定理 )。实际上,这段代码应该是一个容错阅读器。在实践中,不可能有那么多的输入偏差,但也许至少,如果缺少了姓名字段,这段代码应该能从容应对。

这个例子的意义并不在于它是完美的,因为它并不完美,而是它可以降低到一个较低的抽象层次,有时,这可能是对现实更真实的描述。

所有模型都是错误的,但有些模型是有用的。我相信静态类型也是如此。

详细点击标题