BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

讨论:Java编程风格的改变

| 作者 赵劼 关注 5 他的粉丝 发布于 2009年8月18日. 估计阅读时间: 8 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

最近Stephan Schmidt在博客中发表了题为《下一代Java编程风格》的文章,阐述了他眼中Java编程风格的改变,以及未来的走向:

许多公司和开发人员正在从Java转向其他编程语言:Ruby、Python、Grrovy、Erlang或Scala等等。不过你可能做不到这一点。即便如此,你也可以改变你的编程风格,获取这些新语言的优势。事实上,在过去的15年中,Java编程风格也已经有明显变化了。

Stephan在文章中提出了以下几点:

  1. 尽可能地标注final:让所有东西不可变,把变量标为final可以阻止改变它的值。很多时候,重新为变量赋值会引入bug,你应该使用新的变量。除此之外,final可以提高代码的可读性。我针对这个话题还写过一篇文章:《Java中所有变量都应该是final的
  2. 没有setter:许多Java程序员会自然而然地为类中所有的字段加上setter。思考一下,真的每个字段都需要修改吗?更好的方法是创建包含改变后状态的新对象。此外,也试着去除getter,我们应该遵循“Tell, don't ask”的思想。
  3. 避免使用循环来操作List:从函数式编程那里获得的经验,循环并不是进行集合操作最好方法。例如,我们可以使用Google Collections提供的过滤功能。
     
    Predicate canDrinkBeer = new Predicate() {
         public boolean apply(HasAge hasAge) {
             return hasAge.isOlderThan( 16 );
        }
    };
     
    List<Person> beerDrinkers = filter(persons, canDrinkBeer);
  4. 使用单行代码:Java是一门繁杂(noisy)的语言,我们应该编写更精确的代码。尝试将代码写为一行。例如:
     
    public int add(int a, int b) { return a + b; }
  5. 使用大量接口:领域驱动设计已经大行其道,一个应该拆分为多种“角色”,即实现多种接口,提高复用程度。方法应该面向“角色”,而不是面向特定的类。我在《不要在Java中使用String》一文中讨论了更多这方面的内容。
  6. 使用Erlang风格的并发:Java的并发特性(如lock和synchronized)过于低端,难以使用。Erlang风格的并发是一种更好的做法。Java平台上已经有了AkkaActorom。此外,也可以使用java.util.concurrent中的Join/Fork和数据结构进行编程。
  7. 使用Fluent Interface:Fluent Interface可以使代码更短,更容易编写。Google Collections中的MapMaker是个不错的示例:
     
    ConcurrentMap graphs = new MapMaker()
        .concurrencyLevel(32)
        .softKeys()
        .weakValues()
        .expiration(30, TimeUnit.MINUTES)
        .makeComputingMap(
            new Function() {
                public Graph apply(Key key) {
                    return createExpensiveGraph(key);
                }
            });
  8. 避免在DTO中创建getter和setter:如果你拥有简单的DTO(Data Transfer Object),不要耗费精力去编写getter和setter,直接使用公开的字段吧。不过在你无法完全控制代码的使用情况时,还是小心为上。

这篇文章发表之后,有许多人发表了不同的看法。其中Cedric Otaku发表了文章《下一代Java与现在差不多》予以回应,其中反对了Stephan提出的大部分观点。

  • 尽可能final:太多final会降低代码的可读性,它无法代码额外的好处。我已经不记得上次因为重新给变量赋值而造成错误是什么时候了。值得一提的是,在字段以外的成员上标记final违反了Google的风格指南。
  • 避免setter:看上去不错,不过这不现实。有些时候你不愿把所有的参数都通过构造函数传入。此外,如果使用对象池的时候,可变的对象会让编程更为方便。Stephan不是第一个提出要将访问器(accessor)从OO编程中移除的人,不过这个说法很明显不可行
  • 避免循环:Java并不适合函数式编程风格,所以我认为使用Predicate的代码反而难以读懂。我估计大部分的Java程序员会同意我的观点,即使他们已经熟悉了闭包风格。
  • 单行代码:这要视情况而定。并引入临时变量把一个表达式拆开可以提高代码可读性,也容易为其设置断点。
  • 使用接口:不错的建议,但也不能过火。过去我也争论过类似的话题,不过引入太多接口会导致细小类型的爆炸,使你高端的类型意图变得模糊。
  • Erlang风格并行:重申一点,使用Java设计以外的编程风格是危险的做法。java.util.concurrent中包含了非常有用的功能,我遇到过不少基于这些元素的Java抽象,它们要优于Erlang风格的actor架构。
  • Fluent Interface:这个建议比较有趣,它与Stephan提出的另一个建议“避免setter”相违背。Fluent Interface只是setter的另一种形式,不是吗?
  • 使用公有字段:不,千万别这么做。你不会因为加了访问器而后悔,但是我能保证你会因为一时偷懒,使用了公有字段而后悔莫及。

在Cedric的文章之后,Stephan又对他的说法进行了补充:

没有setter并不代表你不能修改这个对象,我只是说纯粹的setter不是面向对象的思维方式。例如,你觉得stop()和setStop(true)哪个更好一些?

(针对Predicate代码不易读)我认为你的假设有误。循环是“程序化”的代码,而Predicate是经过封装的,可以重用的,易于理解的“对象”。这里并没有函数式编程,这里是纯粹的OO - 我提起FP只是因为我从那里“引入”了这个方式。

还有许多人对Stephon和Cedric的文章发表了评论,例如有人支持Stephan的观点,认为final的可以更好的表示出代码的意图。甚至有人提出:

更简单的解决方案是使用Scala :) - 不可变的状态、统一访问原则(字段、属性、方法看上去一样)、单行代码、使用monads或函数来替代循环……这些特性都已经在Scala中优雅地体现出来了。

您的Java编程风格是什么样的,和过去相比有什么改变吗?

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

过犹不及 by 高 德翔

刻意的风格改变是不必要的。你总没法子从苹果里面吃出菠萝味道,尽管你可以把它刻成菠萝的样子。

有的很有道理 by Lee John

例如没有语意的 getter/setter ,这已经误导很多人了
另外,我不觉得Fluent Interface与取消多余setter有冲突,实际上我感觉完全不理解Cedric Otaku在这里的意思

人性化 by yang jian

这个问题由来已久
我觉得使用这些东西都需要程序员先思考,然后再使用
即便你有最好的设计,但是程序员没有认真地去执行,还是白费心机

这种讨论很好。 by lei zhao

Fluent Interface很强大。其他的好像也有借鉴之处。用final也值得考虑。不过一些控制的大对象,或状态频繁变化的大对象,用final岂不是要经常new大对象?

写得不错 by chu easin

大部分意见和建议都不错。但是没有getter/setter 的变量在实际开发中是不现实的。

有可取的地方 by He Yiding

我比较喜欢 Predicate。

Re: 有可取的地方 by Jeffrey Zhao

Java的语法太累赘,真不适合函数式的风格。

编程之道 by lc leader

感觉编程是随意的,不要刻意的追求某种风格。只要能够从产品角度解决问题就可以了。

对《编程之道》感触较深。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

8 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT