吸气剂和二传手被认为有害

Java程序员习惯性地用“ getters”和“ setters”来修饰类,这种做法根深蒂固,以至于几乎没有人质疑为什么这样做或是否应该这样做。 最近,我认为最好不要这样做,并且我开始在编写的Java代码中避免使用它。 在这篇博客文章中,我将解释原因。 但是首先,要进行快速的历史课程。

JavaBeans

Getter和setter起源于JavaBeans规范 ,该规范最初于1996年末发布,并于1997年8月更新为1.01版。最初的想法是使对象的创建成为可能,这些对象可以像构建块一样用于组成应用程序。 这个想法过去了,“用户”可以使用某种构建器工具连接在一起,并自定义一组JavaBeans组件以一起充当应用程序。 例如,AWT应用程序中的按钮将是Bean(AWT是Java UI库Swing的前身)。 或者,某些JavaBeans更像是常规应用程序,然后可以将它们组合成复合文档,因此电子表格Bean可以嵌入到网页内。

当遵循以下约定时,对象就是JavaBean:

  1. 它必须具有一个零参数的构造函数,该构造函数不能失败。
  2. 它具有可通过“ getter”和“ setter”方法访问和更改的属性。
  3. 对于称为Foo的bean的任何属性,访问器方法必须称为getFoo 。 在布尔属性的情况下,可以将吸气剂称为isFoo
  4. Foo的setter方法必须称为setFoo
  5. Bean不必为每个属性都同时提供getter和setter:具有getter但没有setter的属性是只读的; 具有setter且没有getter的属性是只写的。

该规范描述了许多不同的用例,但是从上面的描述中可以清楚地看出,JavaBean被视为具有行为的对象,而不仅仅是数据包。 这个想法已经淡出人们的视线,但是尽管JavaBean被很大程度上遗忘了,但是Java中的getter和setter方法的习语仍然存在。

隐喻是错误的

“获取”和“设置”的概念似乎很自然,但这是否正确? JavaBeans约定使用“ get”来表示查询,这是一个没有副作用的操作,但在现实世界中,getting是一个会改变状态的动作:如果我将一本书下架,则该书不再上架。 您可能会反对,这只是纯粹的学问,但我认为这种误解会鼓励我们错误地思考我们编写对象以进行交互的方式。 例如,如果我们有一个Thermometer类,那么大多数Java开发人员都会编写代码来读取温度,如下所示:

Temperature t = thermometer.getTemperature();

确实,“获取”温度是温度计的工作吗? 没有! 温度计的工作是测量温度。 我为什么要为此努力呢? 这是因为“获取”是必要的陈述:它是温度计的一项操作说明。 但是我们不想指示温度计在这里做任何事情; 它已经在做它的工作(测量温度),我们只想知道它的当前读数是多少。 阅读是由我们完成的。 因此,以这种方式编写时,代码更加自然:

Temperature t = thermometer.reading();

我认为这样可以更好地将责任真正归属。 但是请务必考虑是否需要访问器,因为…

对象不是数据结构

用getter和setter编写类的习惯对我们的编码方式有微妙的影响。 它自然化了我们应该进入对象以获取所需数据,对其进行处理,然后使用结果更新对象的想法,而不是让对象自己执行处理。 换句话说,它鼓励我们将对象视为数据包。 我们通过获取器提取数据,并通过设置器进行更新。 同时,对数据进行操作的代码位于其他位置。

如果我们的编码习惯使我们倾向于将对象视为纯数据结构,那么ORM框架会积极地实施它。 更糟糕的是,如果您使用的是Spring框架-并且如果您是Java开发人员,那么很有可能-默认情况下,它会将所有bean创建为单例。 (令人困惑的是,Spring bean与JavaBeans无关)。 因此,现在您有了一个由单例对象组成的系统,该系统在无行为的数据结构上运行。 如果您将代码和数据分开听起来像是您所熟悉的编程风格,那么您就没错:我们称其为过程编程。

考虑一下这是否是一件好事。 毕竟,Java被认为是一种面向对象的编程语言。 OO的一大优点是我们可以编写对象的类,这些对象的名称和交互作用反映问题域。 它使我们能够编写要解决的问题的代码,而不会模糊基本编程结构和原始数据类型的全局。 它帮助我们透过树林看木头。 我们不应该放弃这一点。

该怎么做

尽可能停止编写get and set! 有时这是适当的做法,但一定要停止使用IDE的功能来为您生成getter和setter。 这只是快速执行错误操作的便捷方法。 如果需要在对象上公开某个属性,只需将其命名为该属性,然后还要检查是否确实需要公开该属性。 询问为什么要这样做。 可以将任务委派给对象本身吗? 例如,假设我有一个表示货币金额的类,并且希望对一堆交易进行汇总:

Amount total = new Amount(transactions.stream().map(Transaction::getAmount).mapToDouble(Amount::getValue).sum());

代替getValue访问器,为什么不给Amount类一个add()方法并让它为我求和呢?

Amount total = transactions.stream().map(Transaction::getAmount).reduce(Amount.ZERO, Amount::add);

