This article mainly explains two kinds of componentization schemes
componentization
Componentalization is actually a way to separate modules, layer modules, and specify the communication mode between modules, so as to achieve decoupling, which is mainly used for team development
Why componentization?
There are four main reasons
-
1. Decoupling between modules
-
2. Module reuse
-
3. Improve the efficiency of team cooperation and development
-
4. Unit testing
When the project is coming due to various requirements, if the various modules at this time are called each other, that is, there is a me in each other, there is a you in each other, this situation will cause high coupling. Once we need to change a piece of code, it will affect the whole project, making it difficult to maintain
Its problems are mainly reflected in the following aspects:
-
1. When you modify a function, you also need to modify the code of other modules, because there are references to this module in other modules. It can be understood that high coupling makes code modification difficult
-
2. The external interface of the module is not clear, and even exposes the private interface that should not be exposed, which takes time and effort to modify. It can be interpreted as an interface disorder caused by an unfixed interface
-
The consequence of highly coupled code is that it can affect the development of other team members and cause code conflicts
-
4. When modules need to be reused to other projects, it is difficult to separate them
-
5. The taboo of coupling between modules leads to the confusion of interfaces and dependencies, which makes unit testing impossible
Therefore, in order to solve the above problems, we need to adopt a more standardized way to reduce the coupling degree between modules, which is componentization, can also be understood as modularization
However, it is important to note that not all projects need to be componentized because componentization is also a cost that takes time to design interfaces, separate code, and so on. You don’t need componentization if your project has the following characteristics:
-
1. Small project, simple interaction between modules and less coupling
-
2. The project is not referenced by multiple external modules, just a single small module
-
Modules do not need to be reused and code is rarely changed
-
4. Small teams
-
5. No need to write unit tests
If you have the following characteristics, you must consider componentization:
-
1. Module logic is complex, and multiple modules frequently reference each other
-
2. As the project scale grows, it becomes more and more difficult to modify the code (here it can be understood as: to modify one code, it is necessary to modify several other places at the same time)
-
3. As the team grows, submitted code often conflicts with other members
-
4. Project compilation takes a long time
-
5. Module unit tests often fail due to changes in other modules
Componentization scheme
Eight indicators of the componentization scheme
How to evaluate a project after componentization, there are mainly the following criteria:
- 1. There is no coupling between modules, and modifications within modules will not be made to other modules
- 2. Modules can be compiled separately
- 3. Clear data transfer between modules
- 4. A module can be replaced at any time by another module that provides the same functionality
- 5. The external interface of the module is clear and easy to maintain
- 6. When the module interface changes, the external code of the module can be efficiently refactored
- 7. Make existing projects modular with as little modification and code as possible
- 8, support OC and Swift, and mixed
The first four are used to measure whether a module is truly decoupled, while the last four are used to measure how easy it is to use in practice in a project
Principle of componentization A project is divided into three layers: the business layer, the general layer, and the basic layer. The following describes the componentization
-
You can only rely on the upper layer, not the lower layer on the upper layer, because the lower layer is an abstraction from the upper layer
-
Project common code resources sink
-
Horizontal dependencies should be as minimal as possible, preferably down to generic modules or base modules
Componentization schemes There are two common componentization schemes:
-
Local componentalization: This is done by creating a library in your project and using Cocoapods workSpec to manage it locally. You don’t need to upload your project to Git, but instead call it directly in your own project as a framework method
-
Cocoapods componentization: You can use Cocoapods to manage your modules remotely by uploading your project to Git.
Local componentization
1. Create the main project
-
Start by creating a project
-
Integrate Cocopods for local management:
$CD Project directory $pod initCopy the code
- Edit the podfile and execute
pod install
2. Create a component
Suppose there are the following modules:
The main project
: hosts the main surface layer business codeCore
: exists independently and applies sensitive codes such as encryption and interface requestBase
: Base class encapsulation, expansion, basic data processingService
: service layer, which encapsulates business tool classes, such as network layer services and persistence servicesPods
: Tripartite dependencies
The relationship between each module is as follows
Next, let’s create a module, taking Core module as an example:
-
Choose New -> Project -> iOS -> Framework to create a new module
-
Select the correct Group and WorkSpace (note that the library you created should be placed in the root of the main project, otherwise pod Install will fail later on in the podfile)
-
Change the library Build Settings -> Mach-O Type to Static library
3. The main project calls library
- Create a new file in CJLCore and add the following code
Public public static let SCRET_KEY = "SCRET_KEY"}Copy the code
-
Add the new file to Public in Build Phases -> Headers -> Public so that the main project can access the file
-
In the main project, select Target -> Linked Frameworks Library to add CJLCore. Just build the main project, and the Library automatically links
4, the use of
First import CJLCore and then use it
It is important to note that the child libraries call each other in the same way that the main project calls library by adding dependencies and exposing headers
Manage third-party dependencies using Cocoapods
Suppose we need to encapsulate network layer code in CJLCore, using the tripartite library Alamofire, in podfile
Platform: ios, '9.0' inhibit_all_warnings! use_frameworks! # configuration workspace path workspace 'Modularization. Xcworkspace' # # # # # # # # # # # # # # # # # # three sides rely on public def workspace_pods pod 'SwiftyJSON' End # Def project_only_Pods pod 'SnapKit' end # network def network_layer_Pods pod 'Alamofire' end ################# module Target 'CJLCore do # project configuration libray path' CJLCore/CJLCore xcodeproj 'workspace_pods network_layer_pods end ################# Main project target 'Modularization' do workspace_PODS project_only_PODS network_layer_PODS Target 'ModularizationTests' do inherit! :search_paths end target 'ModularizationUITests' do end endCopy the code
At this point, a local componentized module is configured
Cocoapods componentization
In addition to local componentization, you can also use Cocoapods, which works as shown below
Again, let’s take local componentization as an example
1. Create a private repository
-
To create a MySpecs repository on Github, do the following: Go to Github and click “+” in the upper right corner. Select New Repository. Enter Repository name as MySpecs, select the repository type as private, and click Create Repository.
-
Add the private repository to the local ~/.cocoapods/repos directory
pod repo add mySpecs https://github.com/xxx/MySpecs.git
Copy the code
2. Create the PODS project, the componentized project
- Using a terminal
CJLServices
The module
pod lib create CJLServices
Copy the code
-
Enter ios, swift, yes, None, no, and CJL as prompted
-
Go to the module directory and copy the file to CJLServices -> Classes
-
Executing Pod Install updates Classes to pods
3. Configure the PODS project
Modify the module’s configuration file, cjLservices.podspec
- If you need to rely on third-party libraries, you need to configure them
s.dependency
s.dependency 'AFNetworking'
Copy the code
- If modules need to reference each other, this configuration is also required
s.dependency
In order toCJLBase
For example, a reference is requiredCJLService
//********2, modify podspec file pod 'CJLServices', :path => '.. /.. /CJLServices'Copy the code
- If you need to load resources, such as images, JSON, bundles, etc
- 1, in the module
Assets
Add resource files to the folder - 2, in
specs
To configure resource path (must be configured!! Otherwise the resource cannot be read. - 3. Specify the path of the resource file
- 1, in the module
//*****1. Modify podspec s.resource_bundles = {'CJLBase' => ['CJLBase/Assets/*']} //***** String = Bundle.init(for: dynamicClass.self).resourcePath! + "/CJLBase.bundle" let bundle = Bundle(path: bundlePath) if let path = bundle? .path(forResource: "mouse", ofType: "jpg"){ self.imgView.image = UIImage(contentsOfFile: path) }Copy the code
Similarly, the xiB and JSON files in the module are obtained in the same way
4. Commit to Git
The module submitted to Git must be the PODS project. Take CJLBase as an example
-
You need to create a private repository on Github called CJLBase
-
Run the following terminal command
$git init $git add. $git commit -am $git remote add origin https://github.com/xxx/CJLBase.git $git push origin master / / must have labels, or you will have the following warning / / podspec file access to the git version control projects need the tag number, $git tag -m "first release" "0.1.0Copy the code
5. Verify the PodSpec file
Run the terminal command pod spec lint
Note: Pod Specs are more accurate than pod Lib,
pod lib
It’s equivalent to verifying only one local repository,pod spec
Both local and remote repositories are validated.
6. Commit to a private repository
Execute the following command
Pod repo push [local Spec repo name][Podspec file path] //****** Example $pod repo push MySpecs CJLBase. PodspecCopy the code
After a successful commit, you can see the commit path MySpecs -> CJLBase in the local repository
7, use,
- Create a new project and add it to the project’s podfile
Private spec # warehouse address, rather than a single pod warehouse address source 'https://github.com/xxx/MySpecs' pod' CJLBase 'Copy the code
- perform
pod install
Can be
Refer to the link
- Building a complete iOS componentization solution: How to decouple modules for interfaces
- [Swift based modular development practice scheme](