Newspeak是大洋洲人民在乔治奥尔韦尔小说十九八十四的虚构语言。
“难道你不知道新闻的整个目的是缩小思想范围吗?最终,我们将使思想过敏,因为没有任何言语表达它。“
Newspeak为大洋洲的人而糟糕,但我们开发人员可以从2010年来学习一两件事。
作为一个插图,让我们在Java中提出一个简单的示例方法签名:
这段代码做了什么?签名只告诉我们它是一种从字符串到字符串的方法,所以它显然它与输入字符串做点什么,或者可能无法做点什么并返回null,或突变某些状态,或者执行其他副作用,或者抛出其他副作用(这是毕竟是Java)。
密封特性案例类(i:int)扩展案例类(i:int)扩展def(str:string):选项[postalcode]
更好的是,此代码将字符串转换为两个可能的后支通(或德语)之一,或者未能执行此操作,返回无。估计猜测是此函数尝试从字符串创建有效的邮政编码。我们只需用几种类型指定我们的域,现在这段代码的意图很清楚。
从域驱动设计中借用术语,我们将域中的域名呼叫为专用构造域名原始。在语言原语(String,Boolean,Int,Float等)是编程代码的构建块的方式,域名是域模型和业务逻辑的构建块(ShoppingBag,订单,数量等。如果您在电子商务中)。
域名原始在其定义中精确,不可能是非法的,其存在意味着其有效性。
在实际业务逻辑中使用这些域基元素时,揭示了以这种方式建模的真正力量:
查看类型,只有有一件事可以做到这一点:基于邮政编码和房屋号而异步返回地址或没有结果。此功能将与任何后展码合作,因此我们可以推断我们的域名支持两者和德语地址。祝你好运从以下签名中讨论了所有这一点:
让我们调查在域逻辑中使用语言原语的潜在问题与另一个例子,这次具有正确的命名,其中我们模拟了一种从一个帐户将钱转移到另一个帐户的方法:
现在让我们计算这种方法可以被称为错误的方式:
fromaccountnumber和toaccountnumber可以是相同的帐号,这再次没有意义。
这是这种方法的9个潜在的错误,编译器不会帮助我们任何一个,它归结为人类弟子和勤奋做正确的事。
如果我们添加正确的检查,可以抓住第1,2,3,4和5,这种方法将在运行时爆炸,这是不幸的,但无论如何。问题6,但根本无法检查。如果来电者混淆了两个帐号,我们将无法找到,直到愤怒的客户开始呼叫!
案例类(a:帐户)案例类(a:帐户)def(来自:fromaccount,to:toaccount,金额:money):boolean
我们添加了额外的类型信息,如之前,现在如果来电者混淆了我们代码无法编译的参数。我们一直搬到缺陷层次结构,很好!
在上面的例子中仍然可以混合起来和陷阱,但现在至少会更加明显。我们不会更深入地进入它,但如果我们真的想将代码一直限制为11,我们可以使用像archUnit这样的东西来强制执行,只能从登录的用户中派生,确保它不可能创建它除此以外。
上面的代码更冗长,但谁关心?代码是类型安全的,其意图更明显。
很多现代,高级语言支持别名和/或纽特类型的一些概念:
以任何语言包装,而不是型式别名可能会对性能产生影响,因为我们基本上是拳击和解压缩域原语的内部值。仍然是性能和类型安全之间的权衡肯定是值得的。
现在在您当前的项目中,您可以算上需要多少个要求和断言和他们的亲戚?所有这些都像代码库中的笨蛋陷阱,当呼叫者跳过时,它们会在运行时爆炸。
以下是要为此需要一些炸弹处置的不完整清单:
具有相同类型的两个或更多个参数的函数(除非您的函数是换向)。
使用SET或ORDEREDSET更合适的列表,几乎总是。即使你不在意,也可以更好地沟通意图。
UUIDS作为方法参数,客户UUID与UUID的顺序不同。
到目前为止,我们还没有不得不处理外部世界。真正的程序必须一直注意垃圾数据,从数据库响应,用户输入,第三方服务,配置文件等。
[{:" b4ae6a1b-ee07-4fbe-9588-11f451980a07":"约翰":32,},{:" 2711eba4-098c-44e9-a8a2-518ff07969bf& #34 ;,:" Mary&#34 ;,:31}]
最终案例类(Val ID:String,Val名称:String,Val年龄:int)对象{def(输入:字符串):list [User] = ???}
可以从字符串解码用户对象并传递给程序的其余部分。但不高兴的道路怎么样?
从类型的角度完全合法,但域名不是我们想要的。如果这样的响应不小心地传递给我们的业务逻辑,它将成为滴答时间炸弹。使用Scala-Newtype并精制更好的编码:
最终案例类(value:uuid)最终案例类(value:string精制nonempty)最终案例类(value:int精细肯定)type = nonememylist [user]最终案例类(ID:userid,名称:姓名:名称,年龄:年龄)对象{def(输入:字符串):[DecodeException,Users] = ???}
现在不可能创造非法的国家,因为我们无法满足编译器,非法州已经变得无法形容。我们被迫而来在原始数据进入的计划中处理最多外层或边缘的无效输入。
由域名基元建造的适当的域模型迫使我们,开发人员做正确的事情。