这带来了好处–也许您对使用双精度表示货币金额的想法很感兴趣。 没错,BigDecimal会更好。 第二个示例使此问题更易于修复,因为内部表示形式得到了更好的封装。 我们只需要在一处更改它。

也许您想获取对象的数据以测试它是否等于某物。 在这种情况下,请考虑在对象上实现equals()方法,并为您测试是否相等。 如果使用Mockito创建间谍,则无需使用参数捕获器:相反,您可以创建一个等值的对象作为示例,并将其直接传递给verify语句进行比较。

有时您必须创建访问器。 例如,为了将数据持久存储在数据库中,您可能需要访问数据的原始表示形式。 您是否真的必须遵循获取/设置命名约定? 如果您的回答是“这就是用Java完成的方式”,我鼓励您回头阅读JavaBeans规范。 您是否真的在编写JavaBean以按照规范描述的方式使用它? 您是否正在使用期望您的对象遵循约定的框架或库?

必须创建变种器的时间将减少。 函数式编程现在正像一股狂潮一样席卷整个行业,而不变数据的原理是一个很好的原则。 它也应该应用于OO程序。 如果没有必要改变状态,你应该考虑有必要改变状态,所以不用加一个赋值函数方法。 当您编写导致出现新状态的代码时,将尽可能返回新实例来表示新状态。 例如,BigDecimal实例上的算术方法不会更改其自身的值:它们返回表示其结果的新BigDecimal实例。 如今,我们拥有足够的内存和处理能力,可以使这种方式的编程变得可行。 而且Spring框架不需要依赖项注入的setter方法,它也可以通过构造函数参数进行注入。 实际上,这种方法是Spring文档推荐的方法。

某些技术确实要求类遵循JavaBeans约定。 如果您仍在为视图层编写JSP页面,则EL和JSTL期望响应模型对象具有getter方法。 用于在XML中对对象进行序列化/反序列化的库可能需要它。 ORM框架可能需要它。 由于这些原因而被迫编写数据结构时,建议您将其隐藏在体系结构边界后面。 当对象泄漏到您的域中时,不要让这些数据结构伪装。

结论

在与使用其他语言工作的程序员交谈时,我经常听到他们批评Java。 他们说诸如“太罗y”或“样板太多”之类的话。 Java当然有其缺陷,但是当我更深入地查询这些批评时,我通常会发现它们针对的是特定的实践,而不是针对该语言固有的东西。 做法不是一成不变的,它们会随着时间的流逝而发展,不良做法可以得到解决。 我认为在Java中随意使用get和set是一种不好的做法,如果放弃,我们会编写更好的代码。

翻译自: https://www.javacodegeeks.com/2018/03/getters-and-setters-considered-harmful.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html编辑器设置为publisher,将PDF转换为Publisher的简单方法

二、 如何把PDF文件转换为Publisher支持的图片格式一些专业的软件或者在线网站都可以帮助我们把PDF文件转换为Publisher支持的图片格式。下面将提供几种支持PDF文件转换为图片格式的方法。(1) 使用都叫兽™PDF转换器进行格式转换热点推荐 - ADs都叫兽™PDF转换器 - 多功能的PDF…

Oracle应用容器云上的WildFly Swarm

在此博客文章中,我将描述如何将打包在WildFly Swarmber -jar中的CloudEE Duke应用程序部署到Oracle Application Container Cloud 。 在Oracle Application Container Cloud中进行部署所需的部署工件是一个ZIP归档文件,其中包含应用程序ber-jar和清单文…

适合学计算机用的机械键盘,一款好用的机械键盘应该怎么选?看完这篇就明白了...

一款好用的机械键盘应该怎么选?看完这篇就明白了2019-07-30 15:53:134点赞14收藏3评论今天给大家带来好物推荐第1期——机械键盘。作为在办公室办公的从业者们,平时工作中与电脑的接触时间最多。而人与电脑的交互主要靠键盘和鼠标,其中使用最…

六年级计算机课学什么时候,六年级信息技术《进一步了解计算机》教学设计

六年级信息技术《进一步了解计算机》教学设计教学目标知识与技能:1.了解计算机的五大部件2.了解各种典型的、常见的输入设备、输出设备、存储器等。过程与方法:通过学生利用教师提供的主题资源网站自主学习,了解计算机五大部件。情感、态度与…

asciidoc文件阅读_可搜索的文件? 是的你可以。 选择AsciiDoc的另一个原因

asciidoc文件阅读Elasticsearch是一个基于Apache Lucene的灵活,功能强大的开源,分布式实时云搜索和分析引擎,可提供全文搜索功能。 它是面向文档且无架构的。 Asciidoctor是一个纯Ruby处理器,用于将AsciiDoc源文件和字符串转换为…

专转本计算机专业录取分数线,2018江苏专转本各专业分数线一览!

原标题:2018江苏专转本各专业分数线一览!2018江苏专转本分数线梳理018江苏专转本考试已过去四个月,分数线已经公布了三个多月。按照分数线进行梳理大致情况如下:300分以上院校专业常州大学的财务管理 320分独占鳌头。300分以上分数…

