设为首页收藏本站language→→ 语言切换

鸿鹄论坛

 找回密码
 论坛注册

QQ登录

先注册再绑定QQ

查看: 1173|回复: 1
收起左侧

Java工程师最常犯的10个问题 南京Java培训分享

[复制链接]
发表于 2016-8-8 13:52:34 | 显示全部楼层 |阅读模式
  当今这个社会,不论想做什么,都要尽全力去做,反之很快就会被淘汰。那么要做一个最优秀的Java软件开发工程师,除了努力以外,还要做到哪些方面呢?南京万和Java培训总结了那些有经验的开发者最常犯的10个问题。

  1、像C语言一样使用Java (即不理解面向对象编程的理念)

  回到C语言编程的时代,C语言建议用过程化的形式来书写代码。开发者使用结构体存储数据,通过函数来描述那些发生在数据上的操作。这时数据是愚笨的,方法反而是聪明的。

  南京万和Java培训注:数据和函数是分离的没有直接的上下文来描述之间的关系。

  然而Java正好是反其道而行。由于Java是一门面向对象的语言,在创建类的时候数据和函数被聪明地绑定在一起。

  然而大多数的Java开发者要么不理解上述两门语言之间的区别,要么就是他们讨厌编写面向对象代码。虽然他们知道过程化开发方式与Java有些格格不入。

  一个在Java应用程序中,最显而易见的过程化编程就是使用instanceof,并在随后的代码中判断向上转换或向下转换。instanceof有它合适使用的情况,但在企业级的代码中通常它是一个严重的反模式示例。

  下面的示例代码描述了这种情况:

  

                               
登录/注册后可看大图

  使用面向对象的来重构以后的代码如下:

  

                               
登录/注册后可看大图

  南京万和Java培训注:这里可以认为使用设计模式当中的Factory method模式。

  每个继承Customer(或者实现Customer接口)定义了一个返回折扣的方法。这样做的好处在于你可以假如新的类型的Customer而不需要关系customer的管理逻辑。而使用instanceof的判断每次添加一个新的类型的Customer意味着你需要修改customer打印代码、财务代码、联系代码等等,当然同时还需要添加一个If判断。

  2、滥用延迟初始化 (即不能真正的理解对象的生命周期)

  大家是不是经常能发现如下的代码:

  

                               
