IDEA开发java web项目:在多个git仓库,多个模块下,IDEA build,debug以及maven package等各种问题

背景

我们最近在开发一个Java web项目,当时的设计基本是这样:将各个基础档案或者其它应用按照模块划分,基本上是一个档案对应一个git仓库(也有一个git下面有多个maven模块,这样的也有),按照职责划分开,希望将来能够按照微服务进行拆分(每个模块都会有api,domain,web层),但是暂时并不会这样做,也没有用springboot,常规的war包项目。而且设计上会有一个启动器,由一个启动器来控制要依赖哪些模块并且把它们启动,不同的启动器所包含的内容会不一样,但它们之间也会有共同使用的一些模块。

最后创建了大约有十余个git仓库,也有十个左右的开发,然后基本上每个开发会参与其中的一些(大于等于二,一个启动器+几个模块)。使用IDEA开发,基本上会在同一个工作空间(这个我指的是一个IDEA窗口)里面会导入多个git项目,通过maven视图的添加按钮添加进来的,这样开发的话,就会使用到本地最新的代码去编译测试,测试完了以后是需要deploy到远程仓库,供其他人和构建测试环境使用。

基本问题

我刚开始并没有参与设计和开发,最近加入了,不过我先是梳理十几个Git仓库之间的关系,因此把所有的代码拉取下来并加入到IDEA的一个工作空间内(注意有的项目代码,是我很久之前已经拉下来了),之后我在启动项目的过程当中碰见了两个问题:

假设有3个工程吧,A是启动工程,A依赖了B和C。

问题1: 本地启动,报错;发在群里面问一下,这是谁负责的,应该怎么处理。有人告诉我应该去拉取一下项目B的代码,然后build一下,再启动。我试了一下,果然好了。
关于这个问题,我当时就非常郁闷,我启动的时候,为什么要用本地工作空间的代码编译启动?为什么没有用maven仓库的。而且在之间群里面,隐约记得,有好几次有这种问题,解决方案都是如此。
我在意的有两点:

  1. 我并不关心项目B,我也没有修改它,因此我不需要也不应该操作它。我启动工程就不应该去拉取B的代码,我用最新的仓库里面的就行了呀。
  2. 默认启动的话,为什么用的是工作空间的,而不是仓库的。

我抛出了这样的问题,并且想去查看一下为什么。当然得到了一个比较错误的结论,是因为对方导入idea的方式有问题,并且让对方按照我的来。在这个过程里面,而且我用maven package的时候,发现打出来的依赖包,居然不是最新的,是因为对方并没有deploy。基于这两点,我以为回答了上面的这两个问题。

后来,我又碰到了一个问题,让我知道了我理解的有问题,并且这个问题很重要,必须要彻底搞清楚。
问题2: 我后面启动的时候,报错,一个类找不到,是C工程里面,我下意识的进行了一系列操作:拉代码,build,启动,错误仍然还在。最新的代码里面,有那个类,没有问题。然后我又查看了A工程target目录中的c.jar,发现里面确实没有。我又进一步查看了本地和远程maven仓库,发现都没有问题。那么问题来了,这个错误的c.jar到底是从哪里来的?一定要找到问题,一顿操作,发现是在c工程目录下的target/classes下面,并没有那个类的class文件。
哇哦,原来如此。说明IDEA在启动A的时候,处理C依赖的时候,用了C工程target目录下的相关文件用于打包,而且它并没有用C的源码去编译,当然也就没有使用maven仓库里面的了。
那显然我自己的导入方式也是不正确的,因此就展开了一系列的研究,我觉得非常有必要去搞清楚这个问题,肯定可以提高开发效率。

明确目标

我为什么要去研究这个呢?我希望是这样一种场景:十几个人开发同一个项目,分为好多模块,各自负责各自的就行,但是负责的模块里面肯定也会有交集,当别人正确的修改完模块B的代码以后,发布到远程仓库里面,其它人启动的时候,都应该直接用远程仓库的(尽管自己本地也有这个模块),这样就不会有任何问题(排除他本身提交的错误的情况),同时我们自己在做开发的时候,本地测试的时候,编译使用的应该就是本地的,并且在测试完成后,发布的仓库中以后,它本身也可以用仓库中的进行测试,保证仓库中那个的也是没有问题的,这样别人甚至搭建的环境中的是没有问题的。当然,这些都建立在所有开发都遵循我们的开发规范,这样也就可以节省很多不必要的时间了。而且在整个过程当中,所有的项目都是在同一个工作空间的,我不需要对它们进行移除和添加操作。
刚才说的是做这件事情的原因,那如何来实现这件事情呢?基本上当时是有如下的目标:

  1. IDEA在debug或者run的时候,会先build,或者build也可以单独执行,那么这个build到底是如何来区分用工作空间中的还是仓库?到底是在哪里配置的,我们能不能手动修改,然后自己来控制?虽然我当时见到的全是使用工作空间的,但很明显有一个现象,我把工程B移除了工作空间,它就会使用仓库的,我想那肯定是有配置的。
  2. 在IDEA中的maven仓库中的clean,compile以及package等命令,与IDEA的build命令到底有什么关系?或者它们分别做了什么事情?

这是两个比较大的目标,但是在实际过程执行的时候,其实也帮助我弄清楚了一些其它小问题,比如maven仓库中关于快照版本的处理方式,build的时候,有时候会构建,有时候不构建,它到底是怎么判断的?package结束了,直接build的时候,有时候没有任何变化,但有的时候就会有变化,这是为什么?如果当不变化的时候,意味着你用的代码是最新的仓库里面的,并不是你本地的,但是你可能不知道。而且还发现了IDEA的关于Build的源码在哪里,处理jar或者resources的是哪个类,当然没有仔细看,还不至于到那一步。

有时候会觉得整个过程特别玄幻,基本上就是大量的测试,采用控制变量法,不断的去观察记录现象,好不容易得出一个结论,过一会儿现象就会推翻之前的结论,然后一度怀疑人生~

关于maven的快照版本:SNAPSHOT

这个我简单说一下,详细的可以去查询资料。
快照版本的出现就是用来解决在开发态会不定期高频率更新代码的场景的。
使用的发行版本的话,只要本地有,就不会去远程仓库拉,除非把本地的删除。加参数-U也没用。
想要拉取最新代码,就必须更新版本,其实就是升级版本,1.0.0升级到1.0.1。对于开发者和使用者都一样。
那么快照版本的话,就允许在同一个版本下,提交无数次快照版本,并且快照版本和发布版本会放在maven仓库的不同地方,区别处理,只要不带SNAPSHOT的都是发行版本。
快照版本它会以时间戳+提交次数命名。因此当我们依赖快照版本的时候,打出来的依赖Jar包一般都是带时间戳的,当然肯定可以处理一下,比如按照如下配置一下插件:

<plugin>
	<artifactId>maven-war-plugin</artifactId>
	<version>2.6</version>
	<configuration>
		<outputFileNameMapping>@{artifactId}@-@{baseVersion}@.@{extension}@</outputFileNameMapping>
	</configuration>
</plugin>

那不配置上面的插件,行不行呢?我只能说,可能行,因为在开发态的时候,一定会影响使用;但是仅仅用maven打包的话,可能是不会有影响的。

为什么要去研究这个呢?我当时发现了一个问题:最后打出来的文件,WEB-INFO/lib目录下的jar包,所有快照版本的jar包,都出现了两次,一个正常的,一个带时间戳的。并且这两个jar包是不一样的,这个我指的是jar包的内容,包含的文件都会有所区别,jar包大小也不一样。假如说其中一个是旧的,并且在使用的时候,类加载器加载到了旧的类,那显示问题就出现了,我就是碰见了这个问题。

为了查看这两个jar包怎么来的,也是费了不少的事情,前面一直重现不了,重现的时候,得出的结论又被推翻了,我就直接说一下结论吧。
带时间戳的是maven进行package命令的时候产生的;
正常的是IDEA在Build的时候产生的;
上面那个插件处理也是maven的插件,当配置完了以后,两者所产生的jar包就会重复了,如果我们在开发的时候,反复package以及build,那么很幸运的是,它们可能会反复地进行替换,你一定都不知道现在用的是哪个工具打出来的包。为什么是可能呢?关键在于build的执行原则是:仅build变化的,当没有变化的时候,它什么都不干。关于怎么来区分变化,这是个重点,后面详细说一下吧。

快照版本的出现就是为了为了方便快捷地在开发阶段不更新pom文件的情况下更新最新的依赖。因此它也会有一个更新策略,叫做updatePolicy,用来配置maven从远程仓库检查更新的频率,默认的值为daily,表示每天检查一次,这个在maven的setting文件里面:

<snapshots>
	<enabled>true</enabled>
	<updatePolicy>always</updatePolicy>
</snapshots>

上面配置的是always,代表的就是每次都强制更新。
或者在执行maven命令的时候,加上-U,代表这次执行也是强制更新。
或者在IDEA里面也可以配置,当然,肯定是推荐这个了,如下图:
在这里插入图片描述
把这个勾上就行了,然后在IDEA中使用maven的功能就行了。我还稍微研究了一下,加上这个到底有什么影响,其实就是加了一个参数:

--update-snapshots 

虽然不是-U,因为在执行maven命令的时候并不是直接执行的,而且执行了IDEA中的某个类,由那个类去间接执行的,怎么看的呢?当你执行命令的时候,控制台会打一行日志:
在这里插入图片描述
看这个图还是比较明确的。关于快照的时候就到这边吧。

在IDEA中执行maven命令

直接说结论吧,在IDEA中执行maven命令:
在这里插入图片描述
就是上述命令,和在命令行里面执行maven命令,效果是完全一致是:

mvn -U clean compile package -P test

这一点非常肯定。
而且在IDEA里面执行package的时候,依赖打包的时候一定用的是仓库的,它一定不会用工作空间里面。这一点按照正常逻辑也可以想明白:IDEA里面执行maven===在命令行执行maven,那么对于maven而已,它根本不知道有IDEA的工作空间这回事。
package用的是仓库的,build不一定用,所以可能会冲突。

maven的离线工作模式(work offline)

这个东西,和我整体描述的没有太大关系,只不过顺便研究了一下,我曾以为它对我的研究有所干扰,后来发现完全没有。但是这个在我们工作当中,也会有一些作用。
开启离线模式的话,我们在用maven命令打包的时候,用的都是本地仓库中,它不会去拉取远程仓库中最新的。
啥时候可以用呢?就是,我们仅仅想打个包,不想去拉远程仓库的最新包,而且比较明确的是,本地仓库的就是最新的,毕竟拉取远程仓库的是比较慢的。
在IDEA里面有两种切换离线模式的方式:
在这里插入图片描述
在这里插入图片描述

IDEA在build的时候,到底选择的是工作空间还是仓库的?

终于到重点了,怎么发现的,过程就不多说了,重点还是说一下结论吧。

artifacts文件的发现与查看

IDEA在build的时候,它是根据artifacts进行构建的。artifacts里面定义了各种要构建的目标目标和目标文件,非常详细,它会按照其中的每一个条目去执行。
(至于artifacts这个概念以及更加详细的作用,可以在网上自行查询,我这边只讲解其中一部分)
artifacts文件在我们增加一个Tomcat Server类型的Run/Debug Configurations的时候,会自动创建。
它就是项目中目录下“./idea/artifacts/project_A_war_exploded.xml”,就是这个xml文件,大家可以自行去查看和打开这个文件。
在这里插入图片描述
在这个xml里面,重点看一下关于依赖jar的不同展现形式吧:

<element id="library" level="project" name="Maven: com.alibaba:fastjson:1.2.17" />

id=library的,这种指的是依赖的仓库中的,并且是发行(RELEASE)版本。

<element id="file-copy" path="$MAVEN_REPOSITORY$/com/test/project-b/1.0.0-SNAPSHOT/project-b-1.0.0-20200104.063052-16.jar" output-file-name="project-b-1.0.0-SNAPSHOT.jar" />

id=file-copy的,这种指的是依赖的仓库中的,但是这个特指的快照版本,也能够看到它本身依赖的是本地仓库中的某个具体快照版本,具体上可以断定build的时候就会直接拷贝过来,就是一种绑定关系,这个也会在build的时候判断更新的时候也会用到。

<element id="archive" name="project-b-1.0.0-SNAPSHOT.jar">
 	<element id="module-output" name="project-b" />
</element>

id=archive的,它在这边基本上是代表输出一个jar包,在里面的元素就是意味着这个jar包里面有哪些内容了。比如上面这种的,id=module-output的,意思也很明确,就是用name这个模块的输出。这种的配置就是用的工作空间中的代码。

对于这3中情况,它也对应了3中不同依赖的jar包的生成方式。
file-copy和library,基本上就是从本地仓库直接拷贝过去的。
archive会用模块的输出,也就是target下面的classess目录下的文件去打包生成jar包。

当我发现这些的时候,我感觉已经成功了一大半了,找到了。那就是archive与file-copy的区别了。
当然这些也都是自动生成的,我也研究了一下IDEA是如何更新这些文件的。比如我把B工程从工作空间移除:
在这里插入图片描述
移除以后,它会自己刷新一下,但它并没有修改artifacts文件,当时为这个事情,头疼了好久,我在不断反复添加和移除,发现有的时候会修改,有的时候没有修改,难受死了。
当你移除或者添加以后,可以再点击一下,Reimport按钮
在这里插入图片描述
然后它就会自动对archive和file-copy进行更新了。
研究这个文件更新,花费了不少心血,也研究了一下ignore某个工程的作用,它不会修改文件,但是用可视化工具打开的时候,会有红字错误提示,但build也会成功,只不过会少一个jar包。笑哭脸。

artifacts文件的手动更改

知道了几种元素的区别,那你就可以手动修改了。可以直接修改文件。
也有一种方式,它本身也提供了可视化工具。
File-Project Structure:Artifacts
点击exploded,右侧就会可视化那个xml,
在这里插入图片描述
注意在右侧可以在lib下面找出那3种不同的展现形式,同时也可以右击对元素进行增删改。
如果要添加工作空间的模块输出的话,注意先添加一个archive,名字起成jar包的名称,然后里面加一个module output就行了。
如果要添加file-copy的,选择file,会打开文件浏览器,就直接选择到本地仓库中的一个具体的jar包,把它们关联起来。
在这里插入图片描述

它能做什么呢?

回到我遇到的问题,显然就是,当我把所有工程添加进来的时候,它build的时候,用的就是工作空间的,这个时候,我可能不想用工作空间的,因为需要我一直拉最新的代码。那么我就想用仓库的,那么我把它由module-output改成file-copy就行了。

它的价值到底有多大?

本来我觉得这个价值非常大,但是不幸的是,我刚才说了reimport的时候IDEA会修改artifacts文件,而且我也做了一下测试,我把module-output修改成file-copy,直接去reimport,不去移除项目或者添加的,尴尬的是,它居然给改回去了,又成了module-output。而且重点是,reimport是一个高频操作。这就很无语了。
如果在这种情况下,还要坚持按照我上面说的做的话,那么比较好的方式就是改完以后,把相关的内容复制保存下来,你记得在reimport以后,手动修改一下,然后就可以了。可问题是,这样麻烦不?还是有点儿麻烦呀。
但是如果是相对于,你启动报错,问别人,别人看看,告诉你应该怎么做,这种情况来说,还是非常值得的。而且我也碰见了就算你拉代码,就不一定可以解决的场景,下面会重点说一下。

