从你想要写优秀代码的那一刻开始,你的代码就一定会越写越好,加油~。我平时也会经常去思考这方面的问题,主要是为了两个目的:
- 为自己,清晰、职责分明、可维护的代码有利于后期迭代
- 为他人,离职了以后同事能更好地交接
我个人认为,要想写出优秀的代码,可以从以下几个方面入手:
- 观察并吸收同事优秀的代码风格(这取决于你自己的品味了,品味差的话可能越学越差...)
- 代码可读性放在第一位
- 注意大的性能优化
- 学习并在适当的场景使用设计模式
学习同事的代码
我倒不是刻意去模仿同事的代码,而是为了学习公司业务时,被迫看了很多同事的代码。有时看到同事基于某个需求的实现时,会反思:如果这个需求让我来实现,我会怎么做,能写得更好吗?当我觉得自己可能有更好地思路时,我会一边想一边改,验证自己的想法。当然,最后我会revert刚才的代码,不会提交上去,毕竟不是我的需求啊...
时刻注意代码可读性
我一向觉得,代码的可读性应该排在性能优化前面(只要你不是for循环里rpc调用)。这里介绍一下我工作中最常用的一些技巧。
不要使用魔法值
不要这样:

应该这样:

再不济也要这样:

变量声明后立即使用
不要这样:

用卫函数代替if else
尽量不要这样:

可以这样:

像写诗一样换行
这是现代诗:

这是代码:

它们的共同点是,换行后就成了诗。
抽取类、方法
也就是让职责更明确、注重封装性。别在A方法中,把整个原本属于B方法的内容塞进去,阅读代码的人可能并不关心B做了啥。

方法内的代码层次尽量保持一致
少用显式for循环(多使用Java8)
这个:

还有这个:

一般来说第二个可读性更佳,因为它是内部迭代,你看到的只剩下业务含义,而for循环暴露太多无关细节,阅读代码的人需要去筛选业务信息。
记得打日志
新手往往通篇代码没有一行日志,等出问题时,排查很慢,这也是新手和老鸟的差距之一。
注意大的性能优化
很多人习惯于对性能吹毛求疵,实际上大部分内存级别的性能优化是没太大必要的(比如是不是多一次for循环内存处理),无非就是1ms和2ms的区别。

很多人巴不得在一个for循环中完成左右操作,最终显得十分拥挤混乱。实际上内存操作是很快的,为了可读性,可以适当拆分for循环。
但千万别在循环中进行网络调用,比如rpc或数据库查询,这个反而要注意。内存for循环拼死拼活省下来的几毫秒都不够一次网络调用挥霍的。
学习并使用设计模式(理解业务的基础上)
学习设计模式本身其实能提高你的代码鉴赏能力,你会了解到什么是"代码的坏味道",也就知道了怎么避免它,最终也就能顺理成章写出优秀的代码。但设计模式的使用场景其实是重构,也就是提倡所谓的"refactor to pattern(重构得到模式)",也就是说好的设计模式应该是通过一次次的重构引入的,而不是此地无银三百两、霸王硬上弓、司马昭之心路人皆知、装逼不成反被....
咳咳,总之就是因地制宜、有的放矢。比如我前阵子用责任链重构了一次代码,那原本是一个积分兑换里的校验功能,但随着需求迭代,校验的逻辑最终有13条之多,整个方法已经有800行左右。于是我和同事给它进行了重构。

代码来自《设计模式那些事儿》,思想类似

代码来自《设计模式那些事儿》:将业务中的校验抽取到VerifyChain
原来的方法里,关于校验的逻辑最终只剩下一个方法调用。当然,把原本13个方法变成13个Verifier对象,看起来性能上不划算,但还是那句话,可读性往往比性能优先级更高。而且后期增加新的校验逻辑时,我并不需要去修改积分兑换的主逻辑代码(开闭原则)。
当然,设计模式本身是比较抽象的,如何落地是最大的难点,只能说慢慢领悟吧。祝大家代码写得越来越好。
最后推荐:
