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:

  1. Class sinking
  • Move the concrete class to the appropriate Lib module

  • Add a dependency on the Lib in the calling module

  1. The interface extraction
  • Create an empty one in the appropriate common moduleinterface
  • The jump code block that calls the concrete page class is created in the packageThe implementation classTo implement thisinterface
  • (automatically) willCall blockExtract 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 belongsThe implementation classtheMember variablesAs adelegate

The Inject interface needs to be reserved. It is recommended to use Constructor Inject, and the static member provides the setter

  • (automatically) willThe new methodCall transfer todelegateIn 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 tointerfaceIn the
  • (automatically) willThe implementation classMove to the shell
  • Implemented in a shell programThe implementation classThe Inject
  1. 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.

  1. 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

  1. 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