我已经习惯了像JPA这样的框架来进行数据库行和Java对象之间的对象关系映射。
但是,在我的公司中,我们使用ORM的专有框架,它不使用实体类来表示实体,而只是一个java.util.Map
类,其数据库列值映射到它们的名称。
通常,这样的地图也可以作为表示层的模型来呈现表单。再次发布表单将参数作为映射注入到处理程序方法中。它是2000年初的旧框架。
甚至认为在实体类中使用地图闻起来像过时和反模式,我实际上喜欢"动态"这个模型的本质。在将map传递给表示层之前,您可以轻松地将任何数据添加到业务逻辑层中的映射中,并且它只是对模板本身的更改而成为表单的一部分。如有必要,它允许您使用任何实体来扩充任何实体。如果您必须在某些条件下显示某个字段的某些通知,那么这最终会很有用。您只需检查条件,在必要时将通知添加到地图,并在模板中渲染它(如果它存在于地图中)。如果我使用实体类,我将需要使用属性重构实体类接口,该属性甚至不是实体的真实属性。业务逻辑充满了这些特殊条件,并且不断发展。
这是一种危险的想法 - 我是不是因为反模式而堕落?或者在复杂的业务领域中使用这种模式是否合理,这种模式是否具有名称?
答案 0 :(得分:1)
我不知道哪种模式适合您的描述,但在实体类上使用Map
也有缺点。
在将地图传递到表示层之前,您可以轻松地将任何数据添加到业务逻辑层中的地图中,并且只需更改模板本身即可成为表单的一部分。
您认为优势意味着您永远无法确定Map
的状态。如果通过服务1加载实体,则映射可能包含一些值。如果您通过另一个服务2加载同一个实体,它可能不包含某些值。 Map
的状态是特定于用例的。
由于您使用的是Map
,因此从客户的角度来看,每个属性都具有相同的类型,例如Map<String, Object>
。因此,如果您在代码中看到实体映射,则还必须知道它具有哪种类型。不知道它会很难,例如计算订单总数。
只要您是唯一一个处理代码且您知道所有Map
个状态的人,您就会认为它是灵活而快速的。如果您有一段时间没有使用此类代码,您可能会忘记Map
可能具有的不同状态。然后,您需要遍历每个用例的完整代码,以查看某些代码是添加或删除属性还是仅替换属性类型。
因此,请尝试从文档角度考虑该设计。专用实体类的一大优点是它被命名。你可以给一个名字,因此给一个意思。 E.g。
public class PlacedOrder { ... }
public class Refund { ... }
您还可以轻松地将javadoc添加到类中,以提供有关此类在您的上下文中的含义的更详细信息。这通常称为Ubiquitous Language
。我经常使用术语域语言,因为它更容易说话。
根据我的经验,这种设计往往导致难以维护的系统。在代码库很小的开始,你真的很快。但这并不令人惊讶,因为您通常不会应用clean code原则来节省文档时间。
由于编译器无法检查类型,因此只能在运行时找到类型问题。这意味着您必须创建一个大test harness,因为测试还必须发现编译器将报告的错误。或者你只是开发试验和错误的方式,但这不是我的方式,并不满足我。