登录/注册后可看大图

  延迟初始化初衷是好的,即如果你有个非常昂贵的对象(譬如对象需要网络连接或者连接Web API等等),当然应该只在需要的时候创建它。

  然而,在你的项目中使用这项技术的时候最好确认以下两点:

  这个对象真的很“昂贵”(你是如何给出这样的结论或者定义?)

  存在这个对象不被使用的情况 (确实不需要创建这个对象)

  在实际开发中,南京万和Java培训不断发现延迟初始化被用在对象上。但实际上,这样的对象要么不是真的那么“昂贵”,要么总是在运行期创建。延迟初始化这种对象能得到什么好处呢?

  过度使用延迟初始化的主要问题在于它隐藏了组件的生命周期。一个经过良好搭建的应用程序应该对它主要部件的生命周期有清晰的了解。应用程序需要非常清楚对象什么时候应该被创建、使用和销毁。依赖注入可以帮助定义对象的生命周期。

  但依赖注入在对象创建时也有副作用。使用以来注入表明应用程序状态依赖于对象被创建的顺序(按照要求的类型顺序)。由于涵盖了过多的用例,对应用程序调试就变成了一件不可能完成的事情。复现生产环境也变成一项巨大的工程,因为你必须十分清楚场景执行的顺序。

  相应的我们需要做的就是定义应用程序启动时需要的所有对象。这也带来了一个额外的好处,可以在应用程序发布过程中捕获任何致命的错误。

  3、把GOF(俗称四人帮)当作圣经

  如果你没看过《设计模式》,没有记住模式的名字或者准则的话,那么在面试中就可能无法通过。期望这样的错误可以慢慢改善。

  不要误解我,这本书本身是没有问题的。问题出在人们如何解释以及使用它。下面是通常场景:

  架构师马克,拿到这本书开始阅读。他觉得这本书牛逼坏了!

  马克趁热打铁开始阅读现在工作的代码。

  马克选择了一种设计模式并应用到了代码当中。

  随后马克把这本书推荐给了那些跟他重复同样步骤的资深开发者。

  结果就是一团糟。

  如何正确使用这本书实际上已经在导读中做了清晰的说明(提醒那些不看导读的人)——“在过去你有个问题,而且这个问题总是一遍又一遍地困扰着你”。注意到其中的顺序了吗?先有一个问题,然后查看这本书之后找到对应的解决方案。

  不要掉进看这本书的陷阱当中——“找到一个方案然后尝试把它应用在自己的的代码中。尤其要注意的是,一些书中描述的模式在现实当中已经不再正确。”

  4、单例模式-已经成为反模式之一
  南京万和Java培训已经在上面设计模式的讨论中提到了这一点,但单例模式需要单独说明。请跟着南京万和Java培训重新下面的话:

  单例模式是一个反模式 单例模式是一个反模式单例模式是一个反模式单例模式是一个反模式单例模式是一个反模式……

  单例模式以前有它们适用的场景。但是现在随着依赖注入框架的流行,单例模式已经可以完全剔除了。当你使用单例的时候,实际上正在向你的代码引入一系列新的问题。

  之所以这么说,理由如下:

  单例模式在类中引入了隐含的依赖关系。

  单例模式让代码变得不便于测试(即使用mock帮助)

  单例模式把资源创建与资源获取给混在一起了

  单例模式容易带来全局状态副作用(译注:这个实际上好理解,即单例实际上引入了全局状态,那么状态更改失败或者发生错误容易造成整个应用程序的行为不可确定)

  单例模式容易带来并发问题。

  5、忽略方法的可见性(作用域)

  大家是不是一直羡慕那些有经验的Java开发者,他们认为Java只有3中方法可见性(作用域)修饰符。好吧,其实应该是四种,还有一个称为包缺省修饰符。但是这里南京万和Java培训不想去解释这些事情,相反需要注意的是其它方面。

  南京万和Java培训真正想说的是,你需要特别注意公有方法。由于公有方法对整个程序来说都是可见的,所以这些方法需要尽可能足够简练,在编写类库时尤其如此(可以看一下SOLID准则)。

  不知道大家是不是很讨厌看见那些本应该是私有的方法被设计成公有方法。不仅仅因为这样对外界暴露了类的内部实现细节,更因为这些方法不能够也不应该被外界使用。

  一个“经典”的结论是,你应该不停地对全局方法进行单元测试。南京万和Java培训看到许多所谓的架构师相信把那些私有方法变成公有方法是可以接受的,仅仅因为这样做可以方便单元测试。

  测试私有方法根本上就是错误的。正确的办法应该是通过测试公有方法来隐含地测试私有方法。需要提醒的是,如果只是为了单元测试,任何情况都不可以把类的私有方法变为公有方法(考虑使用方法覆盖method overriding)。

  6、总是使用项目定制的StringUtils

  这样的情况存在于一些早期的Java项目中,你会发现很多StringUtils、DateUtils、FileUtils等工具类。现在开始了解这么做的问题,为了使这些工具类变得成熟稳定所付出的精力是巨大的。

  但是新的代码在没有任何限制的情况下也这么做就变得不可理解了。一个架构师或者资深开发者的职责就是关注那些通过完整测试的解决方案,这些方案会更易于集成到你的应用程序。

  如果你的职位描述包含架构师的字眼话,不应该有任何的理由说你不知道Apache Commons、Google Guava或者Joda Date。

  南京万和Java培训建议你还需要在一些开发不熟悉领域的程序时提前做一些研究。例如,在写REST服务时候如果需要创建PDF文件,应该先花点时间了解在Java领域存在哪些REST框架以及创建一个PDF文件有什么推荐的方法(运行UNIX命令是不推荐的一种做法,Java可以通过iText自行创建PDF文件)。

  7、构建过程依赖环境

  南京万和Java培训告诉你一个秘密:构建一个企业级项目的时候只有一种可以接受的方式,那就是:

  ◎新人在公司出现的第一天(完成他自己相关的一些手续)。
  ◎新人熟悉工作环境(机器等),安装JDK和他所喜好的IDE(开发工具)。
  ◎新人从公司的代码仓库中拿出代码(使用SVN、Git或者其它工具)。
  ◎新人花费5分钟了解公司的代码是使用什么构建工具(例如:Maven、Gradle或者ANT)。
  ◎新人运行命令构建整个应用程序。

  这不应该是一个理想化的状态,而应该是一种现实的状态去创建应用程序的构建系统。

  如果你的应用程序依赖于一个特定IDE、特定版本的开发工具插件、个人电脑的本地文件、没有标注过的环境变量、网络资源或者其它任何非标准的资源。相信这时候需要重新思考你的构建系统了。

  但请不要误解,一个需要自我检查的构建、额外的发布和生成文档的步骤、必要的外部设置或外部的数据库都需要在公司的wiki上有详细描述。

  对于一个新人来说,南京万和Java培训建议的构建行为应该至多1个小时内完成。曾经看到有些项目,新人通常需要2天来完成第一次构建应用程序。

  8、使用反射和自我检查

  当你在编写ORM(对象关系映射)框架、Java代理、元编译器、IDE时,如果你愿意的话很有可能需要使用Java反射。然而大多数的企业级项目很大程度只是操作数据存储的一些CRUD接口(创建、读取、更新、删除),Java反射反而变成了一个杀手。

  南京万和Java培训经常看到Java反射被用作性能提升、向前兼容或向后兼容。而且几乎总是被错误地使用。反射总是基于一些现在成立但是将来未必成立的假设(例如,方法名称命名规则)。

  反射的问题在于非常难于理解、调试以及解决相应的问题。

  很多人甚至不愿意深入这种自我修正的代码。在Java企业级项目中,使用反射就相当于在一个大厦里面安装了一个定时炸弹。虽然这个大厦现在可能是稳定的,但只要到了那个时间所有将变成灰烬。

  大家是不是很困扰,那些“资深”的架构师一直反复介绍反射。在实际变成中,你可以通过清晰的对象层次、清晰的定义和文档、可插拔的架构完成同样的功能。

  总结一下,不使用反射可以创建一个稳定、快速和可维护的Java应用程序。当然,如果想在企业级系统中增加麻烦的话那么就使用反射吧。

  9、错误地使用或者误解了依赖式注入

  对于一个企业级项目来说,依赖式注入通常被认为是好的概念。存在一种误解——如果使用依赖注入就不会出现问题。但是这是真的吗?

  依赖式注入的一个基本思想是不通过对象本身去查看依赖关系,而是通过开发者以在创建对象之前预先定义并且初始化依赖关系(需要一个依赖式注入框架,譬如Spring)。当对象真正被创建时,仅仅需要在构造函数中传入预先配置好的对象(构造函数注入)或者使用方法(方法注入)。

  然而总的思想是指仅仅传递对象需要的依赖关系。但是我依然可以在一些新的项目里发现如下的代码:

  

                               
