preface
According to CloudDisk’s future architecture, we use ArchUnit to run the architecture test daemon and Intellij’s Dependendencies to analyze the abnormal dependencies that need to be solved according to the future architecture design.
We’ll begin this article by sharing the refactoring process, methods, and common tool use for dependency removal.
The refactoring process
Graph TD 1. Identify a cohesive package -->2. Remove abnormal dependencies on the package 2. Remove abnormal dependencies on this package -->3. Move code and resources corresponding to this package to the new module 3. Move the code and resources corresponding to the package to the new module ->4. Acceptance of package decoupling
1. Identify cohesive packages
For mobile applications, we can usually identify the domain by business division of the product. For example, CloudDisk is relatively clear, and its business is mainly divided into file, dynamic and personal center.
For some legacy systems, old code may be scattered under different packages, or the original code may be organized by functional divisions rather than business divisions. Just like the CloudDisk code, the first step is to organize the related business code into the same package. At this stage, we can ignore whether there are abnormal dependencies, because only by organizing it into a cohesive package can we facilitate the dependency analysis and code refactoring.
2. Remove the abnormal dependency
Here we will introduce several common dependency relief techniques. Include sinking, interface extraction, and route hop.
The following demonstration will be done by video
Dependency relief technique | Usage scenarios |
---|---|
sinking | Class functions that belong to the Library or Platform are directly subtracted. Examples are LogUtil or DateUtil |
The interface extraction | Applies when bundles have data or behavior dependencies. For example, classA in a BundleA needs to trigger a business behavior in a BundleB |
Routing hop | Applicable to switching between UI pages. For example, if you have Activity1 in BundleA, you need to jump to Activity2 in BundleB |
Reconstruction techniques:
- Class sinking
-
Move the concrete class to the appropriate Lib module
-
Add a dependency on the Lib in the calling module
- The interface extraction
- Create an empty one in the appropriate common module
interface
- The jump code block that calls the concrete page class is created in the package
The implementation class
To implement thisinterface
- (automatically) will
Call block
Extract by Extract methodThe new method
Skip this step if it is already an independent method
- Added (automatically) to the class to which the original calling logic belongs
The implementation class
theMember variables
As adelegate
The Inject interface needs to be reserved. It is recommended to use Constructor Inject, and the static member provides the setter
- (automatically) will
The new method
Call transfer todelegate
In the
If the Method is static, pass the delegate as a parameter to the Method using Change Method Signature
- Automatically Pull up a new method to
interface
In the - (automatically) will
The implementation class
Move to the shell - Implemented in a shell program
The implementation class
The Inject
- Routing hop
- Define the mapping Path in the jump class
- Jump with the corresponding PATH at the point of the call
3. Mobile code and resources
When the exception dependencies of the package are fully decoupled, you can move directly. Here we share the common code movement methods in 2.
- Move
Select a File or Directory, press F6 to select the Directory you want to move.
However, there is a problem with this approach. If the moved class depends on another class or resource, the moved class will cause a dependency exception.
Application scenario: The moved File or Directory has no other dependencies
- Modularize
Modularize can analyze the relevant dependencies of the moved File and associate the Move together, which can solve the pain points of Move very well and is very suitable for cross-module movement.
Select the Module to move and click Preview.
Note here that there are some underlined files, because this file is referenced in multiple places at the same time, and if you move it along, the other places will report an error. So we need to move the underlined file to a suitable public location first. When Preview does not have any files underlined, you can move them.
4. Package decoupling acceptance
- All modules are compiled
- All new modules comply with the module dependency rule
- Pass the architecture guardian test
conclusion
In this article, we share the refactoring process for dependency relief, which consists of four steps: identifying cohesion packages, dependency relief, moving, and acceptance. It also introduces the Modularize function which is very useful in Intellij. Then we can start to refactor the code, but at this point we are faced with another problem, which is a lot of students often worry about when doing refactoring. How to ensure that functions are correct and new problems are not modified during refactoring?
In the next part of mobile Application Legacy System Refactoring (6) – Test, we will share how to develop test strategies and effectively supplement automated testing for individual mobile application legacy systems, so as to better escort the refactoring.
Series of links
Refactoring legacy Systems for mobile Applications (1) – Start
Refactoring legacy systems for mobile applications (2) – Architecture
Refactoring legacy systems for mobile applications (3) – Examples
Refactoring legacy Systems in Mobile Applications (4) – Analysis
The outline
about
Welcome to the CAC Agile Coach public account. Wechat search: CAC Agile Coach.
- Author: Huang Junbin
- Blog: junbin. Tech
- GitHub: junbin1011
- Zhihu: @ JunBin