对于包含...的对象的对象是否有名称或特定规则,等等。我正在使用一个复杂的系统,该系统通常具有运行 5-10 层深的对象。我听说这样做的一个原因是一次将大量数据从服务器传递到客户端,有没有更好的方法来做到这一点?
编辑:它似乎是一些反模式的组合。域模型应该被清理,以下反模式是异味:Train Wreck Pattern 和Everything but the kitchen-sink map
对于包含...的对象的对象是否有名称或特定规则,等等。我正在使用一个复杂的系统,该系统通常具有运行 5-10 层深的对象。我听说这样做的一个原因是一次将大量数据从服务器传递到客户端,有没有更好的方法来做到这一点?
编辑:它似乎是一些反模式的组合。域模型应该被清理,以下反模式是异味:Train Wreck Pattern 和Everything but the kitchen-sink map
我不知道这种对象树的名称。但是一个众所周知的反模式是火车残骸模式,当代码使用过多的方法链接时就会出现这种模式。
objA.getChildB().getChildC().getChildD()....getChildZ().performSomeAction();
包装所有内容是一个很好的经验法则
.getChildC().getChildD()....getChildZ().performSomeAction();
成一个方法
objA.getChildB()
让我们调用这个方法performSomeActionDeepDownTheObjectTree()
。
这看起来像是一个变质的域模型(不是反模式名称,顺便说一句:) 它源于存在定义明确的域模型这样的东西的错觉。实际上,问题域的某些方面可以被优雅地建模,但在更精细的细节层次上,有例外上的例外和特殊情况下的特殊情况,每个特定于单个服务方法,这破坏了这种优雅。
许多嵌套对象的出现通常是不断将域模型“研磨”到更细粒度的结果,希望每个实例变量都可以在不同的上下文中重用。有一个突破点,重用每个域属性的教条命令不再有意义。
我的出路是停止尝试创建一个万能的域模型,并使用专门为每个服务调用设计的对象。这些对象可能依赖于一些定义良好的域对象,但会以不干扰其他服务调用的方式单独添加任何特定信息。
该术语是“面向对象”,其中您通过定义对象类将大型复杂问题分解为较小的问题,每个对象都封装了问题的一小部分。对象交互的方式是通过消息传递,并且对象通过从它们包含的对象开始来查找要传递消息的其他对象。
问题越大越复杂,将其分解为可管理的部分所需的工作就越多,因此获得的对象层数就越多。有时,简单的小问题会被严重分解成大量对象,但这并不会使面向对象本身成为一种反模式。
主要问题只是数据对象通过嵌套以及包含不相关的数据而变得太大。示例:您正在对鸟类进行分类,而不是一个简单的鸟类对象,您收到一个对象鸟类,包含羽毛、喙、可能的寄生虫、空气、可能的HousesNestsCanBeIn 和食物类型,食物类型包含水果、昆虫、蠕虫、种子,种子包含橡树、榆树, thistle, possibleAnimalsThatCanEatSeeds 等等 –</p>
Everything but the kitchen-sink map反模式可能是最合适的。
给定一个具有许多复杂规则的复杂流程,所有内容(业务逻辑、相关和不相关的过程等)都被塞进地图中。
解决此问题的最佳方法是使用过滤操作,您可以在其中指定强类型接口,例如interface BirdList extends Iterable<Bird> {}
,查询系统提供了一个由足够数据支持的实现来支持该接口。
您的 API 可以提供许多不同的接口,例如BirdList
and BirdFeedingHabitMap
,BirdNestingHabitMap
等。客户端可以提出他们需要的接口列表,查询系统分析它们,获取数据,并使用代理类组装一个公开查询的实现类导致类型安全的方式。
包含包含……等的对象的对象
被称为列表,非常好;)
但你是对的,长序列的方法调用几乎没有问题,而且干净的代码气味称为不恰当的亲密关系。
不恰当的亲昵可以increase coupling, decrease cohesion
,有悖law of demeter
常理tell, don't ask
。
参考资料:如果您查找这些术语,您会发现很多答案。特别好的是内聚和耦合以及 Robert C. Martin 的书敏捷软件开发、原则、模式和实践。