登录/注册后可看大图

  当然,这不是真正的依赖注入。因为这个对象始终需要由它自己进行初始化。在上面的代码中“serverContext.getServiceLocator().getCreditCardProcessor()”这一行代码更加体现了该问题。

  注:这里指的是 creditCardProcessor、discount 这两个变量的初始化。

  当然,最好的方式应该是只注入那些真正需要的变量(最好是标记为final):

  

                               
登录/注册后可看大图
  注:南京万和Java培训提醒大家请注意两段代码的区别在于对于代码中需要的资源的范围。从使用依赖注入的角度来看,前一段代码中注入的范围很大,那就意味着有了更多的变化空间,但是容易造成代码的功能不单一,同时增加了代码测试的复杂度。后一段代码中注入的范围就很精确,代码简单易懂测试起来也比较容易。

  10、像使用perl一样来使用Java

  (跟其它编程语言比较)Java提供了一个好的属性,就是它的类型安全性。可能在一些小型项目中开发者只有你自己,你可以使用任何喜欢的编程风格。

  但如果是一个代码量很大以及复杂系统的Java项目中, 在错误发生时你需要早一些得到警示。

  大多数的错误应该在编译阶段而不是在到运行期就被发现。

  Java提供了许多特性去辅助产生这些编译器的警告。但是如果你写出下面的代码编译器还是没有办法捕获到对应的警告:

  

                               
登录/注册后可看大图
  注:南京万和Java培训提醒大家请注意这段代码只能工作在jdk 1.7 下。JDK 1.7以下的版本编译不能通过。

  这段代码是非常危险,而且编译器不会产生任何的警告帮到你。一个开发者也许会调用工厂方法以一个错误拼写“dig”创建一个Cat对象。但实际上,他需要的是一个Dog对象。

  这段代码不但会编译通过,而且错误往往只能在运行期被发现。更严重的是,这个错误的产生依赖于应用程序本身的特性,因而有可能在程序上线几个月以后才能发现它。

  你是否希望Java编译器可以通过某种机制帮你提前捕获到这样错误呢?这里南京万和Java培训提供一个更正确的方式来确保代码只有被正确的使用的情况下才能编译通过(当然还有其他的解决方案)。

  

                               
登录/注册后可看大图

  注:这里使用了java enum类型。

  南京万和Java培训期望在你解决类似的问题时上述10条可以用在你所擅长的领域,即使那些最好的开发者也需要记住总有些事情需要去学习和实践。


 楼主| 发表于 2016-8-8 13:53:43 | 显示全部楼层
想要学习JAVA开发的小伙伴,可以咨询江苏万和的老师哦,tel:400-110-1100。
或者进入官网了解:http://www.wanho.net/
现在暑假还有学IT技术,送旅游的活动。想要学IT的小伙伴,走起来~
沙发 2016-8-8 13:53:43 回复 收起回复
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2024-12-27 20:23 , Processed in 0.064362 second(s), 13 queries , Redis On.  

  Powered by Discuz!

  © 2001-2024 HH010.COM

快速回复 返回顶部 返回列表