【问题标题】:Java antipattern name? Objects containing objects containing... etcJava 反模式名称?包含对象的对象包含...等
【发布时间】:2012-11-05 08:46:13
【问题描述】:

对于包含...的对象的对象是否有名称或特定规则等等。我正在使用一个复杂的系统,该系统通常具有运行 5-10 层深的对象。我听说这样做的一个原因是一次将大量数据从服务器传递到客户端,有没有更好的方法来做到这一点?

编辑:似乎是几种反模式的组合。域模型应该被清理掉,下面的反模式是异味:Train Wreck Pattern 和Everything but the kitchen-sink map

【问题讨论】:

  • 不知道是不是反模式。如果您查看任何 ORM,您会发现包含 beans 的 beans...
  • 层数过多的代码称为“千层面代码”:)
  • 对于上述场景,我们有一个名为“责任链模式”的设计模式。只要一个实体只负责照顾它下面的下一个实体 - en.wikipedia.org/wiki/Chain-of-responsibility_pattern

标签: java refactoring anti-patterns


【解决方案1】:

我不知道这种对象树的名称。但是一个众所周知的反模式是 Train Wreck Pattern,当代码使用过多的方法链接时就会出现这种情况。

objA.getChildB().getChildC().getChildD()....getChildZ().performSomeAction();

将所有内容都包装起来是一个很好的经验法则

.getChildC().getChildD()....getChildZ().performSomeAction();

进入一个方法

objA.getChildB()

我们称这个方法为performSomeActionDeepDownTheObjectTree()

【讨论】:

  • 如果呼叫量增加,这不会导致 childB 不必要的膨胀吗?似乎最好创建一个包含必要对象的特定数据对象并添加对该对象的调用以封装逻辑
  • @FooBar 你可以这样做。如何解决这种反模式引起的问题留给读者练习:)
  • 如果我无法更改 A、B、C .. Z 中任何一个的方法/类怎么办?
【解决方案2】:

这看起来像是一个变质的域模型(不是反模式名称,顺便说一句 :) 它源于这样一种错觉,即存在定义良好的域模型之类的东西。实际上,问题域的一些方面可以被优雅地建模,但在更精细的细节层次上,有例外的例外和特殊情况的特殊情况,每个方面都特定于一个服务方法,破坏了这种优雅。

许多嵌套对象的出现通常是不断将领域模型“研磨”到更细粒度的结果,希望每个实例变量都可以在不同的上下文中重用。重用每个域属性的教条式命令不再有意义。

我的出路是停止尝试创建一个万能的域模型,并使用专门为每个服务调用设计的对象。这些对象可能依赖于一些定义良好的域对象,但会以不干扰其他服务调用的方式单独添加任何特定信息。

【讨论】:

  • 听起来是个不错的解决方案,我得看看领域模型,看看是否可以清理它并实现一些新的特定对象来避免这种情况
【解决方案3】:

该术语是“面向对象”,您可以通过定义对象类将大型复杂问题分解为较小的问题,每个对象都封装了问题的一小部分。对象交互的方式是通过消息传递,对象从它们包含的对象开始寻找其他对象来传递消息。

问题越大越复杂,将其分解为可管理的部分所需的工作就越多,因此获得的对象层数就越多。有时,简单的小问题会被严重分解成大量对象,但这并不会使面向对象本身成为一种反模式。


主要问题只是数据对象通过嵌套以及包含不相关的数据而变得太大。示例:您正在对鸟类进行分类,而不是一个简单的鸟类对象,您收到一个对象鸟类,包含羽毛、喙、可能的寄生虫、空气、可能的HousesNestsCanBeIn 和食物类型,食物类型包含水果、昆虫、蠕虫、种子,种子包含橡树、榆树, thistle, possibleAnimalsThatCanEatSeeds 等等 –

Everything but the kitchen-sink map 反模式可能是最合适的。

给定一个包含许多复杂规则的复杂流程,所有内容(业务逻辑、相关和不相关的过程等)都被推送到地图中。

解决此问题的最佳方法是使用过滤操作,您可以在其中指定一个强类型接口,如 interface BirdList extends Iterable<Bird> {},并且查询系统提供了一个由足够数据支持的实现来支持该接口。

您的 API 可以提供许多不同的接口,例如 BirdListBirdFeedingHabitMapBirdNestingHabitMap 等。客户可以提出他们需要的接口列表,查询系统会分析它们,获取数据,然后使用proxy classes 组装一个以类型安全的方式公开查询结果的实现类。

【讨论】:

  • 当然,我不是在争论这个问题,我说的是当你有对象时,特别是嵌套到 n 度的数据对象导致数据膨胀和无法访问正确数据的麻烦甚至知道检索对象时包含哪些数据
  • 虽然这可能是一个问题,但这不是主要问题,主要问题只是数据对象通过嵌套以及包含不相关数据而变得太大。示例:您正在对鸟类进行分类,而不是一个简单的鸟类对象,您收到一个对象鸟类,包含羽毛、喙、可能的寄生虫、空气、可能的HousesNestsCanBeIn 和食物类型,食物类型包含水果、昆虫、蠕虫、种子,种子包含橡树、榆树, thistle, possibleAnimalsThatCanEatSeeds 等
  • @FooBar,这些数据是通过网络发送的吗?你有没有办法说——我需要满足这个接口的东西,只想要满足这个接口所需的数据?
  • @FooBar,请看我的编辑。 “除了厨房水槽地图之外的所有内容”反模式描述了您在谈论的内容。
  • 是的,我会说这是对所发生事情的一个很好的描述,我认为你得到了正确的反模式。对于解决方案,尽管我认为我的需求将是上面建议的,通过修剪对象并为超出其范围的情况创建自定义对象来清理域。
【解决方案4】:

对象包含包含……等的对象

被称为列表,非常好;)

但是你是对的,长序列的方法调用几乎没有问题,而且干净的代码气味称为不恰当的亲密关系

不适当的亲密关系可以increase coupling, decrease cohesion,违反law of demeter和规则tell, don't ask

参考文献:如果您查找这些术语,您会发现很多答案。特别好的是Cohesion and Coupling 和书Agile Software Development, Principles, Patterns, and Practices by Robert C. Martin

【讨论】:

  • 我不认为这被称为“列表”。列表是关于彼此相邻的事物。
  • 这是Object 的列表 - 但它更多地是一个玩笑,因为包含对象的对象 .... 完全没问题,只是方法调用的长序列不是。我希望我的回答能澄清这一点。
  • 不是列表。一个House 对象可以包含一个Door 对象,它可以包含一个Lock 对象,它可以包含一个KeyHole 对象等等。这是层次结构,而不是列表。
  • @jlordo: ...它们都是Object类型的
  • OP 没有说明对象的类型。
猜你喜欢
  • 2020-05-05
  • 2015-01-30
  • 2012-04-20
  • 1970-01-01
  • 2012-02-17
  • 2011-01-01
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多