那还有没有其它的办法呢?来控制到底使用哪里的代码呢?仔细研究了build的更新策略以后,我觉得是可以通过一系列严格顺序的操作来完成的。不需要手动修改artifacts文件的。后面说一下。

build的时候,到底是怎么判断,哪些文件是需要或者不需要build的。

上面讲的所有的内容,基本上才解决了我的第一个问题,我不想通过拉取本部应该我拉取的代码来解决这个问题。还有其它问题,build的更新策略是怎么样的,build与package等命令的关系与区别。

build与package等maven命令

说实话,build是IDEA的,package是maven的,它们之间没有任何直接关系。、
要非说间接关系的话,那还真有一点

  1. maven的clean以及compile命令,可能会在build的更新策略造成一定的影响。
  2. 它们之间会有相同的输出产物,因此会存在一种覆盖关系,这么说吧,package一定会覆盖build的产物,而build不一定。

关于这两点,接下来通过build的更新策略解释一下可能会比较合适。

build的更新策略

关于build的策略,一句话很简单:仅build更新的那部分。
但是太抽象了,一点都不具体,也没法在实际工作中产生巨大价值;最起码要解决我们可能会遇到的一个问题,先build,再package,再build,第二次build的时候,发现没有更新,所以不会有任何变化。因此打出来的包,是仓库里面的,并不是我们本地生成的,但我们可能会以为是我们本地的。
更新策略的话,我这边直接上结论了,我也测试过,如果有其他看法,可以讨论验证一下。先看一张简图:
在这里插入图片描述
我们在Build的时候,会在WEB-INF下面生成classes目录和lib目录,一般也会重点关注一下这两个。
在classes下面一把分为类文件和资源文件,针对资源文件,先不探讨了,后面有机会再说。
对于class文件的话,它对应的就是这个工程src/man/java目录下的文件了,它的更新策略就是判断原始java文件有没有更新过。
lib目录下都是依赖的jar包,但是我们也可以分为两种,依赖本地模块和仓库的,前者可以认为是我们自己也一直开发的,后者完全就是别人的。对于我们自己开发的,也会分为两种,一种是本地模块输出,一种是本地仓库拷贝。
那么基本上就是3种情况,对于在仓库中的,那就是判断仓库中的jar包有没有更新了,这是比较简单了。
关键在于本地模块输出的,比如依赖了B,它判断要不要更新的依据就是,B/target目录下的classes中的class文件有没有被更新。它应该会记录上一次build的时候,target下面的文件状态。这个结果和它的描述也是有点儿联系的,这种的在artifacts文件中称之为:module-output,模块输出,那不就是模块中的target吗?而且我也反复测试过,修改过java类,修改过class文件等等。
基本上当target(或者classes)整个目录不存在的话,它会

A依赖的是B的target,那B的target呢,当然是B的源码了。
但是buildA的时候,并不会buildB(在B的target目录存在的时候),所以我们可能需要单独buildB了。

了解了build的更新策略,带给我们的价值是什么?

