CategoryResourceRepost/极客时间专栏/设计模式之美/开源与项目实战:开源实战/81 | 开源实战三(上):借Google Guava学习发现和开发通用功能模块.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

88 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<audio id="audio" title="81 | 开源实战三借Google Guava学习发现和开发通用功能模块" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/92/01/9270563dc26c6f39b8143b03a7cdac01.mp3"></audio>
上几节课我们拿Unix这个超级大型开源软件的开发作为引子从代码设计编写和研发管理两个角度讲了如何应对大型复杂项目的开发。接下来我们再讲一下Google开源的Java开发库Google Guava。
Google Guava是一个非常成功、非常受欢迎的开源项目。它在GitHub上由近3.7万的stars。在Java项目开发中应用很广泛。当然我们并不会讲解其中的每个类、接口如何使用而是重点讲解其背后蕴含的设计思想、使用的设计模式。内容比较多我分三节课来讲解。
- 第一节课我们对Google Guava做一个简单介绍并借此讲一下如何开发一个通用的功能模块。
- 第二节课我们讲Google Guava中用到的几种设计模式会补充讲解之前没有讲到的Immutable模式。
- 第三节课我们借Google Guava补充讲解三大编程范式中的最后一个函数式编程。
话不多说,让我们正式开始今天的学习吧!
## Google Guava介绍
考虑到你可能不熟悉Google Guava我先对它做下简单的介绍。
Google Guava是Google公司内部Java开发工具库的开源版本。Google内部的很多Java项目都在使用它。它提供了一些JDK没有提供的功能以及对JDK已有功能的增强功能。其中就包括集合Collections、缓存Caching、原生类型支持Primitives Support、并发库Concurrency Libraries、通用注解Common Annotation、字符串处理Strings Processing、数学计算Math、I/O、事件总线EventBus等等。
我截取了Google Guava的包结构图贴到了这里你看起来更加直观些。
<img src="https://static001.geekbang.org/resource/image/1c/45/1ce23ffd03045dadf2bad7e126337045.png" alt="">
我们知道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消息中间件、监控系统、分布式调用链追踪系统等。
## 如何开发通用的功能模块?
当我们发现了通用功能模块的开发需求之后如何将它设计开发成一个优秀的类库、框架或功能组件呢今天我们不讲具体的开发技巧具体的开发技巧在后面Spring开源实战那部分我们会讲到一些我今天打算先讲一些更普适的开发思想。我觉得先有了这些你应该更容易理解后面的内容。
作为通用的类库、框架、功能组件,我们希望开发出来之后,不仅仅是自己项目使用,还能用在其他团队的项目中,甚至可以开源出来供更多人所用,这样才能发挥它更大的价值,构建自己的影响力。
所以,对于这些类库、框架、功能组件的开发,我们不能闭门造车,要把它们当作“产品”来开发。这个产品是一个“技术产品”,我们的目标用户是“程序员”,解决的是他们的“开发痛点”。我们要多换位思考,站在用户的角度上,来想他们到底想要什么样的功能。
对于一个技术产品来说尽管Bug少、性能好等技术指标至关重要但是否易用、易集成、易插拔、文档是否全面、是否容易上手等这些产品素质也非常重要甚至还能起到决定性作用。往往就是这些很容易忽视、不被重视的东西会决定一个技术产品是否能在众多的同类中脱颖而出。
具体到Google Guava它是一个开发类库目标用户是Java开发工程师解决用户主要痛点是相对于JDK提供更多的工具类简化代码编写比如它提供了用来判断null值的Preconditions类Splitter、Joiner、CharMatcher字符串处理类Multisets、Multimaps、Tables等更丰富的Collections类等等。
它的优势有这样几点第一由Google管理、长期维护经过充分的单元测试代码质量有保证第二可靠、性能好、高度优化比如Google Guava提供的Immutable Collections要比JDK的unmodifiableCollection性能好第三全面、完善的文档容易上手学习成本低你可以去看下它的Github Wiki。
刚刚讲的是“产品意识”,我们再来讲讲“服务意识”。我经常在团队中说,如果你开发的东西是提供给其他团队用的,你一定要有“服务意识”。对于程序员来说,这点可能比“产品意识”更加欠缺。
首先,从心态上,别的团队使用我们开发出来的技术产品,我们要学会感谢。这点很重要。心态不同了,做起事来就会有微妙的不同。其次,除了写代码,我们还要有抽出大量时间答疑、充当客服角色的心理准备。有了这个心理准备,别的团队的人在问你问题的时候,你也就不会很烦了。
相对于业务代码来说开发这种被多处复用的通用代码对代码质量的要求更高些因为这些项目的影响面更大一旦出现bug会牵连很多系统或其他项目。特别是如果你要把项目开源影响就更大了。所以这类项目的代码质量一般都很好开发这类项目对代码能力的锻炼更有大。这也是我经常推荐别人通过阅读著名开源项目代码、参与开源项目来提高技术的原因。
具体到Google Guava它是Google员工开发的单元测试很完善注释写得很规范代码写得也很好可以说是学习Google开发经验的一手资料建议你如果有时间的话可以认真阅读一下它的代码。
尽管开发这些通用功能模块更加锻炼技术,但我们也不要重复造轮子,能复用的尽量复用。而且,在项目中,如果你想把所有的通用功能都开发为独立的类库、框架、功能组件,这就有点大动干戈了,有可能会得不到领导的支持。毕竟从项目中将这部分通用功能独立出来开发,比起作为项目的一部分来开发,会更加耗时。
所以,权衡一下的话,我建议初期先把这些通用的功能作为项目的一部分来开发。不过,在开发的时候,我们做好模块化工作,将它们尽量跟其他模块划清界限,通过接口、扩展点等松耦合的方式跟其他模式交互。等到时机成熟了,我们再将它从项目中剥离出来。因为之前模块化做的好,耦合程度低,剥离出来的成本也就不会很高。
## 重点回顾
好了,今天的内容到此就讲完了。我们一块来总结回顾一下,你需要重点掌握的内容。
做业务开发也会涉及很多非业务功能的开发。我们要有善于发现、善于抽象的能力,并且具有扎实的设计、开发能力,能够发现这些非业务的、可复用的功能点,并且从业务逻辑中将其解耦抽象出来,设计并开发成独立的功能模块,比如类库、框架、功能组件。
实际上,不管是类库、框架还是功能组件,这些通用功能模块最大的两个特点就是复用和业务无关。如果你开发的这块代码,业务无关并且可能会被复用,那就可以考虑将它独立出来,开发成类库、框架、功能组件等。
当我们发现了通用功能模块的开发需求之后,如何将它设计开发成一个优秀的类库、框架或功能组件呢?这里我们讲了一些更普适的开发思想,比如产品意识、服务意识、代码质量意识、不要重复造轮子等。
除此之外我特别建议你去阅读一下Google Guava的开源代码。它的代码不复杂很容易读懂不会有太大阅读负担但它是你获取Google公司开发经验的一手资料特别是在单元测试、编码规范方面。
## 课堂讨论
针对你正在参与开发的项目,思考一下,有哪些通用的功能模块可以抽象出来,设计开发成独立的类库、框架、功能组件?它们都可能会包括哪些功能点呢?试着自己设计一下吧!
欢迎留言和我分享你的想法,如果有收获,也欢迎你把这篇文章分享给你的朋友。