日历

September 2020
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
282930  

值类型是否有行为?

Home Forums 《冒号课堂》讨论区 值类型是否有行为?

Tagged: 

  • This topic is empty.
Viewing 5 reply threads
  • Author
    Posts
    • #1073
      Todd
      Member

      OOP对象3大特征:标识、状态、行为。书中认为值类型具备:状态和行为,而不具备标识。不过,最近我看到一些其他一些资料更强调值类型不具备行为,而是表示状态。我想这是有道理的,因为行为必定要有主体,即标识。所以,我更倾向于从纯语义的角度来看,值类型应该不具备行为。

    • #1247
      hui
      Keymaster

      你的这个问题本质上是使用充血对象模型(rich object model)还是该使用贫血对象模型(anemia object model)的问题。显然书中提到的DTO属于后者,而VO则视具体情况而定。Eric Evan认为,在application layer(service layer)中可用后者,而在Domain Layer(Model Layer)中则建议用前者,否则有让对象式滑到过程式之嫌(可以参考Martin Fowler的这篇文章),是一种anti-pattern。当然,这也只是一种观点,反方观点同样也有市场。具体选择与实际项目、设计者的偏好以及所用的语言、框架等有关。

      另外,《冒号课堂》中在提到值类型时,倾向于用运算(operation)而非行为(behavior)来指代对象的方法,毕竟前者的“动感”不如后者,似乎更适用于值类型(值本就是运算的作用对象)。这样你或许更能接受些。

      举个常见的例子:Money作为一个典型的值类型,你可以说它是一个被动的实体,不应有任何“行为”,但赋予它一些“运算”往往会很方便,比如add(加法运算),exchange(兑换运算)等等。相比把这些运算与Money分拆开来的做法,这种设计通常更简洁、更优雅些。

    • #1248
      Todd
      Member

      语义上值类型的确可以参与运算,语法上我还是更倾向于使用自由函数或运算符重载。可以把值类型和它所参与的运算定义在一个模块中避免分拆。

    • #1249
      hui
      Keymaster

      运算符重载不仅很多语言不支持,而且许多运算无法对应合理的运算符,因此不是通用的解决办法。至于自由函数,有其灵活的一面,但也不总是最好的选择。从一种意义上说,这是在过程式与对象式之间作选择;从另一种意义上说,这是在系统设计中对模块的职责分配的选择。这里没有一个绝对的胜者。

    • #1250
      Todd
      Member

      经过思考我改变了看法,我认为的确应该把值和运算放在一起形成类,这个过程正是数据抽象。值的意义不能脱离运算而单独存在,而运算的意义也是相互联系的,没有+就没有-,+和-必定相互依存。

      我现在认为对于引用对象具备标识,状态和行为;值对象具备状态和运算。

    • #1251
      hui
      Keymaster

      很多时候状态与(某些)行为究竟是否该绑定是很难抉择的,这也是许多动态语言都支持mixin的缘故。

Viewing 5 reply threads
  • You must be logged in to reply to this topic.
 请您评分1星(很差)2星(不行)3星(一般)4星(不错)5星(很棒)