知道了上述以后,可以解释得通,我碰见的第二个问题了。
所有能猜到的地方,都是最新的代码,但是Build出来的包就是旧的。就是因为target下面缺了一个类文件,而且我没有更新过它。
如果我选择使用仓库中的,那就不会有这个问题了。按照上面讲的去修改artifacts文件了。
但是肯定会有更多的场景是需要使用本地模块的文件的,那么基于上面得出的结论,我们要怎么做呢。
那就是持续更新某个工程的target目录,也就是需要clean以及compile,或者直接clean掉就行了,build的时候会自动compile。
但是如果说我们使用IDEA开发的时候,修改完java,不是基本上就会自动编译了嘛,那上面岂不是就白说了。这种情况下,还真的是。
那基本上就是针对在非IDEA环境下拉取代码的时候,如果想用本地的话,就去clean一下。或者针对那个工程build一下。
实在是不想费这个劲去思考到底怎么更新的话,可以选择rebuild,这个操作是强制Build,先clean然后build。而且rebuild A的时候,也会把B顺便rebuild了,是不是很强大的功能,但是缺点也很明显,费时间啊。肯定不会每次都这样做的。

利用build的更新策略,来控制启动的时候用的jar包到底是工作空间的代码产生的,还是仓库的。

明确一点,我们使用IDEA启动工程,一定会build。
还是A依赖B,就讨论B。
下面的讨论,建立在不修改artifacts文件的情况下。修改的话,就会破坏默认的配置。
那么怎么确认我们用本地工作空间的代码呢?
永远不使用maven的package功能。每次启动仅Build,或者build之前clean一下B工程,保证可以拿到最新的本地工作空间的代码打出来的jar包。
那么怎么确认来使用仓库中的呢?
根据上面的所有讨论,有下面几个事实:

  1. maven的package功能一定会用仓库中的。
  2. 启动工程的时候,一定会用到build功能。
  3. 默认情况下,build功能会使用的工作空间中的代码进行打包。

既然要使用仓库的,那一定要用maven的package功能,而且之后的build不能覆盖package的结果。
默认的build功能,它仅编译,不打包,但是可以配置让它也打包:
在这里插入图片描述
勾选上就行了,做这个事情是为了每次只需要仅仅build就行了,而不用debug或者run去打包,然后再停下来。
关键的步骤来了,
对A工程进行build或者rebuild,仅仅对这个工程就行了,不需要对整个工作空间Build。
然后去package,仅仅package,不要clean。
然后直接启动,这样打出来的包,一定用的是仓库的。
第一次的build是为了第二次的build不去覆盖package的结果。

其实在开发过程中,更多的场景是一部分用本地的(比如B工程),其它的用仓库的(但是工作空间中也有)。也可以做。
还是按照上面的,先build,然后package,然后把B工程clean一下,然后启动A。这样A一定用的是你本地的。
我觉得这种操作方式不错。

实际的价值在哪里?

等写到这里的时候,我甚至有点儿怀疑了,它产生的价值到底大不大呢?我内心最直接的感觉是好像对各种操作更加了解了,但是总感觉缺了点什么,那就是非常明确直观的开发规范,能够直接对开发过程产生积极影响的做法,必须要输出。

关于开发过程的思考

从一刚开始我来研究这个问题,根本原因是我认为整个开发过程不顺畅,会做一些无用功,我应该去捋一捋顺一顺这件事情。因为在人很多,开发周期很长的情况,任何低效率无用的开发都会产生不小的负面作用,影响到开发进度。而且我还发现了开发过程中的其它问题,比如:
A依赖了B,C,D。而C依赖了D。
第一个人只关心,A,B,C。
第二个人只关心,A,B,D。
第二个人修改了B和D,测试通过后,提交了。第一个人拉取了代码,B报错了,问第二个人应该怎么办,说要把D添加进工作空间里面,就可以解决这个问题。第一个人也做了,好了。
可问题是,为什么要这样做呢?这不是搞笑呢嘛。当然这个事情和上面讨论的,没有关系。
开发规范的话,就是应该在项目初期订好,中间也可以增加,所有的开发都必须严格按照开发规范执行,对自己,对他人,对项目负责。
那我研究了上面这个东西,肯定也要输出一些正确的开发规范。

具体的开发规范

