用实战项目经验告诉你什么是二方包!
前言
只有光头才能变强。
文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y
最近在整合各种的系统,在这个过程中遇到了各种的问题,三歪今天来分享一下关于「项目结构」或者说「二方包」的事。
我们先不聊「二方包」,因为初学或者还没工作的同学可能没听过这个词。
初学的时候或者刚做项目的时候,我们的项目架构是怎么样的呢?我翻出了我在大学的时候写的小Demo:
可以看到的是,我们的项目只有一个Module
,里边我们分各种的包:dao/service/controller/utils...
等等。
这看起来好像没啥问题吧?
我们去到公司里边,可能看到的项目都分了多个Module
,比如下图:
有什么区别呢?我们用一个Module
在里边分各种的子包,看起来也还行。为什么我们要分多个Module
呢?
我个人认为原因是这样的:Maven本身就支持多模块(Module
)的管理,将不同的层分出来,项目看起来更加清晰,在改动的时候针对某个模块去变更就好了。
- 比如,我把dao层分成一个模块,当我变更dao这个模块的时候,我只需要关心这个模块就好了,不需要关心service模块或者web模块
- 举个例子:每层几乎都会有自己的配置信息(配置文件),数据访问层会有数据库的配置文件、业务层也会有对应的配置文件。我们抽出多个
Module
(不同的Module
放属于自己的配置文件),从代码结构层面上会显得更加清晰。
我们写完的代码是需要维护的,可维护性很重要。
很多编程方式客观上没有对错之分,一致性很重要,可读性很重要,团队沟通效率很重要。程序员天生需要团队协作,而协作的正能量要放在问题的有效沟通上。个性化应尽量表现在系统架构和算法效率的提升上,而不是在合作规范上进行纠缠不休的讨论、争论,最后没有结论。
二方包
当年我看《阿里巴巴开发手册》的时候也写过一篇总结,当时的文章也提到了那时候不咋懂二方包,现在我回来填坑了。
首先来科普一下什么是二方库?(二方库也叫·)
- 一方库指的是本项目中的依赖
- 二方库指的是公司内部其他项目提供的依赖
- 三方库指的是其他组织、公司等来自第三方的依赖
如果看过我之前文章的同学都知道,三歪在公司目前维护的是消息管理平台,全公司发送的消息都会经过我的系统。
我会打个「二方包」到公司的Maven仓库,然后他们引入我的pom
依赖,调用我的接口去下发消息。
假如我没有分Module
,所有的代码都写在同一个Module
下,那我发到公司的Maven仓库会发生什么?打包(deploy
)这个过程是没毛病的。
如果他们依赖了我这个没有处理过的二方包,相当于把我整个工程给依赖进去了,这是非常可怕的。
如果有从零搭过系统或者整合过系统的同学会知道,这个过程有会有多「版本」的坑。只要版本不一致,就会出现一大堆奇奇怪怪的问题,并且这些问题都不太好解决。
所以,一般我们的二方包都应该是很清爽的。比如我提供的二方包,它就只有接口和接口所需要的实体,没有杂余的繁琐依赖。
业务方是不关心接口的实现的,我们只需要暴露接口就好了。
三歪一次经历
最近三歪在整合系统嘛,分享一次经历。
我负责的消息管理平台系统的架构是这样的:
可以看到,我所负责的系统是分得很细的(很符合分布式的理念)。从功能上看,这些系统变成一个大工程也不是什么问题,只是这个系统会非常非常大。
消息管理平台除了上面的系统,还有其他的子系统,比如说「ID映射」。这里当初设计的时候也把它当做一个系统给抽出去了。
「ID映射」应该不难理解:业务方传入的是站内的userId
,但要发的是短信。我这边要把userId
转换成手机号
,可以简单理解这个系统就做的这么一个ID转换的功能。
现在要规划把这个「ID映射」给整合起来,原有的机器要下线了,要把这个服务的功能给整到消息管理平台的系统中。(为啥要整到我这个架构上?因为本身这个系统就只有我这边在频繁使用)
为啥要整合?现在的潮流可能是把单个系统拆出多个系统做”微服务“,但真正系统多起来未必是一件好事。
一些小的功能其实没必要单独分出来一个系统,这是需要成本的,至少我们机器成本是有的(一个系统我们至少会有四台机器)->两台线上,一台预发,一台线下
OK,说完背景了以后,我们再来看看「ID映射」这个系统的代码架构:
说白了,就是这个工程下有这三个Module
,如果你要问我为什么没看到dao
层的Module,而是直接放到core
层,问就是当初设计不合理。依我的理解,应该至少是要把数据访问层抽出一个Module。
可以看到的是,这个「ID映射」系统其实也是一个完整的系统,从后台管理页面到数据库都是完整的。
现在要把这个系统给整到消息管理平台的架构下,如果是你,你会怎么弄呢?
其实就两种方式:
- 把这个「ID映射」系统整个搬到某一个系统中
- 把这个「ID映射」系统通过模块拆出来,分到各个系统中。
最简单的做法肯定是把这个系统的代码搬到另一个系统,然后就可以run
起来了。但前人已经把系统分得那么干净了,如果我这样干了,后面接手的人会不会锤我呢?
三歪认为服务相关的代码,应该就整合到专门提供服务的系统。后台相关的代码,就应该整合到后台相关的系统。即便我后台系统发布了,丝毫不影响对外提供的服务。
所以,我决定把「ID映射」的各个Module抽出来,分到不同的系统中。把api
层和部分core
层的代码的Module分到service
系统中,把web
层的Module分到admin
系统中。
看似是挺完美的,我当初也是这样执行的,于是我顺利把api
和core
的代码整合到service
系统之后,正打算把web
的代码整合到admin
系统中,遇到了一个问题。
web
的代码是controller
层,它显然会依赖service
层的代码,service
层的代码也显然会依赖dao
的代码。
现在我已经把api/core
层的代码大多数已经迁到了service
系统,而admin
系统是没有这些代码和依赖的,我需要整个系统是能跑通的,我能怎么办?
此时能想到的有两种方案:
把
service
系统的代码再到admin
系统中实现。现在
service
系统已经实现好了,打个二方包,然后让admin
系统依赖。这里也有两个方案:- 二方包不做任何处理,
admin
系统直接依赖其所有的实现。 - 把
admin
系统所依赖的接口再出一个api
层,admin
系统只需要依赖api
层,实现远程调用
- 二方包不做任何处理,
如果是你,你会选择哪种?我们来分析一下:
- 第一种方案:
service
系统的代码再到admin
系统实现,这肯定会有代码冗余的情况。毕竟service
系统肯定会依赖dao
层的,而admin
系统最终也是需要依赖dao
层。dao
层没有完全抽出,在前期就肯定会有代码冗余的情况 - 第二种方案分支①:将
service
系统已实现的代码直接打成二方包,admin
系统直接引入就没有任何代码冗余的问题。但这会引发其他问题:- 直接打成二方包意味着要把所有的实现依赖都打进去,
admin
系统在引入的时候需要针对这个二方包做一系列的排包操作。(这个非常蛋疼) - 其实最致命的是我们干不了。我们的系统在发布的时候是分环境的(线上、预发、线下),我们会在发布的时候根据不同的环境使用不同的配置。如果我们此时直接打个二方包,我们是需要指定环境的,这说明我们只能用一个环境的配置,这是行不通的。
- 直接打成二方包意味着要把所有的实现依赖都打进去,
- 第二种方案分支②:把
admin
系统所依赖的接口再出一个api
层,实现远程调用。从字面上,这是最优雅的方案,但如果admin
系统依赖的接口众多的时候,实际践行的时候会发现这工作量巨大。admin
系统所依赖的接口有40+个,这些接口所依赖的实体有80+个。我搞了大半天,发现完全搞不动,工作量巨大!!这是单纯的体力活
第二个方案的分支①三歪再来聊聊为什么说干不了,首先我们的实现是有配置的
我们在deploy
的时候就必须指定一个环境,比如我们默认选择线上环境的配置好了。打完包以后,这个包默认的环境就是给线上使用的。但是admin
系统他还需要在线下环境启动,怎么办?没办法吧?
假设环境配置的问题能解决,等着我们还有各种依赖的问题。admin
系统和二方包的依赖冲突了怎么办?
比如说:相同的配置项,不同的配置信息。在service
系统上能兼容(毕竟代码都在同一个工程下),但直接打成二方包就没法跟admin
系统兼容了。
这只能删除冲突的部分,然后再发包了吧?但冲突是admin
系统冲突的,跟我service
系统的有啥关系呢?这我要做成一个完美兼容admin
和service
系统的Module
吗?老实说,不太现实。
扯了一大堆,三歪最终选择的是第一个方案。
在初期现在dao
层的代码肯定是在admin
和service
系统上冗余的。service
层不好抽取,但dao
层还是相对好抽取的啊。
为什么dao
和service
层的代码不一样?明明我在上面已经讲了怎么多直接抽取二方包的不可行性了。
dao
层的代码相较于service
层的代码要简单多了,一个合格dao
层应该是只管访问数据库,不应该有dao
层的代码去调service
层的代码的。
代码的简单意味着依赖会很少,比如我们的dao
层就应该只有Mybatis和Spring
相关的依赖,其余的就不应该有。而前面提到的环境配置的问题,我们可以交给业务方去实现,不在dao
层上做任何配置信息,开个hook
给业务方去做。
像三歪这种”微服务“系统,本应该要把dao
层给抽出来。再回看我的系统架构图,可以发现会有几个系统都需要依赖dao
,如果没有抽出来,这必会冗余,冗余的代码意味着不好维护。
规范
之前看不懂的阿里巴巴开发手册,现在能看懂了。我建议有空的时候还是可以看看的,都说得挺有道理的。
阿里大佬们踩了一堆坑,然后总结出来的规范。
【强制】二方库的新增或升级,保持除功能点之外的其它 jar 包仲裁结果不变。如果有改变,
必须明确评估和验证,建议进行 dependency:resolve 前后信息比对,如果仲裁结果完全不一
致,那么通过 dependency:tree 命令,找出差异点,进行
<excludes>
排除 jar 包。
【参考】为避免应用二方库的依赖冲突问题,二方库发布者应当遵循以下原则:
1)精简可控原则。移除一切不必要的 API 和依赖,只包含 Service API、必要的领域模型对
象、Utils 类、常量、枚举等。如果依赖其它二方库,尽量是 provided 引入,让二方库使用
者去依赖具体版本号;无 log 具体实现,只依赖日志框架。
2)稳定可追溯原则。每个版本的变化应该被记录,二方库由谁维护,源码在哪里,都需要能
方便查到。除非用户主动升级版本,否则公共二方库的行为不应该发生变化。
…
三歪瞎扯
为什么我们会用多模块(Module
)?其实就是让我们的项目代码变得更加清晰,像对外服务的api
层就必须要抽出一个精简的Module
给别人使用。
不知道你们如果能看完这篇文章能不能有所启发,反正我已经写完了。如果你们感兴趣的话,等我整合完这些系统我再来写一篇关于这段时间的感受。
我是三歪,一个要成为光头强的男人,下期见。给三歪点个赞,对三歪真的非常重要!**
用实战项目经验告诉你什么是二方包!相关推荐
- 赠书|大牛BTA大厂实战项目经验分享,真会玩!
如今,全球早已步入数据时代,随着行业的高速发展,相关岗位缺口已超150万,且薪资超同行业50%.未来十年,数据细分岗位将扩张5倍,各行业数据人才缺口明显. 很多人想抓住机遇进入数据分析行业,却经常遇到 ...
- 什么是互联网大厂_仅限今天!大厂最热数据分析经典实战项目大公开!
原标题:仅限今天!大厂最热数据分析经典实战项目大公开! 如今,全球早已步入数据时代,随着行业的高速发展,相关岗位缺口已超150万,且薪资超同行业50%.未来十年,数据细分岗位将扩张5倍,各行业数据人才 ...
- 真相!没项目经验高薪就无望?
福利!廖雪峰最新研磨的实战宝典<如何将大数据开发做到优秀>首次开放了,内容出自开课吧 vip 课程"大数据高级开发实战班",为帮助大家特殊时期职场走得更加顺畅,现决定将 ...
- B站 ‘顶流‘ 实战项目,yyds
哈喽,大家好,我是朋哥,一个资深的软件开发工程师,致力于:Java核心技术(SpringBoot,SpringCloud,算法,数据库,热衷高性能,高并发,分布式技术的研究),专注前沿技术开发,非常硬 ...
- Vue3+node.js网易云音乐实战项目(五)
推荐歌单详细页面顶部 1.推荐歌单详细页面 1.1.导航条和背景 1.2.头像和简介 1.3.头部完整代码 1.4.链接 实现效果 1.推荐歌单详细页面 1.1.导航条和背景 推荐歌单页面做好后,我们 ...
- vue+websocket+express+mongodb实战项目(实时聊天)(一)
##vue+websocket+express+mongodb实战项目(实时聊天)(一) 在原来基础上增加了多个聊天室以及发送图片[vue+websocket+express+mongodb实战项目( ...
- Vue3+node.js网易云音乐实战项目(三)
页面 一.头部导航栏布局 二.轮播图的实现 三.请求网易的banner图 四 链接 一.头部导航栏布局 首先我们看最上面这里的布局,大致可分为三个模块,顶部左边,顶部中间,顶部右边 那么我们在comp ...
- Java 高并发_JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过!...
JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过! 1.JPG (37.82 KB, 下载次数: 0) 2018-12-3 09:40 上传 2.JPG (28 ...
- dt测试软件的学习心得,无线网络优化dt测试心得_适合新手入门,高手进阶_5年项目经验实战经验.docx...
无线网络优化DT测试心得_适合新手入门,高手进阶_5年项目经验实战经验 无线网络优化DT测试心得_适合新手入门,高手进阶_5年项目经验实战经验 路测中不常见的问题和个人心得 1.深井子镇投诉测试报告 ...
最新文章
- 名校 Stanford
- MySQL-索引优化篇(4)_索引的维护
- oracle分区表相关
- 孟岩谈Erlang:并行计算和云计算
- andriod studio 查看项目依赖_Intellij IDEA 中如何查看maven项目中所有jar包的依赖关系图...
- 经理人如何与这“六种人”打交道?
- 19-6/28作业:100以内偶数求和
- vue控制台报错Duplicate keys detected: 'xxxx'. This may cause an update error.解决方案
- [渝粤教育] 广东-国家-开放大学 21秋期末考试互联网金融10139k2
- 在linux中配置编译u-boot方法,U-Boot编译过程解析
- 烟雾传感器的matlab程序,单片机烟雾传感器proteus仿真+程序+PCB原理图
- 数据库设计—图书管理数据库系统设计
- java怎么用unicode写程序_简单的讲解Java是使用Unicode字符集
- Mac book 合并分区,报错文件系统验证失败的解决办法
- 2008年IT行业10大热门职业调查结果出炉
- 解决在串口调试助手中每次复位后只能发送一次数据的问题
- 组建一个最简单的局域网
- Mask R-CNN 原理解析
- 使用scrapy再次爬取猫眼前100榜单电影!
- 宗镜录略讲——南怀瑾老师——系列9
热门文章
- 【Python爬虫_8】爬取必应图片
- GLES2.0中文API-glCompressedTexSubImage2D
- provider: SQL Network Interfaces , error: 26 - Error Locating Server / Instance
- 【已解决】阿里自动滑块 x5sec 解密 钉钉数据采集
- 京东抢购失败?试试用Python准时自动抢购!七夕秒抢种礼物!
- 沪市和深市股票托管方式的区别
- android友盟埋点,友盟数据埋点前,你要知道这些
- 组网胖模式_胖瘦AP组网优劣对比
- 请保持内心中最后一点良知
- 2020下半年中小学教资考试教育知识与能力试题(中学)——主观题