实体是否有行为?不是吗?
为什么或为什么不呢?
如果没有,那是否违反了封装?
答案 0 :(得分:6)
如果您的实体没有行为,那么您就不会编写面向对象的代码。如果一切都是使用getter和setter完成而没有其他行为,那么你就是在编写程序代码。
许多商店say they're practicing SOA当他们保持实体愚蠢时。他们的理由是数据结构很少改变,但业务逻辑确实如此。这是一个谬论。有很多模式可以解决这个问题,而且它们并不涉及将所有东西都减少到吸气剂和固定剂袋中。
答案 1 :(得分:4)
实体不应该有行为。它们代表数据,数据本身是被动的。 我目前正在开发一个遗留项目,其中包含实体中的行为,这是一个噩梦,代码是没有人愿意接触的。
您可以在我的博文中了解更多信息:Object-Oriented Anti-Pattern - Data Objects with Behavior。
属性和行为
对象由属性和行为组成,但数据对象按定义仅表示数据,因此只能具有属性。书籍,电影,文件,甚至IO流都没有行为。一本书有一个标题,但它不知道如何阅读。电影有演员,但不知道怎么玩。文件包含内容但不知道如何删除。流有内容但不知道如何打开/关闭或停止。这些都是具有属性但没有行为的数据对象的示例。因此,它们应被视为哑数据对象,我们软件工程师不应强迫它们行为。
传递数据而非行为
数据对象在不同的执行环境中移动,但行为应该被封装,并且通常仅与一个环境相关。在任何应用程序中,数据都被传递,解析,操作,持久化,检索,序列化,反序列化等等。例如,实体通常从休眠层传递到服务层,再传递到前端层,然后再传回。在分布式系统中,它可能会通过多个管道,队列,缓存并最终进入新的执行上下文。属性可以应用于所有三个层,但是特定行为(如save,parse,serialize)仅在各个层中有意义。因此,向数据对象添加行为违反了封装,模块化甚至安全原则。
代码写得像这样:
book.Write();
book.Print();
book.Publish();
book.Buy();
book.Open();
book.Read();
book.Highlight();
book.Bookmark();
book.GetRelatedBooks();
可以像这样重构:
Book book = author.WriteBook();
printer.Print(book);
publisher.Publish(book);
customer.Buy(book);
reader = new BookReader();
reader.Open(Book);
reader.Read();
reader.Highlight();
reader.Bookmark();
librarian.GetRelatedBooks(book);
自然面向对象建模有多大区别!我们从一个可怕的Book课程到六个独立的课程,每个课程都对自己的个人行为负责。
这使得代码:
答案 2 :(得分:1)
这取决于他们是什么类型的实体 - 但“实体”一词至少对我来说意味着商业实体,在这种情况下他们应该有行为。
“业务实体”是对现实世界对象的建模,它应该封装对象表示在软件上下文中的所有业务逻辑(行为)和属性/数据。
答案 3 :(得分:0)
如果您严格遵循MVC,您的模型(实体)将不会有任何固有行为。但是,我确实包含了任何帮助方法,可以最简单地管理实体持久性,包括有助于维护与其他实体的关系的方法。
答案 4 :(得分:0)
如果您打算将您的实体暴露给全世界,那么您(通常)会更好地保持实体的行为。如果要集中业务操作(即ValidateVendorOrder),则不希望Order具有运行某些逻辑来验证自身的IsValid()方法。您不希望代码在客户端上运行(如果他们捏造它就会发生什么。即类似于不提供任何客户端UI来设置放置在购物车中的商品的价格,而是在URL上发布虚假价格。如果你没有服务器端验证,这不好!并且重复验证是......冗余......干(不要重复自己)。
当实体上的行为不起作用的另一个例子是延迟加载的概念。今天很多ORM将允许您在实体上访问属性时延迟加载数据。如果您正在构建一个3层应用程序,这只是不起作用,因为您的客户端最终无意中尝试在访问属性时进行数据库调用。
这些是我保持行为偏离实体的最重要的论点。