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 executepod install

2. Create a component

Suppose there are the following modules:

  • The main project: hosts the main surface layer business code
  • Core: exists independently and applies sensitive codes such as encryption and interface request
  • Base: Base class encapsulation, expansion, basic data processing
  • Service: service layer, which encapsulates business tool classes, such as network layer services and persistence services
  • Pods: 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 terminalCJLServicesThe 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 thems.dependency
s.dependency 'AFNetworking'

Copy the code
  • If modules need to reference each other, this configuration is also requireds.dependencyIn order toCJLBaseFor 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 moduleAssetsAdd resource files to the folder
    • 2, inspecsTo configure resource path (must be configured!! Otherwise the resource cannot be read.
    • 3. Specify the path of the resource file
//*****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 libIt’s equivalent to verifying only one local repository,
  • pod specBoth 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
  • performpod installCan be

Refer to the link

  • Building a complete iOS componentization solution: How to decouple modules for interfaces
  • [Swift based modular development practice scheme](