坚实原则:开放/封闭原则

先前我们讨论了单一责任原则。 关于实体原则首字母缩写, 打开/关闭原则是该行中的第二个原则。 “软件实体(类,模块,功能等)应打开以进行扩展,但应关闭以进行修改” 通过采用该原理,目标是在不…

trim函数 html,trim、stripslashes、htmlspecialchars函数

通过 PHP 验证表单数据我们要做的第一件事是通过 PHP 的 htmlspecialchars() 函数传递所有变量。在我们使用 htmlspecialchars() 函数后,如果用户试图在文本字段中提交以下内容:location.href(http://www.hacked.com)- 代码不会执行,因为会被…

有效的Java第三版有哪些新功能?

自从听说即将出版的有效Java 第三版以来,我一直想知道其中有什么新内容。 我假设将涵盖自Java 6以来引入Java的功能,的确如此。 但是,第三版Java开发人员经典版也有一些其他更改。 在本文中,我提供了有关在第三版中添加&#xff0…

综合知识计算机类编制,天津事业编综合知识是什么

天津事业编综合知识有三类,分别是文字综合类、财会类、计算机类,考试时根据岗位考试要求进行一类综合知识的考核,均为主客观性试题,考试时限为150分钟,满分为100分。综合知识(文字综合类)简介(一)测试内容综合知识(文字…

哥大计算机科学学费,哥大计算机科学专业成功案例解析!!!

学生背景:学生:刘同学本科背景:北京大学 生物工程专业GPA: 3.5/4.0雅思7.5 GRE320录取院校:哥伦比亚大学—MS in Computer Science计算机科学硕士规划分析:1、背景分析L同学本科读的是生物工程专业,因为同学…

moxy json介绍_MOXy是GlassFish 4中新的默认JSON绑定提供程序

moxy json介绍GlassFish 4现在可以提供完整的Java EE 7(JSR-342)平台。 EclipseLink为该发行版做出了一些重大贡献。 首先是提供JPA 2.1(JSR-338)实现。 我将在本文中介绍的第二个内容是EclipseLink MOXy,它现在是JAX-…

大学计算机科技论文格式,《中国科技论文在线》稿件格式

《中国科技论文在线》期刊以中国科技论文在线网站http://www.paper.edu.cn/ 为基础,对在线发表论文进行评审,将评选的优秀论文作为期刊的主要稿源。稿件格式如下:中文标题(20字以内)作者11,作者22,……(1. 学校 院系,城…

使用Spring Boot和React进行Bootiful开发

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。 在过去的几年中,React受到了很多积极的报导,使其成为Java开发…

计算机图形学结课论文,计算机图形学结课论文精要.doc

计算机图形学结课论文精要2017届结课论文《计算机图形学基础教程》—小球的弹跳运动学生姓名学 号所属学院专 业 计算机科学与技术班 级塔里木大学教务处制目录摘 要11.背景11.1计算机图形学概述11.2计算机图形画面的分类22.OpenGL概述22.1程序的基本结构32.2状态机制43.方案论…

word计算机基础考试题及答案,计算机基础习题及答案题库(期末考试)-word资料(精).doc...

文档介绍:1. 计算机的诞生: 第一台电子计算机是 1946 年在美国诞生的,该机的英文缩写是。答案(A)ENIAC 2. 计算机的诞生: 第一台电子计算机诞生于______ 。答案(C) 美国 3. 计算机的诞生: 第一台电子计算机诞生于______ 。答案(C)1946 年 4. 计算机的诞生: 世界上公…

编译hotspot_从Hotspot JIT编译器打印生成的汇编代码

编译hotspot有时,在对Java应用程序进行性能分析时,有必要了解Hotspot JIT编译器生成的汇编代码。 这对于确定已做出的优化决策以及我们的代码更改如何影响生成的汇编代码非常有用。 在调试并发算法以确保已按预期应用可见性规则时,知道何时发…

计算机硬盘按不同接口,硬盘接口不同 速度差别竟然这么大

硬盘接口是硬盘与主机系统间的连接部件,作用是在硬盘缓存和主机内存之间传输数据。不同的硬盘接口决定着硬盘与计算机之间的连接速度,在整个系统中,硬盘接口的类型以及好坏都会直接影响程序运行快慢。说到硬盘接口我们常见的有SATA、PCI-E、M…

计算机导论设计实验,基于抽象知识点的《计算机导论》实验软件设计

Development of Experiment Software for《Computing Essentials》based on the Abstract Knowledge Points1、 College of Computer and Information Science, Southwest University, Chongqing, 400715Abstract:This paper develops an experiment software for 《…

使用Java的@Deprecated前瞻

我偶尔遇到一种情况,我需要引入新的API或构造以供其他人试用,但是我知道在使用某些API后,它可能会根据其他人的反馈而改变。 在这种情况下,我想以某种方式注释该构造,以警告其他开发人员此新添加的构造的暂定性。 在这…