赞
踩
前几篇文章,我们拿 Unix 这个超级大型开源软件开发作为因子,从代码设计编写和研发管理两个角度,讲了如何应对大型复杂项目的开发。接下来,我们再讲一下 Google 开源的 Java 开发库 Google Guava。
Google Guava 是一个非常成功、非常受欢迎的开源项目。在Java 项目开发中应用很广泛。当然,我们并不会讲解其中的每个类、接口如何使用,而是重点讲解其背后蕴含的设计思想、使用的设计模式。因内容较多,我们分三章进行讲解。
Google Guava 是 Google 公司内部 Java 开发工具库的开源版本。Google 内部的很多 Java 项目都在使用它。它提供了一些 JDK 没有提供的功能,以及对 JDK 已有功能的增强功能。其中包括:集合(Collections)、缓存(Caching)、原生类型支持(Primitives Support)、并发库(Concurrency Libraries)、通用注解(Common Annotation)、字符串处理(String Processing)、数学计算(Math)、I/O、事件总线(EventBus)等等。
下图是截取了 Google Guava 的包结构图,这样你看起来更加直观些。
JDK 的全称是 Java Development Kit。它本身就是 Java 提供的工具类库。那现在请你思考一下,既然有了 JDK,为什么 Google 还要开发一套新的类库 Google Guava?是否有重复造轮子?两者的差异化在哪里?
带着这个问题,结合 Google Guava,我们来学习如何在业务开发中,发现通用的功能模块,以及如何将它们开发成类库、框架或者功能组件。
很多人觉得做业务开发没有挑战,实际上,做业务开发也会涉及很多非业务功能的开发,比如我们前面讲到的 ID 生成器、性能计数器、EventBus、DI 容器,以及后面会讲到的限流框架、幂等框架、灰度组件。关键在于,我们要有善于发现、善于抽象的能力,并且具有扎实的设计、开发能力,能够发现这些非业务的、可复用的功能点,并且从业务逻辑中将其解耦抽象出来,设计并开发成独立的功能模块。
在我看来,在业务开发中,跟业务无关的通用功能模块,常见的一般有三类:类库(Library)、框架(framework)、功能组件(component)。
其中,Google Guava 属于类库,提供一组 API 接口。EventBus、DI 容器属于框架,提供骨架代码,能让业务开发人员聚焦在业务开发部分,在预留的扩展点里填充业务代码。ID 生成器、性能计数器属于功能组件,提供一组特殊功能的 API 接口,有点类似类库,但功能更加聚焦和重量级,比如 ID 生成器有可能会依赖 Redis 等外部系统,不像类库那么简单。
前面提到的限流、幂等、灰度,到底是属于框架还是属于功能组件,要视具体情况而定。如果业务代码嵌套在它里面的开发,那就可以称他们为框架。如果他们只是开放 API 接口,供业务系统调用,那就可以称它们为组件。不过,叫什么也没有太大关系,不必过于深究。
到底该如何发现项目中的这些通用的功能模块呢?
实际上,不管是类库、框架还是功能组件,这些通用功能模块都有两个最大的特点:复用和业务无关。Google Guava 就是一个典型的例子。
如果没有复用场景,那就没有必要抽离出来,设计成独立模块。如果与业务有关又可复用,大部分情况下会设计成独立的系统(比如微服务),而不是类库、框架或功能组件。所以,如果你负责开发的代码,与业务无关并且可能会被复用,那你就可以考虑将它独立出来,开发成类库、框架、功能组件等功能模块。
除了业务开发团队之外,很多公司还有一些基础架构团队,他们除了开发类库、框架、通用组件外,也会开发一些通用的系统、中间件,比如,Google MapReduce、Kafka 消息中间件、监控系统、分布式调用链追踪系统等。
当我们发现了通用功能模块的开发需求之后,如何将它们设计开发成一个优秀的类库、框架或者功能组件呢?
本章先不讲具体的开发技巧,先讲一些更普适的开发思想。我觉得有了这些,你应该更容易理解后面的内容。
作为通用的类库、框架、功能组件,我们希望开发出来之后,不仅仅是自己项目使用,还能用在其他团队的项目中,甚至可以开源出来供更多人所用,这样才能发挥它更大的价值,构建自己的影响力。
所以,对于这些类库、框架、功能组件的开发,我们不能闭门造车,要把它们当做 “产品” 来开发。这个产品是一个 “技术产品”,我们的目标用户是 “程序员”,解决他们的 “开发痛点”。我们要多换位思考,站在用户的角度上,来想他们到底想要什么样的功能。
对于一个技术产品来说,尽管 BUG 少、性能好等技术指标至关重要,但是否易用、易集成、易插拔、文档是否全面、是否容易上手等,这些产品素质也非常重要,甚至还能起到决定性作用。往往是这些很容易忽视、不被重视的东西,会决定一个技术产品能够在众多的同类中脱颖而出。
具体到 Google Guava,它是一个开发类库,目标用户是 Java 开发工程师,解决用户主要痛点是,相对于 JDK,提供更多的工具类,简化代码编写,比如,它提供了用来判断 null 值的 Preconditions
类;Spliter
、Joiner
、CharMatcher
字符串处理类;Multisets
、Multimaps
、Tables
等更丰富的 Collections 类等等。
它的优势有这样几点:
Immutable Collections
要比 JDK 的 unmodifiableCollection
性能好;刚刚讲的是 “产品意识”,再来讲讲 “服务意识”。对于程序员来说,这点可能比 “产品意识” 更加欠缺。
相对于业务代码来说,开发这种被多处复用的通用代码,对代码质量的要求更高些,因为这些项目的影响面更大,一旦出现 bug,会牵连很多系统或其他项目。特别是如果你要把项目开源,影响就更大了。所以,这类项目的代码质量一般都很好,开发这类项目对代码能力的锻炼也更大。这也是我经常推荐别人通过阅读著名开源项目、参与开源项目来提高技术的原因。
具体到 Google Guava,它是 Google 员工开发的,单元测试很完善,注释写的很规范,代码写的也很好,可以书说是学习 Google 开发经验的一手资料,建议如果你有时间的话,可以认真阅读一下它的代码。
尽管开发这些通用功能模块更加锻炼技术,但我们也不要重复造轮子,能复用的尽量复用。而且,在项目中,如果你想要把所有的通用功能都开发为独立的类库、框架、组件,这就有点大动干戈了,有可能会得不到领导的支持。毕竟从项目中奖这部分呢通用功能独立出来开发,比起作为项目的一部分开开发,会更加耗时。
所以,我建议初期先把这些通用的功能作为项目的一部分来开发。不过,在开发时,我们要做好模块化工作,将它们尽量跟其他模块划清接线,通过接口、扩展点等松耦合方式跟其他模块交互。等到时机成熟了,我们再将它从项目中剥离出来。因为之前模块化做的好,耦合度低,剥离出来的成本也就不会很高。
做业务开发也会涉及很多非业务功能的开发。要有善于发现、善于抽象的能力,并且具有扎实的设计、开发能力,能够发现这些非业务、可复用的功能点,并且从业务逻辑中将其解耦抽象出来,设计并开发成独立的功能模块,比如类库、框架、功能组件。
实际上,不管是类库、框架还是功能组件,这些通用功能模块最大的两个特点就是复用和业务无关。如果你开发的这块代码,跟业务无关且可能互被复用,那就可以考虑将它独立出来,开发成类库、框架、功能组件等。
当我们发现了通用功能模块的开发需求之后,如何将它设计开发成一个优秀的类库、框架、或功能组件呢?本章,我讲了一些更普适的开发思想,比如产品意识、服务意识、代码质量意识、不要重复造轮子等。
此外,特别建议你去阅读一下 Google Guava 的开源代码。它的代码不复杂,很容易读懂,不会有太大的阅读负担,但它是你获取 Google 公司开发经验的一手资料,特别是在单元测试、编码规范等方面。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。