还是以我们这个项目为例,十几个git,每个人负责一些。
(这种场景和一个git下面,十几个模块的,不一样。一个git的会非常简单)

  1. 所有人开发测试完的代码,都必须及时提交,并且要及时deploy到maven的远程仓库(可以除过启动器,这个一定用的是本地的);你自己用的本地代码开发测试的,但是并不代表别人也用的本地的,或者说其它开发更希望用的是仓库里面的,因为它本身就不关心这个。而且我们构建的测试环境使用的一定是仓库里面的,否则可能经常会出现:本地没有问题,测试环境就出了问题。
  2. deploy结束以后,一定要使用拉取远程仓库里面的包,测试一下,保证远程仓库里面的没有问题。这个测试有两种层面,一种看一下只要是最新的就行,可以通过时间戳以及大小来判断,或者也可以真正跑起来,验证一下。
  3. 如果你自己的工作空间里面仅仅导入了你所负责的工程,那么在整个过程当中,不需要使用package功能,这样你每次启动就是使用的就是本地的,不会是远程仓库的。而其余的你不关心的,就会默认使用仓库里面的。
  4. 如果你打算使用工作空间里面,并且向保证每次使用最新的,可以在启动前,clean一下,注意,clean的是被依赖的那个,比如A依赖B,clean B,然后在启动。一定是最新的,防止意外情况出现。
  5. 上面的场景都比较简单,可能也不是常见的。常见的肯定就是下面这种的:你负责A,B,C,D,4个工程,A依赖于其它的,并且全部导入进来了,并且别人也会更新BCD。而且此时此刻你正在修改B,别人修改了B和C,B和C都提交和deploy了,但是你只更新了B,如果此时此刻,你用工作空间跑起来,显然,一定会出错,因为你并没有最新的C。这里面的错可能会分为两种,编译错误和运行错误,如果是编译错误,那么你可能是不是必须拉一下C的代码了?因为你关心的B都编译失败了。要是C没有在你的工作空间里面还好说,但是它在,确实挺尴尬的。关于编译错误的正确解决方案,后面在研究一下,看看会不会有更好的。关于运行态的问题,你只要保证C是远程仓库的,那就一定没有问题。具体从操作步骤的话,就是:build A,package A,clean B,debug A。这样B一定是本地的,其余的都是远程仓库的。
  6. 如果开发过程中, 你发现了一些错误,别人给你的解决方案,你认为是不正确的,不合理的,那就应该提出来,并且一起探讨出来合理的做法,如果仅仅抛出问题,不解决的话,那还不如不抛。共同来促进开发。这一点是开发的意识,比上面所有的步骤都重要。

由本地研究IDEA而引出的关于黑箱子的思考

黑箱子,对你而言,你给它输入,它就给你期待的输出,你也不关心它是怎么做的。黑箱子,生活中到处都是。
关于对工作中的黑箱子,我的态度都是比较明确的。
黑箱子是为了更好的辅助我的工作,在正常情况下,我不需要关心它是如何工作的,内部做了什么,只要它不对我的工作产生负面的影响。
所以分界线就是:对我的工作有没有产生负面影响。
那么一旦产生了影响,那我就需要去思考一些问题,是不是我的操作不对导致的,那么正确的操作是什么,这些操作下去,它到底做了什么,这些问题必须搞清楚,搞到什么程度呢?搞到你可以确信这里不会影响到你了就行。
一直研究这个,也找到了IDEA源码中具体的处理Build的相关类代码了,但是并没有进一步看,因为还没有到那一步,或许将来会去看。
或者这是不是工具本身的Bug,那这种情况下,是不是就要考虑用其它的方式或者换个黑盒子了?

但是各种的主流框架,不严格来说,它也算,它从输入输出的角度来讲,和工具都是一样的,你必须要会用它,在不影响你使用的情况下,你也可以不去研究。但是或许有一点不同,框架里面的原理和具体实现,学到了,我们可以学以致用。但普通的工具,或许没有这种价值。

发布了28 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ywg_1994/article/details/103989792