去除冗余插件代码,重构开源项目
2023-12-22 16:20:21
身为一名合格的开源项目贡献者,为开源项目添加新功能是常见的情况,我们都曾遇到过这种问题。这很好,但此时我们往往会发现,项目的代码没有使用任何的设计模式,也没有用适当的方法组织好代码,全部功能都写在一起,对于我们新功能的添加来说非常糟糕。为了解决这个问题,我们需要重构一下项目代码。
我们以RemoveButterKnife为例,近期我们想给这个开源项目加入一些新的功能,经过一番调查,我们发现以前的代码没有使用任何的设计模式,全部功能都写在一起。这对于我们新功能的添加来说十分糟糕。趁此机会,我重构了一下代码,在此记录过程。
首先,是主插件入口部分。项目最开始的代码直接定义了一个名为RemoveButterKnifePlugin.java的文件,所有的代码都写在这个文件里。对于后续的新功能的添加来说,很不方便。这里采用模块化的设计,把它变成插件的主入口,具体实现的工作,通过主入口来调用相应的模块。另外,初始化工作也应该放进插件的入口,方便统一管理。
其次,是代码寻找/处理部分。我们原先是用递归的方式来寻找ButterKnife代码,实际上这是很不方便的,对于Android Studio这样的大项目来说,递归会很耗时,实际项目使用中可能会耗费超过一分钟的时间。通过仔细地分析代码,我们发现,实际上,我们只需要寻找顶层的ButterKnife代码,然后逐个转化即可。这样的话,速度就会快很多。但原来的代码就是这个样子:
/**
* Finds the elements annotated with ButterKnife inside the specified project.
*
* @param project
* @param progressListener
*/
public static void findFieldsAnnotatedWithButterKnife(Project project, ProgressListener progressListener) {
Log.v(TAG, "Starting to find fields annotated with ButterKnife.");
AndroidProject androidProject = AndroidProject.getInstance(project);
Collection<JavaSourceDirectory> javaSourceDirectories = androidProject.getJavaDirectories();
Map<File, JavaDirectory> processedDirs = new HashMap<>();
for (JavaSourceDirectory directory : javaSourceDirectories) {
// Ignore the /gen folder
if (directory.getName().equals("gen")) {
continue;
}
processJavaDirectory(directory, progressListener, processedDirs);
}
}
在项目重构前,我们是按照这个顺序来寻找和处理ButterKnife代码的:1-按顺序遍历项目的所有代码文件;2-对每个文件,检查是否含有ButterKnife注解;3-如果有,就移除ButterKnife注解;4-将移除注解后的文件保存起来。
在重构过程中,我们发现,这个顺序可以优化。我们可以先对代码文件进行预处理,将所有含有ButterKnife注解的文件挑出来,然后再对它们进行统一处理。这样就可以避免对没有ButterKnife注解的文件进行不必要的扫描,从而提高效率。
重构后的代码如下:
/**
* Finds the elements annotated with ButterKnife inside the specified project.
*
* @param project
* @param progressListener
*/
public static void findFieldsAnnotatedWithButterKnife(Project project, ProgressListener progressListener) {
Log.v(TAG, "Starting to find fields annotated with ButterKnife.");
AndroidProject androidProject = AndroidProject.getInstance(project);
Collection<JavaSourceDirectory> javaSourceDirectories = androidProject.getJavaDirectories();
Map<File, JavaDirectory> processedDirs = new HashMap<>();
List<File> javaFilesToProcess = new ArrayList<>();
for (JavaSourceDirectory directory : javaSourceDirectories) {
// Ignore the /gen folder
if (directory.getName().equals("gen")) {
continue;
}
collectJavaFilesToProcess(directory, javaFilesToProcess);
}
processJavaFiles(javaFilesToProcess, progressListener, processedDirs);
}
以上介绍了在RemoveButterKnife插件中进行重构的过程。我希望这个例子能够帮助大家理解重构的思想和方法。在实际项目中,我们可以根据不同的情况采用不同的重构方法。但有一点是肯定的:重构可以帮助我们提高代码的可读性、可维护性和可扩展性。